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
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_svgio.hxx"
24 
25 #include <svgio/svgreader/svgrectnode.hxx>
26 #include <basegfx/polygon/b2dpolygon.hxx>
27 #include <basegfx/polygon/b2dpolygontools.hxx>
28 
29 //////////////////////////////////////////////////////////////////////////////
30 
31 namespace svgio
32 {
33     namespace svgreader
34     {
35         SvgRectNode::SvgRectNode(
36             SvgDocument& rDocument,
37             SvgNode* pParent)
38         :   SvgNode(SVGTokenRect, rDocument, pParent),
39             maSvgStyleAttributes(*this),
40             maX(0),
41             maY(0),
42             maWidth(0),
43             maHeight(0),
44             maRx(0),
45             maRy(0),
46             mpaTransform(0)
47         {
48         }
49 
50         SvgRectNode::~SvgRectNode()
51         {
52             if(mpaTransform) delete mpaTransform;
53         }
54 
55         const SvgStyleAttributes* SvgRectNode::getSvgStyleAttributes() const
56         {
57             static rtl::OUString aClassStr(rtl::OUString::createFromAscii("rect"));
58             maSvgStyleAttributes.checkForCssStyle(aClassStr);
59 
60             return &maSvgStyleAttributes;
61         }
62 
63         void SvgRectNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent)
64         {
65             // call parent
66             SvgNode::parseAttribute(rTokenName, aSVGToken, aContent);
67 
68             // read style attributes
69             maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent);
70 
71             // parse own
72             switch(aSVGToken)
73             {
74                 case SVGTokenStyle:
75                 {
76                     maSvgStyleAttributes.readStyle(aContent);
77                     break;
78                 }
79                 case SVGTokenX:
80                 {
81                     SvgNumber aNum;
82 
83                     if(readSingleNumber(aContent, aNum))
84                     {
85                         setX(aNum);
86                     }
87                     break;
88                 }
89                 case SVGTokenY:
90                 {
91                     SvgNumber aNum;
92 
93                     if(readSingleNumber(aContent, aNum))
94                     {
95                         setY(aNum);
96                     }
97                     break;
98                 }
99                 case SVGTokenWidth:
100                 {
101                     SvgNumber aNum;
102 
103                     if(readSingleNumber(aContent, aNum))
104                     {
105                         if(aNum.isPositive())
106                         {
107                             setWidth(aNum);
108                         }
109                     }
110                     break;
111                 }
112                 case SVGTokenHeight:
113                 {
114                     SvgNumber aNum;
115 
116                     if(readSingleNumber(aContent, aNum))
117                     {
118                         if(aNum.isPositive())
119                         {
120                             setHeight(aNum);
121                         }
122                     }
123                     break;
124                 }
125                 case SVGTokenRx:
126                 {
127                     SvgNumber aNum;
128 
129                     if(readSingleNumber(aContent, aNum))
130                     {
131                         if(aNum.isPositive())
132                         {
133                             setRx(aNum);
134                         }
135                     }
136                     break;
137                 }
138                 case SVGTokenRy:
139                 {
140                     SvgNumber aNum;
141 
142                     if(readSingleNumber(aContent, aNum))
143                     {
144                         if(aNum.isPositive())
145                         {
146                             setRy(aNum);
147                         }
148                     }
149                     break;
150                 }
151                 case SVGTokenTransform:
152                 {
153                     const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this));
154 
155                     if(!aMatrix.isIdentity())
156                     {
157                         setTransform(&aMatrix);
158                     }
159                     break;
160                 }
161                 default:
162                 {
163                     break;
164                 }
165             }
166         }
167 
168         void SvgRectNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool /*bReferenced*/) const
169         {
170             // get size range and create path
171             const SvgStyleAttributes* pStyle = getSvgStyleAttributes();
172 
173             if(pStyle && getWidth().isSet() && getHeight().isSet())
174             {
175                 const double fWidth(getWidth().solve(*this, xcoordinate));
176                 const double fHeight(getHeight().solve(*this, ycoordinate));
177 
178                 if(fWidth > 0.0 && fHeight > 0.0)
179                 {
180                     const double fX(getX().isSet() ? getX().solve(*this, xcoordinate) : 0.0);
181                     const double fY(getY().isSet() ? getY().solve(*this, ycoordinate) : 0.0);
182                     const basegfx::B2DRange aRange(fX, fY, fX + fWidth, fY + fHeight);
183                     basegfx::B2DPolygon aPath;
184 
185                     if(getRx().isSet() || getRy().isSet())
186                     {
187                         double frX(getRx().isSet() ? getRx().solve(*this, xcoordinate) : 0.0);
188                         double frY(getRy().isSet() ? getRy().solve(*this, ycoordinate) : 0.0);
189 
190                         frX = std::max(0.0, frX);
191                         frY = std::max(0.0, frY);
192 
193                         if(0.0 == frY && frX > 0.0)
194                         {
195                             frY = frX;
196                         }
197                         else if(0.0 == frX && frY > 0.0)
198                         {
199                             frX = frY;
200                         }
201 
202                         frX /= fWidth;
203                         frY /= fHeight;
204 
205                         frX = std::min(0.5, frX);
206                         frY = std::min(0.5, frY);
207 
208                         aPath = basegfx::tools::createPolygonFromRect(aRange, frX * 2.0, frY * 2.0);
209                     }
210                     else
211                     {
212                         aPath = basegfx::tools::createPolygonFromRect(aRange);
213                     }
214 
215                     drawinglayer::primitive2d::Primitive2DSequence aNewTarget;
216 
217                     pStyle->add_path(basegfx::B2DPolyPolygon(aPath), aNewTarget);
218 
219                     if(aNewTarget.hasElements())
220                     {
221                         pStyle->add_postProcess(rTarget, aNewTarget, getTransform());
222                     }
223                 }
224             }
225         }
226     } // end of namespace svgreader
227 } // end of namespace svgio
228 
229 //////////////////////////////////////////////////////////////////////////////
230 // eof
231