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/svgstylenode.hxx>
26ddde725dSArmin Le Grand #include <svgio/svgreader/svgdocument.hxx>
27ddde725dSArmin Le Grand 
28ddde725dSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
29ddde725dSArmin Le Grand 
30ddde725dSArmin Le Grand namespace svgio
31ddde725dSArmin Le Grand {
32ddde725dSArmin Le Grand     namespace svgreader
33ddde725dSArmin Le Grand     {
SvgStyleNode(SvgDocument & rDocument,SvgNode * pParent)34ddde725dSArmin Le Grand         SvgStyleNode::SvgStyleNode(
35ddde725dSArmin Le Grand             SvgDocument& rDocument,
36ddde725dSArmin Le Grand             SvgNode* pParent)
37ddde725dSArmin Le Grand         :   SvgNode(SVGTokenStyle, rDocument, pParent),
38ddde725dSArmin Le Grand             maSvgStyleAttributes(),
39ddde725dSArmin Le Grand             mbTextCss(false)
40ddde725dSArmin Le Grand         {
41ddde725dSArmin Le Grand         }
42ddde725dSArmin Le Grand 
~SvgStyleNode()43ddde725dSArmin Le Grand         SvgStyleNode::~SvgStyleNode()
44ddde725dSArmin Le Grand         {
45ddde725dSArmin Le Grand             while(!maSvgStyleAttributes.empty())
46ddde725dSArmin Le Grand             {
47ddde725dSArmin Le Grand                 delete *(maSvgStyleAttributes.end() - 1);
48ddde725dSArmin Le Grand                 maSvgStyleAttributes.pop_back();
49ddde725dSArmin Le Grand             }
50ddde725dSArmin Le Grand         }
51ddde725dSArmin Le Grand 
524374d266SArmin Le Grand         // #125258# no parent when we are a CssStyle holder to break potential loops because
534374d266SArmin Le Grand         // when using CssStyles we jump uncontrolled inside the node tree hierarchy
supportsParentStyle() const544374d266SArmin Le Grand         bool SvgStyleNode::supportsParentStyle() const
554374d266SArmin Le Grand         {
564374d266SArmin Le Grand             if(isTextCss())
574374d266SArmin Le Grand             {
584374d266SArmin Le Grand                 return false;
594374d266SArmin Le Grand             }
604374d266SArmin Le Grand 
614374d266SArmin Le Grand             // call parent
624374d266SArmin Le Grand             return SvgNode::supportsParentStyle();
634374d266SArmin Le Grand         }
644374d266SArmin Le Grand 
parseAttribute(const rtl::OUString & rTokenName,SVGToken aSVGToken,const rtl::OUString & aContent)65ddde725dSArmin Le Grand         void SvgStyleNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent)
66ddde725dSArmin Le Grand         {
67ddde725dSArmin Le Grand             // call parent
68ddde725dSArmin Le Grand             SvgNode::parseAttribute(rTokenName, aSVGToken, aContent);
69ddde725dSArmin Le Grand 
70ddde725dSArmin Le Grand             // parse own
71ddde725dSArmin Le Grand             switch(aSVGToken)
72ddde725dSArmin Le Grand             {
73ddde725dSArmin Le Grand                 case SVGTokenType:
74ddde725dSArmin Le Grand                 {
75ddde725dSArmin Le Grand                     if(aContent.getLength())
76ddde725dSArmin Le Grand                     {
77ddde725dSArmin Le Grand                         static rtl::OUString aStrTextCss(rtl::OUString::createFromAscii("text/css"));
78ddde725dSArmin Le Grand 
79ddde725dSArmin Le Grand                         if(aContent.match(aStrTextCss))
80ddde725dSArmin Le Grand                         {
81ddde725dSArmin Le Grand                             setTextCss(true);
82ddde725dSArmin Le Grand                         }
83ddde725dSArmin Le Grand                     }
84ddde725dSArmin Le Grand                     break;
85ddde725dSArmin Le Grand                 }
86e2bf1e9dSArmin Le Grand                 default:
87e2bf1e9dSArmin Le Grand                 {
88e2bf1e9dSArmin Le Grand                     break;
89e2bf1e9dSArmin Le Grand                 }
90ddde725dSArmin Le Grand             }
91ddde725dSArmin Le Grand         }
92ddde725dSArmin Le Grand 
addCssStyleSheet(const rtl::OUString & aSelectors,const SvgStyleAttributes & rNewStyle)93eb82bfcdSArmin Le Grand         void SvgStyleNode::addCssStyleSheet(const rtl::OUString& aSelectors, const SvgStyleAttributes& rNewStyle)
94ddde725dSArmin Le Grand         {
95eb82bfcdSArmin Le Grand             // aSelectors: CssStyle selectors, any combination, no comma separations, no spaces at start/end
96eb82bfcdSArmin Le Grand             // rNewStyle: the already preapared style to register on that name
97eb82bfcdSArmin Le Grand             if(aSelectors.getLength())
98ddde725dSArmin Le Grand             {
99eb82bfcdSArmin Le Grand                 std::vector< rtl::OUString > aSelectorParts;
100eb82bfcdSArmin Le Grand                 const sal_Int32 nLen(aSelectors.getLength());
101ddde725dSArmin Le Grand                 sal_Int32 nPos(0);
102eb82bfcdSArmin Le Grand                 rtl::OUStringBuffer aToken;
103ddde725dSArmin Le Grand 
104eb82bfcdSArmin Le Grand                 // split into single tokens (currently only space separator)
105311ea6abSArmin Le Grand                 while(nPos < nLen)
106ddde725dSArmin Le Grand                 {
107311ea6abSArmin Le Grand                     const sal_Int32 nInitPos(nPos);
108eb82bfcdSArmin Le Grand                     copyToLimiter(aSelectors, sal_Unicode(' '), nPos, aToken, nLen);
109eb82bfcdSArmin Le Grand                     skip_char(aSelectors, sal_Unicode(' '), nPos, nLen);
110eb82bfcdSArmin Le Grand                     const rtl::OUString aSelectorPart(aToken.makeStringAndClear().trim());
111ddde725dSArmin Le Grand 
112eb82bfcdSArmin Le Grand                     if(aSelectorPart.getLength())
113eb82bfcdSArmin Le Grand                     {
114eb82bfcdSArmin Le Grand                         aSelectorParts.push_back(aSelectorPart);
115eb82bfcdSArmin Le Grand                     }
1169d01bcdeSArmin Le Grand 
117eb82bfcdSArmin Le Grand                     if(nInitPos == nPos)
1189d01bcdeSArmin Le Grand                     {
119eb82bfcdSArmin Le Grand                         OSL_ENSURE(false, "Could not interpret on current position (!)");
120eb82bfcdSArmin Le Grand                         nPos++;
121eb82bfcdSArmin Le Grand                     }
122eb82bfcdSArmin Le Grand                 }
1239d01bcdeSArmin Le Grand 
124eb82bfcdSArmin Le Grand                 if(aSelectorParts.size())
125eb82bfcdSArmin Le Grand                 {
126eb82bfcdSArmin Le Grand                     rtl::OUString aConcatenatedSelector;
127eb82bfcdSArmin Le Grand 
128eb82bfcdSArmin Le Grand                     // re-combine without spaces, create a unique name (for now)
129eb82bfcdSArmin Le Grand                     for(sal_uInt32 a(0); a < aSelectorParts.size(); a++)
130eb82bfcdSArmin Le Grand                     {
131eb82bfcdSArmin Le Grand                         aConcatenatedSelector += aSelectorParts[a];
132eb82bfcdSArmin Le Grand                     }
1339d01bcdeSArmin Le Grand 
134eb82bfcdSArmin Le Grand                     // CssStyles in SVG are currently not completely supported; the current idea for
135eb82bfcdSArmin Le Grand                     // supporting the needed minimal set is to register CssStyles associated to a string
136eb82bfcdSArmin Le Grand                     // which is just the space-char cleaned, concatenated Selectors. The part to 'match'
137eb82bfcdSArmin Le Grand                     // these is in fillCssStyleVectorUsingHierarchyAndSelectors. There, the same string is
138eb82bfcdSArmin Le Grand                     // built up using the priorities of local CssStyle, Id, Class and other info combined
139eb82bfcdSArmin Le Grand                     // with the existing hierarchy. This creates a specificity- and priority-sorted local
140eb82bfcdSArmin Le Grand                     // list for each node which is then chained using get/setCssStyleParent.
141eb82bfcdSArmin Le Grand                     // The current solution is capable of solving space-separated selectors which can be
142eb82bfcdSArmin Le Grand                     // mixed between Id, Class and type specifiers.
143eb82bfcdSArmin Le Grand                     // When CssStyles need more specific solving, the start point is here; remember the
144eb82bfcdSArmin Le Grand                     // needed infos not in maIdStyleTokenMapperList at the document, but select evtl.
145eb82bfcdSArmin Le Grand                     // more specific infos there in a class capable of handling more complex matchings.
146eb82bfcdSArmin Le Grand                     // Additionally fillCssStyleVector (or the mechanism above that when a linked list of
147eb82bfcdSArmin Le Grand                     // SvgStyleAttributes will not do it) will have to be adapted to make use of it.
148eb82bfcdSArmin Le Grand 
149eb82bfcdSArmin Le Grand                     // register new style at document for (evtl. concatenated) stylename
150eb82bfcdSArmin Le Grand                     const_cast< SvgDocument& >(getDocument()).addSvgStyleAttributesToMapper(aConcatenatedSelector, rNewStyle);
151eb82bfcdSArmin Le Grand                 }
152eb82bfcdSArmin Le Grand             }
153eb82bfcdSArmin Le Grand         }
1549d01bcdeSArmin Le Grand 
addCssStyleSheet(const rtl::OUString & aSelectors,const rtl::OUString & aContent)155eb82bfcdSArmin Le Grand         void SvgStyleNode::addCssStyleSheet(const rtl::OUString& aSelectors, const rtl::OUString& aContent)
156eb82bfcdSArmin Le Grand         {
157eb82bfcdSArmin Le Grand             // aSelectors: possible comma-separated list of CssStyle definitions, no spaces at start/end
158eb82bfcdSArmin Le Grand             // aContent: the svg style definitions as string
159eb82bfcdSArmin Le Grand             if(aSelectors.getLength() && aContent.getLength())
160eb82bfcdSArmin Le Grand             {
161eb82bfcdSArmin Le Grand                 // create new style and add to local list (for ownership control)
162eb82bfcdSArmin Le Grand                 SvgStyleAttributes* pNewStyle = new SvgStyleAttributes(*this);
163eb82bfcdSArmin Le Grand                 maSvgStyleAttributes.push_back(pNewStyle);
164eb82bfcdSArmin Le Grand 
165eb82bfcdSArmin Le Grand                 // fill with content
166*52cb04b8SArmin Le Grand                 pNewStyle->readCssStyle(aContent);
167eb82bfcdSArmin Le Grand 
168eb82bfcdSArmin Le Grand                 // comma-separated split (Css abbreviation for same style for multiple selectors)
169eb82bfcdSArmin Le Grand                 const sal_Int32 nLen(aSelectors.getLength());
170eb82bfcdSArmin Le Grand                 sal_Int32 nPos(0);
171eb82bfcdSArmin Le Grand                 rtl::OUStringBuffer aToken;
172eb82bfcdSArmin Le Grand 
173eb82bfcdSArmin Le Grand                 while(nPos < nLen)
174eb82bfcdSArmin Le Grand                 {
175eb82bfcdSArmin Le Grand                     const sal_Int32 nInitPos(nPos);
176eb82bfcdSArmin Le Grand                     copyToLimiter(aSelectors, sal_Unicode(','), nPos, aToken, nLen);
177eb82bfcdSArmin Le Grand                     skip_char(aSelectors, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
178eb82bfcdSArmin Le Grand 
179eb82bfcdSArmin Le Grand                     const rtl::OUString aSingleName(aToken.makeStringAndClear().trim());
180eb82bfcdSArmin Le Grand 
181eb82bfcdSArmin Le Grand                     if(aSingleName.getLength())
182eb82bfcdSArmin Le Grand                     {
183eb82bfcdSArmin Le Grand                         addCssStyleSheet(aSingleName, *pNewStyle);
1849d01bcdeSArmin Le Grand                     }
1859d01bcdeSArmin Le Grand 
186eb82bfcdSArmin Le Grand                     if(nInitPos == nPos)
187ddde725dSArmin Le Grand                     {
188eb82bfcdSArmin Le Grand                         OSL_ENSURE(false, "Could not interpret on current position (!)");
189eb82bfcdSArmin Le Grand                         nPos++;
190eb82bfcdSArmin Le Grand                     }
191eb82bfcdSArmin Le Grand                 }
192eb82bfcdSArmin Le Grand             }
193eb82bfcdSArmin Le Grand         }
194311ea6abSArmin Le Grand 
addCssStyleSheet(const rtl::OUString & aSelectorsAndContent)195eb82bfcdSArmin Le Grand         void SvgStyleNode::addCssStyleSheet(const rtl::OUString& aSelectorsAndContent)
196eb82bfcdSArmin Le Grand         {
197eb82bfcdSArmin Le Grand             const sal_Int32 nLen(aSelectorsAndContent.getLength());
198ddde725dSArmin Le Grand 
199eb82bfcdSArmin Le Grand             if(nLen)
200eb82bfcdSArmin Le Grand             {
201eb82bfcdSArmin Le Grand                 sal_Int32 nPos(0);
202eb82bfcdSArmin Le Grand                 rtl::OUStringBuffer aToken;
203eb82bfcdSArmin Le Grand 
204eb82bfcdSArmin Le Grand                 while(nPos < nLen)
205eb82bfcdSArmin Le Grand                 {
206eb82bfcdSArmin Le Grand                     // read the full selectors (may be multiple, comma-separated)
207eb82bfcdSArmin Le Grand                     const sal_Int32 nInitPos(nPos);
208eb82bfcdSArmin Le Grand                     skip_char(aSelectorsAndContent, sal_Unicode(' '), nPos, nLen);
209eb82bfcdSArmin Le Grand                     copyToLimiter(aSelectorsAndContent, sal_Unicode('{'), nPos, aToken, nLen);
210eb82bfcdSArmin Le Grand                     skip_char(aSelectorsAndContent, sal_Unicode(' '), sal_Unicode('{'), nPos, nLen);
211ddde725dSArmin Le Grand 
212eb82bfcdSArmin Le Grand                     const rtl::OUString aSelectors(aToken.makeStringAndClear().trim());
213eb82bfcdSArmin Le Grand                     rtl::OUString aContent;
2149d01bcdeSArmin Le Grand 
215eb82bfcdSArmin Le Grand                     if(aSelectors.getLength() && nPos < nLen)
216eb82bfcdSArmin Le Grand                     {
217eb82bfcdSArmin Le Grand                         // isolate content as text, embraced by '{' and '}'
218eb82bfcdSArmin Le Grand                         copyToLimiter(aSelectorsAndContent, sal_Unicode('}'), nPos, aToken, nLen);
219eb82bfcdSArmin Le Grand                         skip_char(aSelectorsAndContent, sal_Unicode(' '), sal_Unicode('}'), nPos, nLen);
2209d01bcdeSArmin Le Grand 
221eb82bfcdSArmin Le Grand                         aContent = aToken.makeStringAndClear().trim();
222eb82bfcdSArmin Le Grand                     }
223eb82bfcdSArmin Le Grand 
224eb82bfcdSArmin Le Grand                     if(aSelectors.getLength() && aContent.getLength())
225eb82bfcdSArmin Le Grand                     {
226eb82bfcdSArmin Le Grand                         addCssStyleSheet(aSelectors, aContent);
227311ea6abSArmin Le Grand                     }
228311ea6abSArmin Le Grand 
229311ea6abSArmin Le Grand                     if(nInitPos == nPos)
230311ea6abSArmin Le Grand                     {
231311ea6abSArmin Le Grand                         OSL_ENSURE(false, "Could not interpret on current position (!)");
232311ea6abSArmin Le Grand                         nPos++;
233ddde725dSArmin Le Grand                     }
234ddde725dSArmin Le Grand                 }
235ddde725dSArmin Le Grand             }
236ddde725dSArmin Le Grand         }
237ddde725dSArmin Le Grand 
238ddde725dSArmin Le Grand     } // end of namespace svgreader
239ddde725dSArmin Le Grand } // end of namespace svgio
240ddde725dSArmin Le Grand 
241ddde725dSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
242ddde725dSArmin Le Grand // eof
243