svgnode.cxx (9d56236f) svgnode.cxx (9d01bcde)
1/**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance

--- 33 unchanged lines hidden (view full) ---

42 return true;
43 }
44
45 const SvgStyleAttributes* SvgNode::getSvgStyleAttributes() const
46 {
47 return 0;
48 }
49
1/**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance

--- 33 unchanged lines hidden (view full) ---

42 return true;
43 }
44
45 const SvgStyleAttributes* SvgNode::getSvgStyleAttributes() const
46 {
47 return 0;
48 }
49
50 const SvgStyleAttributes* SvgNode::checkForCssStyle(const rtl::OUString& rClassStr, const SvgStyleAttributes& rOriginal) const
50 void SvgNode::fillCssStyleVector(const rtl::OUString& rClassStr)
51 {
51 {
52 if(maCssStyleVector.empty()) // #120435# Evaluate for CSS styles only once, this cannot change
52 OSL_ENSURE(!mbCssStyleVectorBuilt, "OOps, fillCssStyleVector called double ?!?");
53 mbCssStyleVectorBuilt = true;
54
55 // #125293# If we have CssStyles we need to buuild a linked list of SvgStyleAttributes
56 // which represent this for the current object. There are various methods to
57 // specify CssStyles which need to be taken into account in a given order:
58 // - local CssStyle (independent from global CssStyles at SvgDocument)
59 // - 'id' CssStyle
60 // - 'class' CssStyle(s)
61 // - type-dependent elements (e..g. 'rect' for all rect elements)
62 // - local attributes (rOriginal)
63 // - inherited attributes (up the hierarchy)
64 // The first four will be collected in maCssStyleVector for the current element
65 // (once, this will not change) and be linked in the needed order using the
66 // get/setCssStyleParent at the SvgStyleAttributes which will be used preferred in
67 // member evaluation over the existing parent hierarchy
68
69 // check for local CssStyle with highest priority
70 if(mpLocalCssStyle)
53 {
71 {
54 const SvgDocument& rDocument = getDocument();
72 // if we have one, use as first entry
73 maCssStyleVector.push_back(mpLocalCssStyle);
74 }
55
75
56 if(rDocument.hasSvgStyleAttributesById())
76 const SvgDocument& rDocument = getDocument();
77
78 if(rDocument.hasSvgStyleAttributesById())
79 {
80 // check for 'id' references
81 if(getId())
57 {
82 {
58 // #125293# If we have CssStyles we need to buuild a linked list of SvgStyleAttributes
59 // which represent this for the current object. There are various methods to
60 // specify CssStyles which need to be taken into account in a given order:
61 // - 'id' element
62 // - 'class' element(s)
63 // - type-dependent elements (e..g. 'rect' for all rect elements)
64 // - local firect attributes (rOriginal)
65 // - inherited attributes (up the hierarchy)
66 // The first three will be collected in maCssStyleVector for the current element
67 // (once, this will not change) and be linked in the needed order using the
68 // get/setCssStyleParent at the SvgStyleAttributes which will be used preferred in
69 // member evaluation over the existing parent hierarchy
83 // concatenate combined style name during search for CSS style equal to Id
84 // when travelling over node parents
85 rtl::OUString aConcatenatedStyleName;
86 const SvgNode* pCurrent = this;
87 const SvgStyleAttributes* pNew = 0;
70
88
71 // check for 'id' references
72 if(getId())
89 while(!pNew && pCurrent)
73 {
90 {
74 // search for CSS style equal to Id
75 const SvgStyleAttributes* pNew = rDocument.findSvgStyleAttributesById(*getId());
91 if(pCurrent->getId())
92 {
93 aConcatenatedStyleName = *pCurrent->getId() + aConcatenatedStyleName;
94 }
76
95
77 if(pNew)
96 if(aConcatenatedStyleName.getLength())
78 {
97 {
79 const_cast< SvgNode* >(this)->maCssStyleVector.push_back(pNew);
98 pNew = rDocument.findSvgStyleAttributesById(aConcatenatedStyleName);
80 }
99 }
100
101 pCurrent = pCurrent->getParent();
81 }
82
102 }
103
83 // check for 'class' references
84 if(getClass())
104 if(pNew)
85 {
105 {
86 // find all referenced CSS styles, a list of entries is allowed
87 const rtl::OUString* pClassList = getClass();
88 const sal_Int32 nLen(pClassList->getLength());
89 sal_Int32 nPos(0);
90 const SvgStyleAttributes* pNew = 0;
106 maCssStyleVector.push_back(pNew);
107 }
108 }
91
109
92 skip_char(*pClassList, sal_Unicode(' '), nPos, nLen);
110 // check for 'class' references
111 if(getClass())
112 {
113 // find all referenced CSS styles (a list of entries is allowed)
114 const rtl::OUString* pClassList = getClass();
115 const sal_Int32 nLen(pClassList->getLength());
116 sal_Int32 nPos(0);
117 const SvgStyleAttributes* pNew = 0;
93
118
94 while(nPos < nLen)
95 {
96 rtl::OUStringBuffer aTokenValue;
119 skip_char(*pClassList, sal_Unicode(' '), nPos, nLen);
97
120
98 copyToLimiter(*pClassList, sal_Unicode(' '), nPos, aTokenValue, nLen);
99 skip_char(*pClassList, sal_Unicode(' '), nPos, nLen);
121 while(nPos < nLen)
122 {
123 rtl::OUStringBuffer aTokenValue;
100
124
101 rtl::OUString aId(rtl::OUString::createFromAscii("."));
102 const rtl::OUString aOUTokenValue(aTokenValue.makeStringAndClear());
125 copyToLimiter(*pClassList, sal_Unicode(' '), nPos, aTokenValue, nLen);
126 skip_char(*pClassList, sal_Unicode(' '), nPos, nLen);
103
127
104 // look for CSS style common to token
105 aId = aId + aOUTokenValue;
106 pNew = rDocument.findSvgStyleAttributesById(aId);
128 rtl::OUString aId(rtl::OUString::createFromAscii("."));
129 const rtl::OUString aOUTokenValue(aTokenValue.makeStringAndClear());
107
130
108 if(!pNew && rClassStr.getLength())
109 {
110 // look for CSS style common to class.token
111 aId = rClassStr + aId;
131 // look for CSS style common to token
132 aId = aId + aOUTokenValue;
133 pNew = rDocument.findSvgStyleAttributesById(aId);
112
134
113 pNew = rDocument.findSvgStyleAttributesById(aId);
114 }
135 if(!pNew && rClassStr.getLength())
136 {
137 // look for CSS style common to class.token
138 aId = rClassStr + aId;
115
139
116 if(pNew)
117 {
118 const_cast< SvgNode* >(this)->maCssStyleVector.push_back(pNew);
119 }
140 pNew = rDocument.findSvgStyleAttributesById(aId);
120 }
141 }
121 }
122
142
123 // check for class-dependent references to CssStyles
124 if(rClassStr.getLength())
125 {
126 // search for CSS style equal to class type
127 const SvgStyleAttributes* pNew = rDocument.findSvgStyleAttributesById(rClassStr);
128
129 if(pNew)
130 {
143 if(pNew)
144 {
131 const_cast< SvgNode* >(this)->maCssStyleVector.push_back(pNew);
145 maCssStyleVector.push_back(pNew);
132 }
133 }
134 }
146 }
147 }
148 }
149
150 // check for class-dependent references to CssStyles
151 if(rClassStr.getLength())
152 {
153 // search for CSS style equal to class type
154 const SvgStyleAttributes* pNew = rDocument.findSvgStyleAttributesById(rClassStr);
155
156 if(pNew)
157 {
158 maCssStyleVector.push_back(pNew);
159 }
160 }
135 }
161 }
162 }
136
163
164 const SvgStyleAttributes* SvgNode::checkForCssStyle(const rtl::OUString& rClassStr, const SvgStyleAttributes& rOriginal) const
165 {
166 if(!mbCssStyleVectorBuilt)
167 {
168 // build needed CssStyleVector for local node
169 const_cast< SvgNode* >(this)->fillCssStyleVector(rClassStr);
170 }
171
137 if(maCssStyleVector.empty())
138 {
172 if(maCssStyleVector.empty())
173 {
139 // return original if no CssStlyes found
174 // return given original if no CssStlyes found
140 return &rOriginal;
141 }
142 else
143 {
144 // #125293# rOriginal will be the last element in the linked list; use no CssStyleParent
145 // there (reset it) to ensure that the parent hierarchy will be used when it's base
146 // is referenced. This new chaning inserts the CssStyles before the original style,
147 // this makes the whole process much safer since the original style when used will

--- 40 unchanged lines hidden (view full) ---

188 mrDocument(rDocument),
189 mpParent(pParent),
190 mpAlternativeParent(0),
191 maChildren(),
192 mpId(0),
193 mpClass(0),
194 maXmlSpace(XmlSpace_notset),
195 maDisplay(Display_inline),
175 return &rOriginal;
176 }
177 else
178 {
179 // #125293# rOriginal will be the last element in the linked list; use no CssStyleParent
180 // there (reset it) to ensure that the parent hierarchy will be used when it's base
181 // is referenced. This new chaning inserts the CssStyles before the original style,
182 // this makes the whole process much safer since the original style when used will

--- 40 unchanged lines hidden (view full) ---

223 mrDocument(rDocument),
224 mpParent(pParent),
225 mpAlternativeParent(0),
226 maChildren(),
227 mpId(0),
228 mpClass(0),
229 maXmlSpace(XmlSpace_notset),
230 maDisplay(Display_inline),
196 maCssStyleVector()
231 maCssStyleVector(),
232 mpLocalCssStyle(0),
233 mbCssStyleVectorBuilt(false)
197 {
198 OSL_ENSURE(SVGTokenUnknown != maType, "SvgNode with unknown type created (!)");
199
200 if(pParent)
201 {
202 pParent->maChildren.push_back(this);
203 }
204 else

--- 10 unchanged lines hidden (view full) ---

215 SvgNode::~SvgNode()
216 {
217 while(maChildren.size())
218 {
219 delete maChildren[maChildren.size() - 1];
220 maChildren.pop_back();
221 }
222
234 {
235 OSL_ENSURE(SVGTokenUnknown != maType, "SvgNode with unknown type created (!)");
236
237 if(pParent)
238 {
239 pParent->maChildren.push_back(this);
240 }
241 else

--- 10 unchanged lines hidden (view full) ---

252 SvgNode::~SvgNode()
253 {
254 while(maChildren.size())
255 {
256 delete maChildren[maChildren.size() - 1];
257 maChildren.pop_back();
258 }
259
223 if(mpId) delete mpId;
224 if(mpClass) delete mpClass;
260 if(mpId)
261 {
262 delete mpId;
263 }
264
265 if(mpClass)
266 {
267 delete mpClass;
268 }
269
270 if(mpLocalCssStyle)
271 {
272 delete mpLocalCssStyle;
273 }
225 }
226
274 }
275
276 void SvgNode::readLocalCssStyle(const rtl::OUString& aContent)
277 {
278 if(!mpLocalCssStyle)
279 {
280 // create LocalCssStyle if needed but not yet added
281 mpLocalCssStyle = new SvgStyleAttributes(*this);
282 }
283 else
284 {
285 // 2nd fill would be an error
286 OSL_ENSURE(false, "Svg node has two local CssStyles, this may lead to problems (!)");
287 }
288
289 if(mpLocalCssStyle)
290 {
291 // parse and set values to it
292 mpLocalCssStyle->readStyle(aContent);
293 }
294 else
295 {
296 OSL_ENSURE(false, "Could not get/create a local CssStyle for a node (!)");
297 }
298 }
299
227 void SvgNode::parseAttributes(const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttribs)
228 {
300 void SvgNode::parseAttributes(const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttribs)
301 {
302 // no longer need to pre-sort moving 'style' entries to the back so that
303 // values get overwritten - that was the previous, not complete solution for
304 // handling the priorities between svg and Css properties
229 const sal_uInt32 nAttributes(xAttribs->getLength());
305 const sal_uInt32 nAttributes(xAttribs->getLength());
230 // #122522# SVG defines that 'In general, this means that the presentation attributes have
231 // lower priority than other CSS style rules specified in author style sheets or �style�
232 // attributes.' in http://www.w3.org/TR/SVG/styling.html#UsingPresentationAttributes
233 // (6.4 Specifying properties using the presentation attributes SVG 1.1). That means that
234 // e.g. font-size will appear as presentation attribute and CSS style attribute. In these
235 // cases, CSS style attributes need to have precedence. To do so it is possible to create
236 // a proirity system for all properties of a shape, but it will also work to parse the
237 // presentation attributes of type 'style' last, so they will overwrite the less-prioritized
238 // already interpreted ones. Thus, remember SVGTokenStyle entries and parse them last.
239 // To make this work it is required that parseAttribute is only called by parseAttributes
240 // which is the case.
241 std::vector< sal_uInt32 > aSVGTokenStyleIndexes;
242
243 for(sal_uInt32 a(0); a < nAttributes; a++)
244 {
245 const ::rtl::OUString aTokenName(xAttribs->getNameByIndex(a));
246 const SVGToken aSVGToken(StrToSVGToken(aTokenName));
247
306
307 for(sal_uInt32 a(0); a < nAttributes; a++)
308 {
309 const ::rtl::OUString aTokenName(xAttribs->getNameByIndex(a));
310 const SVGToken aSVGToken(StrToSVGToken(aTokenName));
311
248 if(SVGTokenStyle == aSVGToken)
249 {
250 // #122522# remember SVGTokenStyle entry
251 aSVGTokenStyleIndexes.push_back(a);
252 }
253 else
254 {
255 parseAttribute(aTokenName, aSVGToken, xAttribs->getValueByIndex(a));
256 }
312 parseAttribute(aTokenName, aSVGToken, xAttribs->getValueByIndex(a));
257 }
313 }
258
259 // #122522# parse SVGTokenStyle entries last to override already interpreted
260 // 'presentation attributes' of potenially the same type
261 for(sal_uInt32 b(0); b < aSVGTokenStyleIndexes.size(); b++)
262 {
263 const sal_uInt32 nSVGTokenStyleIndex(aSVGTokenStyleIndexes[b]);
264 const ::rtl::OUString aTokenName(xAttribs->getNameByIndex(nSVGTokenStyleIndex));
265
266 parseAttribute(aTokenName, SVGTokenStyle, xAttribs->getValueByIndex(nSVGTokenStyleIndex));
267 }
268 }
269
270 Display getDisplayFromContent(const rtl::OUString& aContent)
271 {
272 if(aContent.getLength())
273 {
274 static rtl::OUString aStrInline(rtl::OUString::createFromAscii("inline"));
275 static rtl::OUString aStrBlock(rtl::OUString::createFromAscii("block"));

--- 352 unchanged lines hidden ---
314 }
315
316 Display getDisplayFromContent(const rtl::OUString& aContent)
317 {
318 if(aContent.getLength())
319 {
320 static rtl::OUString aStrInline(rtl::OUString::createFromAscii("inline"));
321 static rtl::OUString aStrBlock(rtl::OUString::createFromAscii("block"));

--- 352 unchanged lines hidden ---