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>
52ddde725dSArmin Le Grand 
53ddde725dSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
54ddde725dSArmin Le Grand 
55ddde725dSArmin Le Grand using namespace com::sun::star;
56ddde725dSArmin Le Grand 
57ddde725dSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
58ddde725dSArmin Le Grand 
59ddde725dSArmin Le Grand namespace
60ddde725dSArmin Le Grand {
61ddde725dSArmin Le Grand     svgio::svgreader::SvgCharacterNode* whiteSpaceHandling(svgio::svgreader::SvgNode* pNode, svgio::svgreader::SvgCharacterNode* pLast)
62ddde725dSArmin Le Grand     {
63ddde725dSArmin Le Grand         if(pNode)
64ddde725dSArmin Le Grand         {
65ddde725dSArmin Le Grand             const svgio::svgreader::SvgNodeVector& rChilds = pNode->getChildren();
66ddde725dSArmin Le Grand             const sal_uInt32 nCount(rChilds.size());
67ddde725dSArmin Le Grand 
68ddde725dSArmin Le Grand             for(sal_uInt32 a(0); a < nCount; a++)
69ddde725dSArmin Le Grand             {
70ddde725dSArmin Le Grand                 svgio::svgreader::SvgNode* pCandidate = rChilds[a];
71ddde725dSArmin Le Grand 
72ddde725dSArmin Le Grand                 if(pCandidate)
73ddde725dSArmin Le Grand                 {
74ddde725dSArmin Le Grand                     switch(pCandidate->getType())
75ddde725dSArmin Le Grand                     {
76ddde725dSArmin Le Grand                         case svgio::svgreader::SVGTokenCharacter:
77ddde725dSArmin Le Grand                         {
78ddde725dSArmin Le Grand                             // clean whitespace in text span
79ddde725dSArmin Le Grand                             svgio::svgreader::SvgCharacterNode* pCharNode = static_cast< svgio::svgreader::SvgCharacterNode* >(pCandidate);
80ddde725dSArmin Le Grand                             pCharNode->whiteSpaceHandling();
81ddde725dSArmin Le Grand 
82ddde725dSArmin Le Grand                             // pCharNode may have lost all text. If that's the case, ignore
83ddde725dSArmin Le Grand                             // as invalid character node
84ddde725dSArmin Le Grand                             if(pCharNode->getText().getLength())
85ddde725dSArmin Le Grand                             {
86ddde725dSArmin Le Grand                                 if(pLast)
87ddde725dSArmin Le Grand                                 {
88ddde725dSArmin Le Grand                                     // add in-between whitespace (single space) to last
89ddde725dSArmin Le Grand                                     // known character node
90ddde725dSArmin Le Grand                                     pLast->addGap();
91ddde725dSArmin Le Grand                                 }
92ddde725dSArmin Le Grand 
93ddde725dSArmin Le Grand                                 // remember new last corected character node
94ddde725dSArmin Le Grand                                 pLast = pCharNode;
95ddde725dSArmin Le Grand                             }
96ddde725dSArmin Le Grand                             break;
97ddde725dSArmin Le Grand                         }
98ddde725dSArmin Le Grand                         case svgio::svgreader::SVGTokenTspan:
99ddde725dSArmin Le Grand                         case svgio::svgreader::SVGTokenTextPath:
100ddde725dSArmin Le Grand                         case svgio::svgreader::SVGTokenTref:
101ddde725dSArmin Le Grand                         {
102ddde725dSArmin Le Grand                             // recursively clean whitespaces in subhierarchy
103ddde725dSArmin Le Grand                             pLast = whiteSpaceHandling(pCandidate, pLast);
104ddde725dSArmin Le Grand                             break;
105ddde725dSArmin Le Grand                         }
106ddde725dSArmin Le Grand                         default:
107ddde725dSArmin Le Grand                         {
108ddde725dSArmin Le Grand                             OSL_ENSURE(false, "Unexpected token inside SVGTokenText (!)");
109ddde725dSArmin Le Grand                             break;
110ddde725dSArmin Le Grand                         }
111ddde725dSArmin Le Grand                     }
112ddde725dSArmin Le Grand                 }
113ddde725dSArmin Le Grand             }
114ddde725dSArmin Le Grand         }
115ddde725dSArmin Le Grand 
116ddde725dSArmin Le Grand         return pLast;
117ddde725dSArmin Le Grand     }
118ddde725dSArmin Le Grand }
119ddde725dSArmin Le Grand 
120ddde725dSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
121ddde725dSArmin Le Grand 
122ddde725dSArmin Le Grand namespace svgio
123ddde725dSArmin Le Grand {
124ddde725dSArmin Le Grand     namespace svgreader
125ddde725dSArmin Le Grand     {
126ddde725dSArmin Le Grand         SvgDocHdl::SvgDocHdl(const rtl::OUString& aAbsolutePath)
127ddde725dSArmin Le Grand         :   maDocument(aAbsolutePath),
128*3aaca8a3SArmin Le Grand             mpTarget(0),
129*3aaca8a3SArmin Le Grand             maCssContents()
130ddde725dSArmin Le Grand         {
131ddde725dSArmin Le Grand         }
132ddde725dSArmin Le Grand 
133ddde725dSArmin Le Grand         SvgDocHdl::~SvgDocHdl()
134ddde725dSArmin Le Grand         {
135ddde725dSArmin Le Grand #ifdef DBG_UTIL
136ddde725dSArmin Le Grand             if(mpTarget)
137ddde725dSArmin Le Grand             {
138ddde725dSArmin Le Grand                 OSL_ENSURE(false, "SvgDocHdl destructed with active target (!)");
139ddde725dSArmin Le Grand                 delete mpTarget;
140ddde725dSArmin Le Grand             }
141*3aaca8a3SArmin Le Grand             OSL_ENSURE(!maCssContents.size(), "SvgDocHdl destructed with active css style stack entry (!)");
142ddde725dSArmin Le Grand #endif
143ddde725dSArmin Le Grand         }
144ddde725dSArmin Le Grand 
145ddde725dSArmin Le Grand         void SvgDocHdl::startDocument(  ) throw (xml::sax::SAXException, uno::RuntimeException)
146ddde725dSArmin Le Grand         {
147ddde725dSArmin Le Grand             OSL_ENSURE(!mpTarget, "Already a target at document start (!)");
148*3aaca8a3SArmin Le Grand             OSL_ENSURE(!maCssContents.size(), "SvgDocHdl startDocument with active css style stack entry (!)");
149ddde725dSArmin Le Grand         }
150ddde725dSArmin Le Grand 
151ddde725dSArmin Le Grand         void SvgDocHdl::endDocument(  ) throw (xml::sax::SAXException, uno::RuntimeException)
152ddde725dSArmin Le Grand         {
153ddde725dSArmin Le Grand             OSL_ENSURE(!mpTarget, "Still a target at document end (!)");
154*3aaca8a3SArmin Le Grand             OSL_ENSURE(!maCssContents.size(), "SvgDocHdl endDocument with active css style stack entry (!)");
155ddde725dSArmin Le Grand         }
156ddde725dSArmin Le Grand 
157ddde725dSArmin Le Grand         void SvgDocHdl::startElement( const ::rtl::OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs ) throw (xml::sax::SAXException, uno::RuntimeException)
158ddde725dSArmin Le Grand         {
159ddde725dSArmin Le Grand             if(aName.getLength())
160ddde725dSArmin Le Grand             {
161ddde725dSArmin Le Grand                 const SVGToken aSVGToken(StrToSVGToken(aName));
162ddde725dSArmin Le Grand 
163ddde725dSArmin Le Grand                 switch(aSVGToken)
164ddde725dSArmin Le Grand                 {
165ddde725dSArmin Le Grand                     /// structural elements
166ddde725dSArmin Le Grand                     case SVGTokenSymbol:
167ddde725dSArmin Le Grand                     {
168ddde725dSArmin Le Grand                         /// new basic node for Symbol. Content gets scanned, but
169ddde725dSArmin Le Grand                         /// will not be decomposed (see SvgNode::decomposeSvgNode and bReferenced)
170ddde725dSArmin Le Grand                         mpTarget = new SvgSymbolNode(maDocument, mpTarget);
171ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
172ddde725dSArmin Le Grand                         break;
173ddde725dSArmin Le Grand                     }
174ddde725dSArmin Le Grand                     case SVGTokenDefs:
175ddde725dSArmin Le Grand                     case SVGTokenG:
176ddde725dSArmin Le Grand                     {
177ddde725dSArmin Le Grand                         /// new node for Defs/G
178ddde725dSArmin Le Grand                         mpTarget = new SvgGNode(aSVGToken, maDocument, mpTarget);
179ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
180ddde725dSArmin Le Grand                         break;
181ddde725dSArmin Le Grand                     }
182ddde725dSArmin Le Grand                     case SVGTokenSvg:
183ddde725dSArmin Le Grand                     {
184ddde725dSArmin Le Grand                         /// new node for Svg
185ddde725dSArmin Le Grand                         mpTarget = new SvgSvgNode(maDocument, mpTarget);
186ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
187ddde725dSArmin Le Grand                         break;
188ddde725dSArmin Le Grand                     }
189ddde725dSArmin Le Grand                     case SVGTokenUse:
190ddde725dSArmin Le Grand                     {
191ddde725dSArmin Le Grand                         /// new node for Use
192ddde725dSArmin Le Grand                         mpTarget = new SvgUseNode(maDocument, mpTarget);
193ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
194ddde725dSArmin Le Grand                         break;
195ddde725dSArmin Le Grand                     }
196ddde725dSArmin Le Grand 
197ddde725dSArmin Le Grand                     /// shape elements
198ddde725dSArmin Le Grand                     case SVGTokenCircle:
199ddde725dSArmin Le Grand                     {
200ddde725dSArmin Le Grand                         /// new node for Circle
201ddde725dSArmin Le Grand                         mpTarget = new SvgCircleNode(maDocument, mpTarget);
202ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
203ddde725dSArmin Le Grand                         break;
204ddde725dSArmin Le Grand                     }
205ddde725dSArmin Le Grand                     case SVGTokenEllipse:
206ddde725dSArmin Le Grand                     {
207ddde725dSArmin Le Grand                         /// new node for Ellipse
208ddde725dSArmin Le Grand                         mpTarget = new SvgEllipseNode(maDocument, mpTarget);
209ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
210ddde725dSArmin Le Grand                         break;
211ddde725dSArmin Le Grand                     }
212ddde725dSArmin Le Grand                     case SVGTokenLine:
213ddde725dSArmin Le Grand                     {
214ddde725dSArmin Le Grand                         /// new node for Line
215ddde725dSArmin Le Grand                         mpTarget = new SvgLineNode(maDocument, mpTarget);
216ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
217ddde725dSArmin Le Grand                         break;
218ddde725dSArmin Le Grand                     }
219ddde725dSArmin Le Grand                     case SVGTokenPath:
220ddde725dSArmin Le Grand                     {
221ddde725dSArmin Le Grand                         /// new node for Path
222ddde725dSArmin Le Grand                         mpTarget = new SvgPathNode(maDocument, mpTarget);
223ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
224ddde725dSArmin Le Grand                         break;
225ddde725dSArmin Le Grand                     }
226ddde725dSArmin Le Grand                     case SVGTokenPolygon:
227ddde725dSArmin Le Grand                     {
228ddde725dSArmin Le Grand                         /// new node for Polygon
229ddde725dSArmin Le Grand                         mpTarget = new SvgPolyNode(maDocument, mpTarget, false);
230ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
231ddde725dSArmin Le Grand                         break;
232ddde725dSArmin Le Grand                     }
233ddde725dSArmin Le Grand                     case SVGTokenPolyline:
234ddde725dSArmin Le Grand                     {
235ddde725dSArmin Le Grand                         /// new node for Polyline
236ddde725dSArmin Le Grand                         mpTarget = new SvgPolyNode(maDocument, mpTarget, true);
237ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
238ddde725dSArmin Le Grand                         break;
239ddde725dSArmin Le Grand                     }
240ddde725dSArmin Le Grand                     case SVGTokenRect:
241ddde725dSArmin Le Grand                     {
242ddde725dSArmin Le Grand                         /// new node for Rect
243ddde725dSArmin Le Grand                         mpTarget = new SvgRectNode(maDocument, mpTarget);
244ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
245ddde725dSArmin Le Grand                         break;
246ddde725dSArmin Le Grand                     }
247ddde725dSArmin Le Grand                     case SVGTokenImage:
248ddde725dSArmin Le Grand                     {
249ddde725dSArmin Le Grand                         /// new node for Image
250ddde725dSArmin Le Grand                         mpTarget = new SvgImageNode(maDocument, mpTarget);
251ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
252ddde725dSArmin Le Grand                         break;
253ddde725dSArmin Le Grand                     }
254ddde725dSArmin Le Grand 
255ddde725dSArmin Le Grand                     /// gradients
256ddde725dSArmin Le Grand                     case SVGTokenLinearGradient:
257ddde725dSArmin Le Grand                     case SVGTokenRadialGradient:
258ddde725dSArmin Le Grand                     {
259ddde725dSArmin Le Grand                         mpTarget = new SvgGradientNode(aSVGToken, maDocument, mpTarget);
260ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
261ddde725dSArmin Le Grand                         break;
262ddde725dSArmin Le Grand                     }
263ddde725dSArmin Le Grand 
264ddde725dSArmin Le Grand                     /// gradient stops
265ddde725dSArmin Le Grand                     case SVGTokenStop:
266ddde725dSArmin Le Grand                     {
267ddde725dSArmin Le Grand                         mpTarget = new SvgGradientStopNode(maDocument, mpTarget);
268ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
269ddde725dSArmin Le Grand                         break;
270ddde725dSArmin Le Grand                     }
271ddde725dSArmin Le Grand 
272ddde725dSArmin Le Grand                     /// text
273ddde725dSArmin Le Grand                     case SVGTokenText:
274ddde725dSArmin Le Grand                     {
275ddde725dSArmin Le Grand                         mpTarget = new SvgTextNode(maDocument, mpTarget);
276ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
277ddde725dSArmin Le Grand                         break;
278ddde725dSArmin Le Grand                     }
279ddde725dSArmin Le Grand                     case SVGTokenTspan:
280ddde725dSArmin Le Grand                     {
281ddde725dSArmin Le Grand                         mpTarget = new SvgTspanNode(maDocument, mpTarget);
282ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
283ddde725dSArmin Le Grand                         break;
284ddde725dSArmin Le Grand                     }
285ddde725dSArmin Le Grand                     case SVGTokenTref:
286ddde725dSArmin Le Grand                     {
287ddde725dSArmin Le Grand                         mpTarget = new SvgTrefNode(maDocument, mpTarget);
288ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
289ddde725dSArmin Le Grand                         break;
290ddde725dSArmin Le Grand                     }
291ddde725dSArmin Le Grand                     case SVGTokenTextPath:
292ddde725dSArmin Le Grand                     {
293ddde725dSArmin Le Grand                         mpTarget = new SvgTextPathNode(maDocument, mpTarget);
294ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
295ddde725dSArmin Le Grand                         break;
296ddde725dSArmin Le Grand                     }
297ddde725dSArmin Le Grand 
298ddde725dSArmin Le Grand                     /// styles (as stylesheets)
299ddde725dSArmin Le Grand                     case SVGTokenStyle:
300ddde725dSArmin Le Grand                     {
301*3aaca8a3SArmin Le Grand                         SvgStyleNode* pNew = new SvgStyleNode(maDocument, mpTarget);
302*3aaca8a3SArmin Le Grand                         mpTarget = pNew;
303ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
304*3aaca8a3SArmin Le Grand 
305*3aaca8a3SArmin Le Grand                         if(pNew->isTextCss())
306*3aaca8a3SArmin Le Grand                         {
307*3aaca8a3SArmin Le Grand                             maCssContents.push_back(rtl::OUString());
308*3aaca8a3SArmin Le Grand                         }
309ddde725dSArmin Le Grand                         break;
310ddde725dSArmin Le Grand                     }
311ddde725dSArmin Le Grand 
312ddde725dSArmin Le Grand                     /// structural elements clip-path and mask. Content gets scanned, but
313ddde725dSArmin Le Grand                     /// will not be decomposed (see SvgNode::decomposeSvgNode and bReferenced)
314ddde725dSArmin Le Grand                     case SVGTokenClipPathNode:
315ddde725dSArmin Le Grand                     {
316ddde725dSArmin Le Grand                         /// new node for ClipPath
317ddde725dSArmin Le Grand                         mpTarget = new SvgClipPathNode(maDocument, mpTarget);
318ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
319ddde725dSArmin Le Grand                         break;
320ddde725dSArmin Le Grand                     }
321ddde725dSArmin Le Grand                     case SVGTokenMask:
322ddde725dSArmin Le Grand                     {
323ddde725dSArmin Le Grand                         /// new node for Mask
324ddde725dSArmin Le Grand                         mpTarget = new SvgMaskNode(maDocument, mpTarget);
325ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
326ddde725dSArmin Le Grand                         break;
327ddde725dSArmin Le Grand                     }
328ddde725dSArmin Le Grand 
329ddde725dSArmin Le Grand                     /// structural element marker
330ddde725dSArmin Le Grand                     case SVGTokenMarker:
331ddde725dSArmin Le Grand                     {
332ddde725dSArmin Le Grand                         /// new node for marker
333ddde725dSArmin Le Grand                         mpTarget = new SvgMarkerNode(maDocument, mpTarget);
334ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
335ddde725dSArmin Le Grand                         break;
336ddde725dSArmin Le Grand                     }
337ddde725dSArmin Le Grand 
338ddde725dSArmin Le Grand                     /// structural element pattern
339ddde725dSArmin Le Grand                     case SVGTokenPattern:
340ddde725dSArmin Le Grand                     {
341ddde725dSArmin Le Grand                         /// new node for pattern
342ddde725dSArmin Le Grand                         mpTarget = new SvgPatternNode(maDocument, mpTarget);
343ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
344ddde725dSArmin Le Grand                         break;
345ddde725dSArmin Le Grand                     }
346ddde725dSArmin Le Grand 
347ddde725dSArmin Le Grand                     default:
348ddde725dSArmin Le Grand                     {
349ddde725dSArmin Le Grand                         /// invalid token, ignore
350ddde725dSArmin Le Grand #ifdef DBG_UTIL
351ddde725dSArmin Le Grand                         myAssert(
352ddde725dSArmin Le Grand                             rtl::OUString::createFromAscii("Unknown Base SvgToken <") +
353ddde725dSArmin Le Grand                             aName +
354ddde725dSArmin Le Grand                             rtl::OUString::createFromAscii("> (!)"));
355ddde725dSArmin Le Grand #endif
356ddde725dSArmin Le Grand                         break;
357ddde725dSArmin Le Grand                     }
358ddde725dSArmin Le Grand                 }
359ddde725dSArmin Le Grand             }
360ddde725dSArmin Le Grand         }
361ddde725dSArmin Le Grand 
362ddde725dSArmin Le Grand         void SvgDocHdl::endElement( const ::rtl::OUString& aName ) throw (xml::sax::SAXException, uno::RuntimeException)
363ddde725dSArmin Le Grand         {
364ddde725dSArmin Le Grand             if(aName.getLength())
365ddde725dSArmin Le Grand             {
366ddde725dSArmin Le Grand                 const SVGToken aSVGToken(StrToSVGToken(aName));
367ddde725dSArmin Le Grand                 SvgNode* pWhitespaceCheck(SVGTokenText == aSVGToken ? mpTarget : 0);
368*3aaca8a3SArmin Le Grand                 SvgStyleNode* pCssStyle(SVGTokenStyle == aSVGToken ? static_cast< SvgStyleNode* >(mpTarget) : 0);
369ddde725dSArmin Le Grand 
370ddde725dSArmin Le Grand                 switch(aSVGToken)
371ddde725dSArmin Le Grand                 {
372ddde725dSArmin Le Grand                     /// valid tokens for which a new one was created
373ddde725dSArmin Le Grand 
374ddde725dSArmin Le Grand                     /// structural elements
375ddde725dSArmin Le Grand                     case SVGTokenDefs:
376ddde725dSArmin Le Grand                     case SVGTokenG:
377ddde725dSArmin Le Grand                     case SVGTokenSvg:
378ddde725dSArmin Le Grand                     case SVGTokenSymbol:
379ddde725dSArmin Le Grand                     case SVGTokenUse:
380ddde725dSArmin Le Grand 
381ddde725dSArmin Le Grand                     /// shape elements
382ddde725dSArmin Le Grand                     case SVGTokenCircle:
383ddde725dSArmin Le Grand                     case SVGTokenEllipse:
384ddde725dSArmin Le Grand                     case SVGTokenLine:
385ddde725dSArmin Le Grand                     case SVGTokenPath:
386ddde725dSArmin Le Grand                     case SVGTokenPolygon:
387ddde725dSArmin Le Grand                     case SVGTokenPolyline:
388ddde725dSArmin Le Grand                     case SVGTokenRect:
389ddde725dSArmin Le Grand                     case SVGTokenImage:
390ddde725dSArmin Le Grand 
391ddde725dSArmin Le Grand                     /// gradients
392ddde725dSArmin Le Grand                     case SVGTokenLinearGradient:
393ddde725dSArmin Le Grand                     case SVGTokenRadialGradient:
394ddde725dSArmin Le Grand 
395ddde725dSArmin Le Grand                     /// gradient stops
396ddde725dSArmin Le Grand                     case SVGTokenStop:
397ddde725dSArmin Le Grand 
398ddde725dSArmin Le Grand                     /// text
399ddde725dSArmin Le Grand                     case SVGTokenText:
400ddde725dSArmin Le Grand                     case SVGTokenTspan:
401ddde725dSArmin Le Grand                     case SVGTokenTextPath:
402ddde725dSArmin Le Grand                     case SVGTokenTref:
403ddde725dSArmin Le Grand 
404ddde725dSArmin Le Grand                     /// styles (as stylesheets)
405ddde725dSArmin Le Grand                     case SVGTokenStyle:
406ddde725dSArmin Le Grand 
407ddde725dSArmin Le Grand                     /// structural elements clip-path and mask
408ddde725dSArmin Le Grand                     case SVGTokenClipPathNode:
409ddde725dSArmin Le Grand                     case SVGTokenMask:
410ddde725dSArmin Le Grand 
411ddde725dSArmin Le Grand                     /// structural element marker
412ddde725dSArmin Le Grand                     case SVGTokenMarker:
413ddde725dSArmin Le Grand 
414ddde725dSArmin Le Grand                     /// structural element pattern
415ddde725dSArmin Le Grand                     case SVGTokenPattern:
416ddde725dSArmin Le Grand 
417ddde725dSArmin Le Grand                     /// content handling after parsing
418ddde725dSArmin Le Grand                     {
419ddde725dSArmin Le Grand                         if(mpTarget)
420ddde725dSArmin Le Grand                         {
421ddde725dSArmin Le Grand                             if(!mpTarget->getParent())
422ddde725dSArmin Le Grand                             {
423ddde725dSArmin Le Grand                                 // last element closing, save this tree
424ddde725dSArmin Le Grand                                 maDocument.appendNode(mpTarget);
425ddde725dSArmin Le Grand                             }
426ddde725dSArmin Le Grand 
427ddde725dSArmin Le Grand                             mpTarget = const_cast< SvgNode* >(mpTarget->getParent());
428ddde725dSArmin Le Grand                         }
429ddde725dSArmin Le Grand                         else
430ddde725dSArmin Le Grand                         {
431ddde725dSArmin Le Grand                             OSL_ENSURE(false, "Closing token, but no context (!)");
432ddde725dSArmin Le Grand                         }
433ddde725dSArmin Le Grand                         break;
434ddde725dSArmin Le Grand                     }
435ddde725dSArmin Le Grand                     default:
436ddde725dSArmin Le Grand                     {
437ddde725dSArmin Le Grand                         /// invalid token, ignore
438ddde725dSArmin Le Grand                     }
439ddde725dSArmin Le Grand                 }
440ddde725dSArmin Le Grand 
441*3aaca8a3SArmin Le Grand                 if(pCssStyle && pCssStyle->isTextCss())
442*3aaca8a3SArmin Le Grand                 {
443*3aaca8a3SArmin Le Grand                     // css style parsing
444*3aaca8a3SArmin Le Grand                     if(maCssContents.size())
445*3aaca8a3SArmin Le Grand                     {
446*3aaca8a3SArmin Le Grand                         // need to interpret css styles and remember them as StyleSheets
447*3aaca8a3SArmin Le Grand                         pCssStyle->addCssStyleSheet(*(maCssContents.end() - 1));
448*3aaca8a3SArmin Le Grand                         maCssContents.pop_back();
449*3aaca8a3SArmin Le Grand                     }
450*3aaca8a3SArmin Le Grand                     else
451*3aaca8a3SArmin Le Grand                     {
452*3aaca8a3SArmin Le Grand                         OSL_ENSURE(false, "Closing CssStyle, but no collector string on stack (!)");
453*3aaca8a3SArmin Le Grand                     }
454*3aaca8a3SArmin Le Grand                 }
455*3aaca8a3SArmin Le Grand 
456ddde725dSArmin Le Grand                 if(pWhitespaceCheck)
457ddde725dSArmin Le Grand                 {
458ddde725dSArmin Le Grand                     // cleanup read strings
459ddde725dSArmin Le Grand                     whiteSpaceHandling(pWhitespaceCheck, 0);
460ddde725dSArmin Le Grand                 }
461ddde725dSArmin Le Grand             }
462ddde725dSArmin Le Grand         }
463ddde725dSArmin Le Grand 
464ddde725dSArmin Le Grand         void SvgDocHdl::characters( const ::rtl::OUString& aChars ) throw (xml::sax::SAXException, uno::RuntimeException)
465ddde725dSArmin Le Grand         {
466ddde725dSArmin Le Grand             if(mpTarget)
467ddde725dSArmin Le Grand             {
468ddde725dSArmin Le Grand                 const sal_uInt32 nLength(aChars.getLength());
469ddde725dSArmin Le Grand 
470ddde725dSArmin Le Grand                 if(nLength &&
471ddde725dSArmin Le Grand                     (SVGTokenText == mpTarget->getType() ||
472ddde725dSArmin Le Grand                     SVGTokenTspan == mpTarget->getType() ||
473ddde725dSArmin Le Grand                     SVGTokenTextPath == mpTarget->getType() ||
474ddde725dSArmin Le Grand                     SVGTokenStyle == mpTarget->getType()))
475ddde725dSArmin Le Grand                 {
476ddde725dSArmin Le Grand                     switch(mpTarget->getType())
477ddde725dSArmin Le Grand                     {
478ddde725dSArmin Le Grand                         case SVGTokenText:
479ddde725dSArmin Le Grand                         case SVGTokenTspan:
480ddde725dSArmin Le Grand                         case SVGTokenTextPath:
481ddde725dSArmin Le Grand                         {
482ddde725dSArmin Le Grand                             const SvgNodeVector& rChilds = mpTarget->getChildren();
483ddde725dSArmin Le Grand                             SvgCharacterNode* pTarget = 0;
484ddde725dSArmin Le Grand 
485ddde725dSArmin Le Grand                             if(rChilds.size())
486ddde725dSArmin Le Grand                             {
487ddde725dSArmin Le Grand                                 pTarget = dynamic_cast< SvgCharacterNode* >(rChilds[rChilds.size() - 1]);
488ddde725dSArmin Le Grand                             }
489ddde725dSArmin Le Grand 
490ddde725dSArmin Le Grand                             if(pTarget)
491ddde725dSArmin Le Grand                             {
492ddde725dSArmin Le Grand                                 // concatenate to current character span
493ddde725dSArmin Le Grand                                 pTarget->concatenate(aChars);
494ddde725dSArmin Le Grand                             }
495ddde725dSArmin Le Grand                             else
496ddde725dSArmin Le Grand                             {
497ddde725dSArmin Le Grand                                 // add character span as simplified tspan (no arguments)
498ddde725dSArmin Le Grand                                 // as direct child of SvgTextNode/SvgTspanNode/SvgTextPathNode
499ddde725dSArmin Le Grand                                 new SvgCharacterNode(maDocument, mpTarget, aChars);
500ddde725dSArmin Le Grand                             }
501ddde725dSArmin Le Grand                             break;
502ddde725dSArmin Le Grand                         }
503ddde725dSArmin Le Grand                         case SVGTokenStyle:
504ddde725dSArmin Le Grand                         {
505ddde725dSArmin Le Grand                             SvgStyleNode& rSvgStyleNode = static_cast< SvgStyleNode& >(*mpTarget);
506ddde725dSArmin Le Grand 
507ddde725dSArmin Le Grand                             if(rSvgStyleNode.isTextCss())
508ddde725dSArmin Le Grand                             {
509*3aaca8a3SArmin Le Grand                                 // collect characters for css style
510*3aaca8a3SArmin Le Grand                                 if(maCssContents.size())
511*3aaca8a3SArmin Le Grand                                 {
512*3aaca8a3SArmin Le Grand                                     const ::rtl::OUString aTrimmedChars(aChars.trim());
513ddde725dSArmin Le Grand 
514*3aaca8a3SArmin Le Grand                                     if(aTrimmedChars.getLength())
515*3aaca8a3SArmin Le Grand                                     {
516*3aaca8a3SArmin Le Grand                                         std::vector< rtl::OUString >::iterator aString(maCssContents.end() - 1);
517*3aaca8a3SArmin Le Grand                                         (*aString) += aTrimmedChars;
518*3aaca8a3SArmin Le Grand                                     }
519*3aaca8a3SArmin Le Grand                                 }
520*3aaca8a3SArmin Le Grand                                 else
521ddde725dSArmin Le Grand                                 {
522*3aaca8a3SArmin Le Grand                                     OSL_ENSURE(false, "Closing CssStyle, but no collector string on stack (!)");
523ddde725dSArmin Le Grand                                 }
524ddde725dSArmin Le Grand                             }
525ddde725dSArmin Le Grand                             break;
526ddde725dSArmin Le Grand                         }
527ddde725dSArmin Le Grand                         default:
528ddde725dSArmin Le Grand                         {
529ddde725dSArmin Le Grand                             // characters not used by a known node
530ddde725dSArmin Le Grand                             break;
531ddde725dSArmin Le Grand                         }
532ddde725dSArmin Le Grand                     }
533ddde725dSArmin Le Grand                 }
534ddde725dSArmin Le Grand             }
535ddde725dSArmin Le Grand         }
536ddde725dSArmin Le Grand 
537e2bf1e9dSArmin Le Grand         void SvgDocHdl::ignorableWhitespace(const ::rtl::OUString& /*aWhitespaces*/) throw (xml::sax::SAXException, uno::RuntimeException)
538ddde725dSArmin Le Grand         {
539ddde725dSArmin Le Grand         }
540ddde725dSArmin Le Grand 
541e2bf1e9dSArmin Le Grand         void SvgDocHdl::processingInstruction(const ::rtl::OUString& /*aTarget*/, const ::rtl::OUString& /*aData*/) throw (xml::sax::SAXException, uno::RuntimeException)
542ddde725dSArmin Le Grand         {
543ddde725dSArmin Le Grand         }
544ddde725dSArmin Le Grand 
545e2bf1e9dSArmin Le Grand         void SvgDocHdl::setDocumentLocator(const uno::Reference< xml::sax::XLocator >& /*xLocator*/) throw (xml::sax::SAXException, uno::RuntimeException)
546ddde725dSArmin Le Grand         {
547ddde725dSArmin Le Grand         }
548ddde725dSArmin Le Grand     } // end of namespace svgreader
549ddde725dSArmin Le Grand } // end of namespace svgio
550ddde725dSArmin Le Grand 
551ddde725dSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
552ddde725dSArmin Le Grand // eof
553