bump product version to 4.1.6.2
[LibreOffice.git] / svgio / source / svgreader / svgimagenode.cxx
blob7c7de6b6493e6d17d695379a100f24eb860bb1dd
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svgio/svgreader/svgimagenode.hxx>
21 #include <svgio/svgreader/svgdocument.hxx>
22 #include <sax/tools/converter.hxx>
23 #include <tools/stream.hxx>
24 #include <vcl/bitmapex.hxx>
25 #include <vcl/graphicfilter.hxx>
26 #include <basegfx/matrix/b2dhommatrixtools.hxx>
27 #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
28 #include <drawinglayer/primitive2d/groupprimitive2d.hxx>
29 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
30 #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
31 #include <basegfx/polygon/b2dpolygontools.hxx>
32 #include <basegfx/polygon/b2dpolygon.hxx>
33 #include <rtl/uri.hxx>
34 #include <drawinglayer/geometry/viewinformation2d.hxx>
36 //////////////////////////////////////////////////////////////////////////////
38 namespace svgio
40 namespace svgreader
42 SvgImageNode::SvgImageNode(
43 SvgDocument& rDocument,
44 SvgNode* pParent)
45 : SvgNode(SVGTokenRect, rDocument, pParent),
46 maSvgStyleAttributes(*this),
47 maSvgAspectRatio(),
48 mpaTransform(0),
49 maX(0),
50 maY(0),
51 maWidth(0),
52 maHeight(0),
53 maXLink(),
54 maUrl(),
55 maMimeType(),
56 maData()
60 SvgImageNode::~SvgImageNode()
62 if(mpaTransform) delete mpaTransform;
65 const SvgStyleAttributes* SvgImageNode::getSvgStyleAttributes() const
67 static rtl::OUString aClassStr(rtl::OUString::createFromAscii("image"));
68 return checkForCssStyle(aClassStr, maSvgStyleAttributes);
71 void SvgImageNode::parseAttribute(const OUString& rTokenName, SVGToken aSVGToken, const OUString& aContent)
73 // call parent
74 SvgNode::parseAttribute(rTokenName, aSVGToken, aContent);
76 // read style attributes
77 maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent);
79 // parse own
80 switch(aSVGToken)
82 case SVGTokenStyle:
84 maSvgStyleAttributes.readStyle(aContent);
85 break;
87 case SVGTokenPreserveAspectRatio:
89 setSvgAspectRatio(readSvgAspectRatio(aContent));
90 break;
92 case SVGTokenTransform:
94 const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this));
96 if(!aMatrix.isIdentity())
98 setTransform(&aMatrix);
100 break;
102 case SVGTokenX:
104 SvgNumber aNum;
106 if(readSingleNumber(aContent, aNum))
108 setX(aNum);
110 break;
112 case SVGTokenY:
114 SvgNumber aNum;
116 if(readSingleNumber(aContent, aNum))
118 setY(aNum);
120 break;
122 case SVGTokenWidth:
124 SvgNumber aNum;
126 if(readSingleNumber(aContent, aNum))
128 if(aNum.isPositive())
130 setWidth(aNum);
133 break;
135 case SVGTokenHeight:
137 SvgNumber aNum;
139 if(readSingleNumber(aContent, aNum))
141 if(aNum.isPositive())
143 setHeight(aNum);
146 break;
148 case SVGTokenXlinkHref:
150 const sal_Int32 nLen(aContent.getLength());
152 if(nLen)
154 readImageLink(aContent, maXLink, maUrl, maMimeType, maData);
156 break;
158 default:
160 break;
165 void extractFromGraphic(
166 const Graphic& rGraphic,
167 drawinglayer::primitive2d::Primitive2DSequence& rEmbedded,
168 basegfx::B2DRange& rViewBox,
169 BitmapEx& rBitmapEx)
171 if(GRAPHIC_BITMAP == rGraphic.GetType())
173 if(rGraphic.getSvgData().get())
175 // embedded Svg
176 rEmbedded = rGraphic.getSvgData()->getPrimitive2DSequence();
178 // fill aViewBox
179 rViewBox = rGraphic.getSvgData()->getRange();
181 else
183 // get bitmap
184 rBitmapEx = rGraphic.GetBitmapEx();
187 else
189 // evtl. convert to bitmap
190 rBitmapEx = rGraphic.GetBitmapEx();
194 void SvgImageNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool /*bReferenced*/) const
196 // get size range and create path
197 const SvgStyleAttributes* pStyle = getSvgStyleAttributes();
199 if(pStyle && getWidth().isSet() && getHeight().isSet())
201 const double fWidth(getWidth().solve(*this, xcoordinate));
202 const double fHeight(getHeight().solve(*this, ycoordinate));
204 if(fWidth > 0.0 && fHeight > 0.0)
206 BitmapEx aBitmapEx;
207 drawinglayer::primitive2d::Primitive2DSequence aNewTarget;
209 // prepare Target and ViewBox for evtl. AspectRatio mappings
210 const double fX(getX().isSet() ? getX().solve(*this, xcoordinate) : 0.0);
211 const double fY(getY().isSet() ? getY().solve(*this, ycoordinate) : 0.0);
212 const basegfx::B2DRange aTarget(fX, fY, fX + fWidth, fY + fHeight);
213 basegfx::B2DRange aViewBox(aTarget);
215 if(maMimeType.getLength() && maData.getLength())
217 // use embedded base64 encoded data
218 ::com::sun::star::uno::Sequence< sal_Int8 > aPass;
219 ::sax::Converter::decodeBase64(aPass, maData);
221 if(aPass.hasElements())
223 SvMemoryStream aStream(aPass.getArray(), aPass.getLength(), STREAM_READ);
224 Graphic aGraphic;
226 if(GRFILTER_OK == GraphicFilter::GetGraphicFilter().ImportGraphic(
227 aGraphic,
228 String(),
229 aStream))
231 extractFromGraphic(aGraphic, aNewTarget, aViewBox, aBitmapEx);
235 else if(maUrl.getLength())
237 const OUString& rPath = getDocument().getAbsolutePath();
238 const OUString aAbsUrl(rtl::Uri::convertRelToAbs(rPath, maUrl));
240 if(aAbsUrl.getLength())
242 SvFileStream aStream(aAbsUrl, STREAM_STD_READ);
243 Graphic aGraphic;
245 if(GRFILTER_OK == GraphicFilter::GetGraphicFilter().ImportGraphic(
246 aGraphic,
247 aAbsUrl,
248 aStream))
250 extractFromGraphic(aGraphic, aNewTarget, aViewBox, aBitmapEx);
254 else if(maXLink.getLength())
256 const SvgNode* mpXLink = getDocument().findSvgNodeById(maXLink);
258 if(mpXLink)
260 mpXLink->decomposeSvgNode(aNewTarget, true);
262 if(aNewTarget.hasElements())
264 aViewBox = drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence(
265 aNewTarget,
266 drawinglayer::geometry::ViewInformation2D());
271 if(!aBitmapEx.IsEmpty())
273 // create content from created bitmap
274 aNewTarget.realloc(1);
275 aNewTarget[0] = new drawinglayer::primitive2d::BitmapPrimitive2D(
276 aBitmapEx,
277 basegfx::B2DHomMatrix());
279 // fill aViewBox. No size set yet, use unit size
280 aViewBox = basegfx::B2DRange(0.0, 0.0, 1.0, 1.0);
283 if(aNewTarget.hasElements())
285 if(aTarget.equal(aViewBox))
287 // just add to rTarget
288 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aNewTarget);
290 else
292 // create mapping
293 const SvgAspectRatio& rRatio = getSvgAspectRatio();
295 if(rRatio.isSet())
297 // let mapping be created from SvgAspectRatio
298 const basegfx::B2DHomMatrix aEmbeddingTransform(rRatio.createMapping(aTarget, aViewBox));
300 if(!aEmbeddingTransform.isIdentity())
302 const drawinglayer::primitive2d::Primitive2DReference xRef(
303 new drawinglayer::primitive2d::TransformPrimitive2D(
304 aEmbeddingTransform,
305 aNewTarget));
307 aNewTarget = drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1);
310 if(!rRatio.isMeetOrSlice())
312 // need to embed in MaskPrimitive2D to ensure clipping
313 const drawinglayer::primitive2d::Primitive2DReference xMask(
314 new drawinglayer::primitive2d::MaskPrimitive2D(
315 basegfx::B2DPolyPolygon(
316 basegfx::tools::createPolygonFromRect(aTarget)),
317 aNewTarget));
319 aNewTarget = drawinglayer::primitive2d::Primitive2DSequence(&xMask, 1);
322 else
324 // choose default mapping
325 const basegfx::B2DHomMatrix aEmbeddingTransform(rRatio.createLinearMapping(aTarget, aViewBox));
327 if(!aEmbeddingTransform.isIdentity())
329 const drawinglayer::primitive2d::Primitive2DReference xRef(
330 new drawinglayer::primitive2d::TransformPrimitive2D(
331 aEmbeddingTransform,
332 aNewTarget));
334 aNewTarget = drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1);
338 // embed and add to rTarget, take local extra-transform into account
339 pStyle->add_postProcess(rTarget, aNewTarget, getTransform());
346 } // end of namespace svgreader
347 } // end of namespace svgio
349 //////////////////////////////////////////////////////////////////////////////
350 // eof
352 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */