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