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/svgsvgnode.hxx> 26ddde725dSArmin Le Grand #include <drawinglayer/geometry/viewinformation2d.hxx> 27ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/transformprimitive2d.hxx> 28ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/maskprimitive2d.hxx> 29ddde725dSArmin Le Grand #include <basegfx/polygon/b2dpolygontools.hxx> 30ddde725dSArmin Le Grand #include <basegfx/polygon/b2dpolygon.hxx> 31ddde725dSArmin Le Grand #include <basegfx/matrix/b2dhommatrixtools.hxx> 3241923119SArmin Le Grand #include <drawinglayer/primitive2d/polygonprimitive2d.hxx> 3341923119SArmin Le Grand #include <drawinglayer/primitive2d/hiddengeometryprimitive2d.hxx> 34ddde725dSArmin Le Grand 35ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 36ddde725dSArmin Le Grand 37ddde725dSArmin Le Grand namespace svgio 38ddde725dSArmin Le Grand { 39ddde725dSArmin Le Grand namespace svgreader 40ddde725dSArmin Le Grand { 41ddde725dSArmin Le Grand SvgSvgNode::SvgSvgNode( 42ddde725dSArmin Le Grand SvgDocument& rDocument, 43ddde725dSArmin Le Grand SvgNode* pParent) 44ddde725dSArmin Le Grand : SvgNode(SVGTokenSvg, rDocument, pParent), 45ddde725dSArmin Le Grand maSvgStyleAttributes(*this), 46ddde725dSArmin Le Grand mpViewBox(0), 47ddde725dSArmin Le Grand maSvgAspectRatio(), 48ddde725dSArmin Le Grand maX(), 49ddde725dSArmin Le Grand maY(), 50ddde725dSArmin Le Grand maWidth(), 51ddde725dSArmin Le Grand maHeight(), 52ddde725dSArmin Le Grand maVersion() 53ddde725dSArmin Le Grand { 54ddde725dSArmin Le Grand if(!getParent()) 55ddde725dSArmin Le Grand { 56ddde725dSArmin Le Grand // initial fill is black 57ddde725dSArmin Le Grand maSvgStyleAttributes.setFill(SvgPaint(basegfx::BColor(0.0, 0.0, 0.0), true, true)); 58ddde725dSArmin Le Grand } 59ddde725dSArmin Le Grand } 60ddde725dSArmin Le Grand 61ddde725dSArmin Le Grand SvgSvgNode::~SvgSvgNode() 62ddde725dSArmin Le Grand { 63ddde725dSArmin Le Grand if(mpViewBox) delete mpViewBox; 64ddde725dSArmin Le Grand } 65ddde725dSArmin Le Grand 66ddde725dSArmin Le Grand const SvgStyleAttributes* SvgSvgNode::getSvgStyleAttributes() const 67ddde725dSArmin Le Grand { 68ddde725dSArmin Le Grand return &maSvgStyleAttributes; 69ddde725dSArmin Le Grand } 70ddde725dSArmin Le Grand 71ddde725dSArmin Le Grand void SvgSvgNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) 72ddde725dSArmin Le Grand { 73ddde725dSArmin Le Grand // call parent 74ddde725dSArmin Le Grand SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); 75ddde725dSArmin Le Grand 76ddde725dSArmin Le Grand // read style attributes 77ddde725dSArmin Le Grand maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); 78ddde725dSArmin Le Grand 79ddde725dSArmin Le Grand // parse own 80ddde725dSArmin Le Grand switch(aSVGToken) 81ddde725dSArmin Le Grand { 82ddde725dSArmin Le Grand case SVGTokenStyle: 83ddde725dSArmin Le Grand { 84ddde725dSArmin Le Grand maSvgStyleAttributes.readStyle(aContent); 85ddde725dSArmin Le Grand break; 86ddde725dSArmin Le Grand } 87ddde725dSArmin Le Grand case SVGTokenViewBox: 88ddde725dSArmin Le Grand { 89ddde725dSArmin Le Grand const basegfx::B2DRange aRange(readViewBox(aContent, *this)); 90ddde725dSArmin Le Grand 91ddde725dSArmin Le Grand if(!aRange.isEmpty()) 92ddde725dSArmin Le Grand { 93ddde725dSArmin Le Grand setViewBox(&aRange); 94ddde725dSArmin Le Grand } 95ddde725dSArmin Le Grand break; 96ddde725dSArmin Le Grand } 97ddde725dSArmin Le Grand case SVGTokenPreserveAspectRatio: 98ddde725dSArmin Le Grand { 99ddde725dSArmin Le Grand setSvgAspectRatio(readSvgAspectRatio(aContent)); 100ddde725dSArmin Le Grand break; 101ddde725dSArmin Le Grand } 102ddde725dSArmin Le Grand case SVGTokenX: 103ddde725dSArmin Le Grand { 104ddde725dSArmin Le Grand SvgNumber aNum; 105ddde725dSArmin Le Grand 106ddde725dSArmin Le Grand if(readSingleNumber(aContent, aNum)) 107ddde725dSArmin Le Grand { 108ddde725dSArmin Le Grand setX(aNum); 109ddde725dSArmin Le Grand } 110ddde725dSArmin Le Grand break; 111ddde725dSArmin Le Grand } 112ddde725dSArmin Le Grand case SVGTokenY: 113ddde725dSArmin Le Grand { 114ddde725dSArmin Le Grand SvgNumber aNum; 115ddde725dSArmin Le Grand 116ddde725dSArmin Le Grand if(readSingleNumber(aContent, aNum)) 117ddde725dSArmin Le Grand { 118ddde725dSArmin Le Grand setY(aNum); 119ddde725dSArmin Le Grand } 120ddde725dSArmin Le Grand break; 121ddde725dSArmin Le Grand } 122ddde725dSArmin Le Grand case SVGTokenWidth: 123ddde725dSArmin Le Grand { 124ddde725dSArmin Le Grand SvgNumber aNum; 125ddde725dSArmin Le Grand 126ddde725dSArmin Le Grand if(readSingleNumber(aContent, aNum)) 127ddde725dSArmin Le Grand { 128ddde725dSArmin Le Grand if(aNum.isPositive()) 129ddde725dSArmin Le Grand { 130ddde725dSArmin Le Grand setWidth(aNum); 131ddde725dSArmin Le Grand } 132ddde725dSArmin Le Grand } 133ddde725dSArmin Le Grand break; 134ddde725dSArmin Le Grand } 135ddde725dSArmin Le Grand case SVGTokenHeight: 136ddde725dSArmin Le Grand { 137ddde725dSArmin Le Grand SvgNumber aNum; 138ddde725dSArmin Le Grand 139ddde725dSArmin Le Grand if(readSingleNumber(aContent, aNum)) 140ddde725dSArmin Le Grand { 141ddde725dSArmin Le Grand if(aNum.isPositive()) 142ddde725dSArmin Le Grand { 143ddde725dSArmin Le Grand setHeight(aNum); 144ddde725dSArmin Le Grand } 145ddde725dSArmin Le Grand } 146ddde725dSArmin Le Grand break; 147ddde725dSArmin Le Grand } 148ddde725dSArmin Le Grand case SVGTokenVersion: 149ddde725dSArmin Le Grand { 150ddde725dSArmin Le Grand SvgNumber aNum; 151ddde725dSArmin Le Grand 152ddde725dSArmin Le Grand if(readSingleNumber(aContent, aNum)) 153ddde725dSArmin Le Grand { 154ddde725dSArmin Le Grand setVersion(aNum); 155ddde725dSArmin Le Grand } 156ddde725dSArmin Le Grand break; 157e2bf1e9dSArmin Le Grand } 158e2bf1e9dSArmin Le Grand default: 159e2bf1e9dSArmin Le Grand { 160e2bf1e9dSArmin Le Grand break; 161ddde725dSArmin Le Grand } 162ddde725dSArmin Le Grand } 163ddde725dSArmin Le Grand } 164ddde725dSArmin Le Grand 1652169cc62SArmin Le Grand void SvgSvgNode::seekReferenceWidth(double& fWidth, bool& bHasFound) const 1662169cc62SArmin Le Grand { 1672169cc62SArmin Le Grand if (!getParent() || bHasFound) 1682169cc62SArmin Le Grand { 1692169cc62SArmin Le Grand return; 1702169cc62SArmin Le Grand } 1712169cc62SArmin Le Grand const SvgSvgNode* pParentSvgSvgNode = 0; 1722169cc62SArmin Le Grand // enclosing svg might have relative width, need to cumulate them till they are 1732169cc62SArmin Le Grand // resolved somewhere up in the node tree 1742169cc62SArmin Le Grand double fPercentage(1.0); 1752169cc62SArmin Le Grand for(const SvgNode* pParent = getParent(); pParent && !bHasFound; pParent = pParent->getParent()) 1762169cc62SArmin Le Grand { 1772169cc62SArmin Le Grand // dynamic_cast results Null-pointer for not SvgSvgNode and so skips them in if condition 1782169cc62SArmin Le Grand pParentSvgSvgNode = dynamic_cast< const SvgSvgNode* >(pParent); 1792169cc62SArmin Le Grand if (pParentSvgSvgNode) 1802169cc62SArmin Le Grand { 1812169cc62SArmin Le Grand if (pParentSvgSvgNode->getViewBox()) 1822169cc62SArmin Le Grand { 1832169cc62SArmin Le Grand // viewbox values are already in 'user unit'. 1842169cc62SArmin Le Grand fWidth = pParentSvgSvgNode->getViewBox()->getWidth() * fPercentage; 1852169cc62SArmin Le Grand bHasFound = true; 1862169cc62SArmin Le Grand } 1872169cc62SArmin Le Grand else 1882169cc62SArmin Le Grand { 1892169cc62SArmin Le Grand // take absolute value or cummulate percentage 1902169cc62SArmin Le Grand if (pParentSvgSvgNode->getWidth().isSet()) 1912169cc62SArmin Le Grand { 1922169cc62SArmin Le Grand if (Unit_percent == pParentSvgSvgNode->getWidth().getUnit()) 1932169cc62SArmin Le Grand { 1942169cc62SArmin Le Grand fPercentage *= pParentSvgSvgNode->getWidth().getNumber() * 0.01; 1952169cc62SArmin Le Grand } 1962169cc62SArmin Le Grand else 1972169cc62SArmin Le Grand { 1982169cc62SArmin Le Grand fWidth = pParentSvgSvgNode->getWidth().solveNonPercentage(*pParentSvgSvgNode) * fPercentage; 1992169cc62SArmin Le Grand bHasFound = true; 2002169cc62SArmin Le Grand } 2012169cc62SArmin Le Grand } // not set => width=100% => factor 1, no need for else 2022169cc62SArmin Le Grand } 2032169cc62SArmin Le Grand } 2042169cc62SArmin Le Grand } 2052169cc62SArmin Le Grand } 2062169cc62SArmin Le Grand 2072169cc62SArmin Le Grand void SvgSvgNode::seekReferenceHeight(double& fHeight, bool& bHasFound) const 2082169cc62SArmin Le Grand { 2092169cc62SArmin Le Grand if (!getParent() || bHasFound) 2102169cc62SArmin Le Grand { 2112169cc62SArmin Le Grand return; 2122169cc62SArmin Le Grand } 2132169cc62SArmin Le Grand const SvgSvgNode* pParentSvgSvgNode = 0; 2142169cc62SArmin Le Grand // enclosing svg might have relative width and height, need to cumulate them till they are 2152169cc62SArmin Le Grand // resolved somewhere up in the node tree 2162169cc62SArmin Le Grand double fPercentage(1.0); 2172169cc62SArmin Le Grand for(const SvgNode* pParent = getParent(); pParent && !bHasFound; pParent = pParent->getParent()) 2182169cc62SArmin Le Grand { 2192169cc62SArmin Le Grand // dynamic_cast results Null-pointer for not SvgSvgNode and so skips them in if condition 2202169cc62SArmin Le Grand pParentSvgSvgNode = dynamic_cast< const SvgSvgNode* >(pParent); 2212169cc62SArmin Le Grand if (pParentSvgSvgNode) 2222169cc62SArmin Le Grand { 2232169cc62SArmin Le Grand if (pParentSvgSvgNode->getViewBox()) 2242169cc62SArmin Le Grand { 2252169cc62SArmin Le Grand // viewbox values are already in 'user unit'. 2262169cc62SArmin Le Grand fHeight = pParentSvgSvgNode->getViewBox()->getHeight() * fPercentage; 2272169cc62SArmin Le Grand bHasFound = true; 2282169cc62SArmin Le Grand } 2292169cc62SArmin Le Grand else 2302169cc62SArmin Le Grand { 2312169cc62SArmin Le Grand // take absolute value or cummulate percentage 2322169cc62SArmin Le Grand if (pParentSvgSvgNode->getHeight().isSet()) 2332169cc62SArmin Le Grand { 2342169cc62SArmin Le Grand if (Unit_percent == pParentSvgSvgNode->getHeight().getUnit()) 2352169cc62SArmin Le Grand { 2362169cc62SArmin Le Grand fPercentage *= pParentSvgSvgNode->getHeight().getNumber() * 0.01; 2372169cc62SArmin Le Grand } 2382169cc62SArmin Le Grand else 2392169cc62SArmin Le Grand { 2402169cc62SArmin Le Grand fHeight = pParentSvgSvgNode->getHeight().solveNonPercentage(*pParentSvgSvgNode) * fPercentage; 2412169cc62SArmin Le Grand bHasFound = true; 2422169cc62SArmin Le Grand } 2432169cc62SArmin Le Grand } // not set => height=100% => factor 1, no need for else 2442169cc62SArmin Le Grand } 2452169cc62SArmin Le Grand } 2462169cc62SArmin Le Grand } 2472169cc62SArmin Le Grand } 2482169cc62SArmin Le Grand 2492169cc62SArmin Le Grand // ToDo: Consider attribute overflow in method decomposeSvgNode 250ddde725dSArmin Le Grand void SvgSvgNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const 251ddde725dSArmin Le Grand { 252ddde725dSArmin Le Grand drawinglayer::primitive2d::Primitive2DSequence aSequence; 253ddde725dSArmin Le Grand 254ddde725dSArmin Le Grand // decompose childs 255ddde725dSArmin Le Grand SvgNode::decomposeSvgNode(aSequence, bReferenced); 256ddde725dSArmin Le Grand 257ddde725dSArmin Le Grand if(aSequence.hasElements()) 258ddde725dSArmin Le Grand { 259ddde725dSArmin Le Grand if(getParent()) 260ddde725dSArmin Le Grand { 2612169cc62SArmin Le Grand // #122594# if width/height is not given, it's 100% (see 5.1.2 The 'svg' element in SVG1.1 spec). 262bca0eb5dSArmin Le Grand // If it is relative, the question is to what. The previous implementatin assumed relative to the 263bca0eb5dSArmin Le Grand // local ViewBox which is implied by (4.2 Basic data types): 264bca0eb5dSArmin Le Grand // 265bca0eb5dSArmin Le Grand // "Note that the non-property <length> definition also allows a percentage unit identifier. 266bca0eb5dSArmin Le Grand // The meaning of a percentage length value depends on the attribute for which the percentage 267bca0eb5dSArmin Le Grand // length value has been specified. Two common cases are: (a) when a percentage length value 268bca0eb5dSArmin Le Grand // represents a percentage of the viewport width or height (refer to the section that discusses 269bca0eb5dSArmin Le Grand // units in general), and (b) when a percentage length value represents a percentage of the 270bca0eb5dSArmin Le Grand // bounding box width or height on a given object (refer to the section that describes object 271bca0eb5dSArmin Le Grand // bounding box units)." 2722169cc62SArmin Le Grand 2732169cc62SArmin Le Grand // Comparisons with commom browsers show, that it's mostly interpreted relative to the viewport 2742169cc62SArmin Le Grand // of the parent, and so does the new implementation. 2752169cc62SArmin Le Grand 2762169cc62SArmin Le Grand // Extract known viewport data 2772169cc62SArmin Le Grand // bXXXIsAbsolute tracks whether relative values could be resolved to absolute values 2782169cc62SArmin Le Grand 2792169cc62SArmin Le Grand // If width or height is not provided, the default 100% is used, see SVG 1.1 section 5.1.2 2802169cc62SArmin Le Grand // value 0.0 here is only to initialize variable 2812169cc62SArmin Le Grand bool bWidthIsAbsolute(getWidth().isSet() && Unit_percent != getWidth().getUnit()); 2822169cc62SArmin Le Grand double fW( bWidthIsAbsolute ? getWidth().solveNonPercentage(*this) : 0.0); 2832169cc62SArmin Le Grand 2842169cc62SArmin Le Grand bool bHeightIsAbsolute(getHeight().isSet() && Unit_percent != getHeight().getUnit()); 2852169cc62SArmin Le Grand double fH( bHeightIsAbsolute ? getHeight().solveNonPercentage(*this) : 0.0); 2862169cc62SArmin Le Grand 2872169cc62SArmin Le Grand // If x or y not provided, then default 0.0 is used, see SVG 1.1 Section 5.1.2 2882169cc62SArmin Le Grand bool bXIsAbsolute((getX().isSet() && Unit_percent != getX().getUnit()) || !getX().isSet()); 2892169cc62SArmin Le Grand double fX( bXIsAbsolute && getX().isSet() ? getX().solveNonPercentage(*this) : 0.0); 2902169cc62SArmin Le Grand 2912169cc62SArmin Le Grand bool bYIsAbsolute((getY().isSet() && Unit_percent != getY().getUnit()) || !getY().isSet()); 2922169cc62SArmin Le Grand double fY( bYIsAbsolute && getY().isSet() ? getY().solveNonPercentage(*this) : 0.0); 2932169cc62SArmin Le Grand 2942169cc62SArmin Le Grand if ( !bXIsAbsolute || !bWidthIsAbsolute) 295bca0eb5dSArmin Le Grand { 2962169cc62SArmin Le Grand // get width of enclosing svg and resolve percentage in x and width; 2972169cc62SArmin Le Grand double fWReference(0.0); 2982169cc62SArmin Le Grand bool bHasFoundWidth(false); 2992169cc62SArmin Le Grand seekReferenceWidth(fWReference, bHasFoundWidth); 3002169cc62SArmin Le Grand if (!bHasFoundWidth) 301bca0eb5dSArmin Le Grand { 3022169cc62SArmin Le Grand // Even outermost svg has not all information to resolve relative values, 3032169cc62SArmin Le Grand // I use content itself as fallback to set missing values for viewport 3042169cc62SArmin Le Grand // Any better idea for such ill structures svg documents? 3052169cc62SArmin Le Grand const basegfx::B2DRange aChildRange( 3062169cc62SArmin Le Grand drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence( 3072169cc62SArmin Le Grand aSequence, 3082169cc62SArmin Le Grand drawinglayer::geometry::ViewInformation2D())); 3092169cc62SArmin Le Grand fWReference = aChildRange.getWidth(); 310bca0eb5dSArmin Le Grand } 3112169cc62SArmin Le Grand // referenced values are already in 'user unit' 3122169cc62SArmin Le Grand if (!bXIsAbsolute) 313bca0eb5dSArmin Le Grand { 3142169cc62SArmin Le Grand fX = getX().getNumber() * 0.01 * fWReference; 3152169cc62SArmin Le Grand } 3162169cc62SArmin Le Grand if (!bWidthIsAbsolute) 3172169cc62SArmin Le Grand { 3182169cc62SArmin Le Grand fW = (getWidth().isSet() ? getWidth().getNumber() *0.01 : 1.0) * fWReference; 319bca0eb5dSArmin Le Grand } 320bca0eb5dSArmin Le Grand } 321bca0eb5dSArmin Le Grand 3222169cc62SArmin Le Grand if ( !bYIsAbsolute || !bHeightIsAbsolute) 323bca0eb5dSArmin Le Grand { 3242169cc62SArmin Le Grand // get height of enclosing svg and resolve percentage in y and height 3252169cc62SArmin Le Grand double fHReference(0.0); 3262169cc62SArmin Le Grand bool bHasFoundHeight(false); 3272169cc62SArmin Le Grand seekReferenceHeight(fHReference, bHasFoundHeight); 3282169cc62SArmin Le Grand if (!bHasFoundHeight) 3292169cc62SArmin Le Grand { 3302169cc62SArmin Le Grand // Even outermost svg has not all information to resolve relative values, 3312169cc62SArmin Le Grand // I use content itself as fallback to set missing values for viewport 3322169cc62SArmin Le Grand // Any better idea for such ill structures svg documents? 3332169cc62SArmin Le Grand const basegfx::B2DRange aChildRange( 3342169cc62SArmin Le Grand drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence( 3352169cc62SArmin Le Grand aSequence, 3362169cc62SArmin Le Grand drawinglayer::geometry::ViewInformation2D())); 3372169cc62SArmin Le Grand fHReference = aChildRange.getHeight(); 3382169cc62SArmin Le Grand } 339bca0eb5dSArmin Le Grand 3402169cc62SArmin Le Grand // referenced values are already in 'user unit' 3412169cc62SArmin Le Grand if (!bYIsAbsolute) 342bca0eb5dSArmin Le Grand { 3432169cc62SArmin Le Grand fY = getY().getNumber() * 0.01 * fHReference; 3442169cc62SArmin Le Grand } 3452169cc62SArmin Le Grand if (!bHeightIsAbsolute) 3462169cc62SArmin Le Grand { 3472169cc62SArmin Le Grand fH = (getHeight().isSet() ? getHeight().getNumber() *0.01 : 1.0) * fHReference; 348bca0eb5dSArmin Le Grand } 349bca0eb5dSArmin Le Grand } 350bca0eb5dSArmin Le Grand 351ddde725dSArmin Le Grand if(getViewBox()) 352ddde725dSArmin Le Grand { 3532169cc62SArmin Le Grand // SVG 1.1 defines in section 7.7 that a negative value for width or height 3542169cc62SArmin Le Grand // in viewBox is an error and that 0.0 disables rendering 3552169cc62SArmin Le Grand if(basegfx::fTools::more(getViewBox()->getWidth(),0.0) && basegfx::fTools::more(getViewBox()->getHeight(),0.0)) 356ddde725dSArmin Le Grand { 3572169cc62SArmin Le Grand // create target range homing x,y, width and height as calculated above 358ddde725dSArmin Le Grand const basegfx::B2DRange aTarget(fX, fY, fX + fW, fY + fH); 359ddde725dSArmin Le Grand 360ddde725dSArmin Le Grand if(aTarget.equal(*getViewBox())) 361ddde725dSArmin Le Grand { 362ddde725dSArmin Le Grand // no mapping needed, append 363ddde725dSArmin Le Grand drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aSequence); 364ddde725dSArmin Le Grand } 365ddde725dSArmin Le Grand else 366ddde725dSArmin Le Grand { 367ddde725dSArmin Le Grand // create mapping 3682169cc62SArmin Le Grand // #i122610 SVG 1.1 defines in section 5.1.2 that if the attribute perserveAspectRatio is not specified, 3692169cc62SArmin Le Grand // then the effect is as if a value of 'xMidYMid meet' were specified. 3702169cc62SArmin Le Grand SvgAspectRatio aRatioDefault(Align_xMidYMid,false,true); 3712169cc62SArmin Le Grand const SvgAspectRatio& rRatio = getSvgAspectRatio().isSet()? getSvgAspectRatio() : aRatioDefault; 3722169cc62SArmin Le Grand 3732169cc62SArmin Le Grand // let mapping be created from SvgAspectRatio 3742169cc62SArmin Le Grand const basegfx::B2DHomMatrix aEmbeddingTransform( 3752169cc62SArmin Le Grand rRatio.createMapping(aTarget, *getViewBox())); 3762169cc62SArmin Le Grand 3772169cc62SArmin Le Grand // prepare embedding in transformation 3782169cc62SArmin Le Grand const drawinglayer::primitive2d::Primitive2DReference xRef( 3792169cc62SArmin Le Grand new drawinglayer::primitive2d::TransformPrimitive2D( 3802169cc62SArmin Le Grand aEmbeddingTransform, 3812169cc62SArmin Le Grand aSequence)); 382ddde725dSArmin Le Grand 3832169cc62SArmin Le Grand if(rRatio.isMeetOrSlice()) 384ddde725dSArmin Le Grand { 3852169cc62SArmin Le Grand // embed in transformation 3862169cc62SArmin Le Grand drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xRef); 387ddde725dSArmin Le Grand } 388ddde725dSArmin Le Grand else 389ddde725dSArmin Le Grand { 3902169cc62SArmin Le Grand // need to embed in MaskPrimitive2D, too 3912169cc62SArmin Le Grand const drawinglayer::primitive2d::Primitive2DReference xMask( 3922169cc62SArmin Le Grand new drawinglayer::primitive2d::MaskPrimitive2D( 3932169cc62SArmin Le Grand basegfx::B2DPolyPolygon(basegfx::tools::createPolygonFromRect(aTarget)), 3942169cc62SArmin Le Grand drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1))); 395ddde725dSArmin Le Grand 3962169cc62SArmin Le Grand drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xMask); 397ddde725dSArmin Le Grand } 398ddde725dSArmin Le Grand } 399ddde725dSArmin Le Grand } 400ddde725dSArmin Le Grand } 4012169cc62SArmin Le Grand else // no viewBox attribute 402ddde725dSArmin Le Grand { 403ddde725dSArmin Le Grand // Svg defines that a negative value is an error and that 0.0 disables rendering 404ddde725dSArmin Le Grand if(basegfx::fTools::more(fW, 0.0) && basegfx::fTools::more(fH, 0.0)) 405ddde725dSArmin Le Grand { 406ddde725dSArmin Le Grand if(!basegfx::fTools::equalZero(fX) || !basegfx::fTools::equalZero(fY)) 407ddde725dSArmin Le Grand { 408ddde725dSArmin Le Grand // embed in transform 409ddde725dSArmin Le Grand const drawinglayer::primitive2d::Primitive2DReference xRef( 410ddde725dSArmin Le Grand new drawinglayer::primitive2d::TransformPrimitive2D( 411ddde725dSArmin Le Grand basegfx::tools::createTranslateB2DHomMatrix(fX, fY), 412ddde725dSArmin Le Grand aSequence)); 413ddde725dSArmin Le Grand 414ddde725dSArmin Le Grand aSequence = drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1); 415ddde725dSArmin Le Grand } 416ddde725dSArmin Le Grand 417ddde725dSArmin Le Grand // embed in MaskPrimitive2D to clip 418ddde725dSArmin Le Grand const drawinglayer::primitive2d::Primitive2DReference xMask( 419ddde725dSArmin Le Grand new drawinglayer::primitive2d::MaskPrimitive2D( 420ddde725dSArmin Le Grand basegfx::B2DPolyPolygon( 421ddde725dSArmin Le Grand basegfx::tools::createPolygonFromRect( 422ddde725dSArmin Le Grand basegfx::B2DRange(fX, fY, fX + fW, fY + fH))), 423ddde725dSArmin Le Grand aSequence)); 424ddde725dSArmin Le Grand 425ddde725dSArmin Le Grand // append 426ddde725dSArmin Le Grand drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xMask); 427ddde725dSArmin Le Grand } 428ddde725dSArmin Le Grand } 429ddde725dSArmin Le Grand } 4302169cc62SArmin Le Grand else // Outermost SVG element 431ddde725dSArmin Le Grand { 4322169cc62SArmin Le Grand double fW = 0.0; // effective value depends on viewBox 4332169cc62SArmin Le Grand double fH = 0.0; 434ddde725dSArmin Le Grand 435ddde725dSArmin Le Grand // Svg defines that a negative value is an error and that 0.0 disables rendering 4362169cc62SArmin Le Grand // isPositive() not usable because it allows 0.0 in contrast to mathematical definition of 'positive' 4372169cc62SArmin Le Grand const bool bWidthInvalid(getWidth().isSet() && basegfx::fTools::lessOrEqual(getWidth().getNumber(), 0.0)); 4382169cc62SArmin Le Grand const bool bHeightInvalid(getHeight().isSet() && basegfx::fTools::lessOrEqual(getHeight().getNumber(), 0.0)); 4392169cc62SArmin Le Grand if(!bWidthInvalid && !bHeightInvalid) 440ddde725dSArmin Le Grand { 4412169cc62SArmin Le Grand basegfx::B2DRange aSvgCanvasRange; // effective value depends on viewBox 442ddde725dSArmin Le Grand if(getViewBox()) 443ddde725dSArmin Le Grand { 4442169cc62SArmin Le Grand // SVG 1.1 defines in section 7.7 that a negative value for width or height 4452169cc62SArmin Le Grand // in viewBox is an error and that 0.0 disables rendering 4462169cc62SArmin Le Grand const double fViewBoxWidth = getViewBox()->getWidth(); 4472169cc62SArmin Le Grand const double fViewBoxHeight = getViewBox()->getHeight(); 4482169cc62SArmin Le Grand if(basegfx::fTools::more(fViewBoxWidth,0.0) && basegfx::fTools::more(fViewBoxHeight,0.0)) 449ddde725dSArmin Le Grand { 4502169cc62SArmin Le Grand // The intrinsic aspect ratio of the svg element is given by absolute values of both width and height 4512169cc62SArmin Le Grand // or if one or both of them is relative by the width and height of the viewBox 4522169cc62SArmin Le Grand // see SVG 1.1 section 7.12 4532169cc62SArmin Le Grand const bool bWidthIsAbsolute(getWidth().isSet() && Unit_percent != getWidth().getUnit()); 4542169cc62SArmin Le Grand const bool bHeightIsAbsolute(getHeight().isSet() && Unit_percent != getHeight().getUnit()); 4552169cc62SArmin Le Grand if(bWidthIsAbsolute && bHeightIsAbsolute) 456ddde725dSArmin Le Grand { 4572169cc62SArmin Le Grand fW =getWidth().solveNonPercentage(*this); 4582169cc62SArmin Le Grand fH =getHeight().solveNonPercentage(*this); 4592169cc62SArmin Le Grand } 4602169cc62SArmin Le Grand else if (bWidthIsAbsolute) 4612169cc62SArmin Le Grand { 4622169cc62SArmin Le Grand fW = getWidth().solveNonPercentage(*this); 4632169cc62SArmin Le Grand fH = fW * fViewBoxWidth / fViewBoxHeight ; 4642169cc62SArmin Le Grand } 4652169cc62SArmin Le Grand else if (bHeightIsAbsolute) 4662169cc62SArmin Le Grand { 4672169cc62SArmin Le Grand fH = getHeight().solveNonPercentage(*this); 4682169cc62SArmin Le Grand fW = fH * fViewBoxWidth / fViewBoxHeight ; 469ddde725dSArmin Le Grand } 470ddde725dSArmin Le Grand else 471ddde725dSArmin Le Grand { 4722169cc62SArmin Le Grand fW = fViewBoxWidth; 4732169cc62SArmin Le Grand fH = fViewBoxHeight; 474ddde725dSArmin Le Grand } 4752169cc62SArmin Le Grand // SVG 1.1 defines in section 5.1.2 that x,y has no meanig for the outermost SVG element. 4762169cc62SArmin Le Grand aSvgCanvasRange = basegfx::B2DRange(0.0, 0.0, fW, fH); 4772169cc62SArmin Le Grand 4782169cc62SArmin Le Grand // create mapping 4792169cc62SArmin Le Grand // SVG 1.1 defines in section 5.1.2 that if the attribute perserveAspectRatio is not specified, 4802169cc62SArmin Le Grand // then the effect is as if a value of 'xMidYMid meet' were specified. 4812169cc62SArmin Le Grand SvgAspectRatio aRatioDefault(Align_xMidYMid,false,true); 4822169cc62SArmin Le Grand const SvgAspectRatio& rRatio = getSvgAspectRatio().isSet()? getSvgAspectRatio() : aRatioDefault; 4832169cc62SArmin Le Grand 4842169cc62SArmin Le Grand basegfx::B2DHomMatrix aViewBoxMapping; 4852169cc62SArmin Le Grand aViewBoxMapping = rRatio.createMapping(aSvgCanvasRange, *getViewBox()); 4862169cc62SArmin Le Grand // no need to check ratio here for slice, the outermost Svg will 4872169cc62SArmin Le Grand // be clipped anyways (see below) 488ddde725dSArmin Le Grand 489ddde725dSArmin Le Grand // scale content to viewBox definitions 490ddde725dSArmin Le Grand const drawinglayer::primitive2d::Primitive2DReference xTransform( 491ddde725dSArmin Le Grand new drawinglayer::primitive2d::TransformPrimitive2D( 492ddde725dSArmin Le Grand aViewBoxMapping, 493ddde725dSArmin Le Grand aSequence)); 494ddde725dSArmin Le Grand 495ddde725dSArmin Le Grand aSequence = drawinglayer::primitive2d::Primitive2DSequence(&xTransform, 1); 496ddde725dSArmin Le Grand } 497ddde725dSArmin Le Grand } 4982169cc62SArmin Le Grand else // no viewbox 4992169cc62SArmin Le Grand { 5002169cc62SArmin Le Grand // There exists no parent to resolve relative width or height. 5012169cc62SArmin Le Grand // Use child size as fallback. 5022169cc62SArmin Le Grand const bool bWidthIsAbsolute(getWidth().isSet() && Unit_percent != getWidth().getUnit()); 5032169cc62SArmin Le Grand const bool bHeightIsAbsolute(getHeight().isSet() && Unit_percent != getHeight().getUnit()); 5042169cc62SArmin Le Grand if (bWidthIsAbsolute && bHeightIsAbsolute) 5052169cc62SArmin Le Grand { 5062169cc62SArmin Le Grand fW =getWidth().solveNonPercentage(*this); 5072169cc62SArmin Le Grand fH =getHeight().solveNonPercentage(*this); 5082169cc62SArmin Le Grand 5092169cc62SArmin Le Grand } 5102169cc62SArmin Le Grand else 5112169cc62SArmin Le Grand { 5122169cc62SArmin Le Grand const basegfx::B2DRange aChildRange( 5132169cc62SArmin Le Grand drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence( 5142169cc62SArmin Le Grand aSequence, 5152169cc62SArmin Le Grand drawinglayer::geometry::ViewInformation2D())); 5162169cc62SArmin Le Grand const double fChildWidth(aChildRange.getWidth()); 5172169cc62SArmin Le Grand const double fChildHeight(aChildRange.getHeight()); 5182169cc62SArmin Le Grand fW = bWidthIsAbsolute ? getWidth().solveNonPercentage(*this) : fChildWidth; 5192169cc62SArmin Le Grand fH = bHeightIsAbsolute ? getHeight().solveNonPercentage(*this) : fChildHeight; 5202169cc62SArmin Le Grand } 5212169cc62SArmin Le Grand // SVG 1.1 defines in section 5.1.2 that x,y has no meanig for the outermost SVG element. 5222169cc62SArmin Le Grand aSvgCanvasRange = basegfx::B2DRange(0.0, 0.0, fW, fH); 5232169cc62SArmin Le Grand } 524ddde725dSArmin Le Grand 525ddde725dSArmin Le Grand // to be completely correct in Svg sense it is necessary to clip 526ddde725dSArmin Le Grand // the whole content to the given canvas. I choose here to do this 527ddde725dSArmin Le Grand // initially despite I found various examples of Svg files out there 528ddde725dSArmin Le Grand // which have no correct values for this clipping. It's correct 529ddde725dSArmin Le Grand // due to the Svg spec. 530ddde725dSArmin Le Grand bool bDoCorrectCanvasClipping(true); 531ddde725dSArmin Le Grand 532ddde725dSArmin Le Grand if(bDoCorrectCanvasClipping) 533ddde725dSArmin Le Grand { 534ddde725dSArmin Le Grand // different from Svg we have the possibility with primitives to get 53541923119SArmin Le Grand // a correct bounding box for the geometry. Get it for evtl. taking action 536ddde725dSArmin Le Grand const basegfx::B2DRange aContentRange( 537ddde725dSArmin Le Grand drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence( 538ddde725dSArmin Le Grand aSequence, 539ddde725dSArmin Le Grand drawinglayer::geometry::ViewInformation2D())); 540ddde725dSArmin Le Grand 54141923119SArmin Le Grand if(aSvgCanvasRange.isInside(aContentRange)) 542ddde725dSArmin Le Grand { 54341923119SArmin Le Grand // no clip needed, but an invisible HiddenGeometryPrimitive2D 54441923119SArmin Le Grand // to allow getting the full Svg range using the primitive mechanisms. 54541923119SArmin Le Grand // This is needed since e.g. an SdrObject using this as graphic will 54641923119SArmin Le Grand // create a mapping transformation to exactly map the content to it's 54741923119SArmin Le Grand // real life size 54841923119SArmin Le Grand const drawinglayer::primitive2d::Primitive2DReference xLine( 54941923119SArmin Le Grand new drawinglayer::primitive2d::PolygonHairlinePrimitive2D( 55041923119SArmin Le Grand basegfx::tools::createPolygonFromRect( 55141923119SArmin Le Grand aSvgCanvasRange), 55241923119SArmin Le Grand basegfx::BColor(0.0, 0.0, 0.0))); 55341923119SArmin Le Grand const drawinglayer::primitive2d::Primitive2DReference xHidden( 55441923119SArmin Le Grand new drawinglayer::primitive2d::HiddenGeometryPrimitive2D( 55541923119SArmin Le Grand drawinglayer::primitive2d::Primitive2DSequence(&xLine, 1))); 55641923119SArmin Le Grand 55741923119SArmin Le Grand drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aSequence, xHidden); 55841923119SArmin Le Grand } 55941923119SArmin Le Grand else if(aSvgCanvasRange.overlaps(aContentRange)) 56041923119SArmin Le Grand { 56141923119SArmin Le Grand // Clip is necessary. This will make Svg images evtl. smaller 56241923119SArmin Le Grand // than wanted from Svg (the free space which may be around it is 56341923119SArmin Le Grand // conform to the Svg spec), but avoids an expensive and unneccessary 56441923119SArmin Le Grand // clip. Keep the full Svg range here to get the correct mappings 56541923119SArmin Le Grand // to objects using this. Optimizations can be done in the processors 566ddde725dSArmin Le Grand const drawinglayer::primitive2d::Primitive2DReference xMask( 567ddde725dSArmin Le Grand new drawinglayer::primitive2d::MaskPrimitive2D( 568ddde725dSArmin Le Grand basegfx::B2DPolyPolygon( 569ddde725dSArmin Le Grand basegfx::tools::createPolygonFromRect( 570ddde725dSArmin Le Grand aSvgCanvasRange)), 571ddde725dSArmin Le Grand aSequence)); 572ddde725dSArmin Le Grand 573ddde725dSArmin Le Grand aSequence = drawinglayer::primitive2d::Primitive2DSequence(&xMask, 1); 574ddde725dSArmin Le Grand } 57541923119SArmin Le Grand else 57641923119SArmin Le Grand { 57741923119SArmin Le Grand // not inside, no overlap. Empty Svg 57841923119SArmin Le Grand aSequence.realloc(0); 57941923119SArmin Le Grand } 580ddde725dSArmin Le Grand } 581ddde725dSArmin Le Grand 58241923119SArmin Le Grand if(aSequence.hasElements()) 583ddde725dSArmin Le Grand { 584ddde725dSArmin Le Grand // embed in transform primitive to scale to 1/100th mm 5852169cc62SArmin Le Grand // where 1 inch == 25.4 mm to get from Svg coordinates (px) to 5862169cc62SArmin Le Grand // drawinglayer coordinates 5872169cc62SArmin Le Grand const double fScaleTo100thmm(25.4 * 100.0 / F_SVG_PIXEL_PER_INCH); 588ddde725dSArmin Le Grand const basegfx::B2DHomMatrix aTransform( 589ddde725dSArmin Le Grand basegfx::tools::createScaleB2DHomMatrix( 590ddde725dSArmin Le Grand fScaleTo100thmm, 591ddde725dSArmin Le Grand fScaleTo100thmm)); 592ddde725dSArmin Le Grand 593ddde725dSArmin Le Grand const drawinglayer::primitive2d::Primitive2DReference xTransform( 594ddde725dSArmin Le Grand new drawinglayer::primitive2d::TransformPrimitive2D( 595ddde725dSArmin Le Grand aTransform, 596ddde725dSArmin Le Grand aSequence)); 597ddde725dSArmin Le Grand 598ddde725dSArmin Le Grand aSequence = drawinglayer::primitive2d::Primitive2DSequence(&xTransform, 1); 599ddde725dSArmin Le Grand 60041923119SArmin Le Grand // append to result 60141923119SArmin Le Grand drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aSequence); 60241923119SArmin Le Grand } 603ddde725dSArmin Le Grand } 604ddde725dSArmin Le Grand } 605ddde725dSArmin Le Grand } 606ddde725dSArmin Le Grand } 607ddde725dSArmin Le Grand 608*e92bb418SOliver-Rainer Wittmann const basegfx::B2DRange SvgSvgNode::getCurrentViewPort() const 609ddde725dSArmin Le Grand { 610ddde725dSArmin Le Grand if(getViewBox()) 611ddde725dSArmin Le Grand { 612*e92bb418SOliver-Rainer Wittmann return *(getViewBox()); 613ddde725dSArmin Le Grand } 6142169cc62SArmin Le Grand else // viewport should be given by x, y, width, and height 615ddde725dSArmin Le Grand { 6162169cc62SArmin Le Grand // Extract known viewport data 6172169cc62SArmin Le Grand // bXXXIsAbsolute tracks whether relative values could be resolved to absolute values 6182169cc62SArmin Le Grand if (getParent()) 6192169cc62SArmin Le Grand { 6202169cc62SArmin Le Grand // If width or height is not provided, the default 100% is used, see SVG 1.1 section 5.1.2 6212169cc62SArmin Le Grand // value 0.0 here is only to initialize variable 6222169cc62SArmin Le Grand bool bWidthIsAbsolute(getWidth().isSet() && Unit_percent != getWidth().getUnit()); 6232169cc62SArmin Le Grand double fW( bWidthIsAbsolute ? getWidth().solveNonPercentage(*this) : 0.0); 6242169cc62SArmin Le Grand bool bHeightIsAbsolute(getHeight().isSet() && Unit_percent != getHeight().getUnit()); 6252169cc62SArmin Le Grand double fH( bHeightIsAbsolute ? getHeight().solveNonPercentage(*this) : 0.0); 6262169cc62SArmin Le Grand 6272169cc62SArmin Le Grand // If x or y not provided, then default 0.0 is used, see SVG 1.1 Section 5.1.2 6282169cc62SArmin Le Grand bool bXIsAbsolute((getX().isSet() && Unit_percent != getX().getUnit()) || !getX().isSet()); 6292169cc62SArmin Le Grand double fX( bXIsAbsolute && getX().isSet() ? getX().solveNonPercentage(*this) : 0.0); 6302169cc62SArmin Le Grand 6312169cc62SArmin Le Grand bool bYIsAbsolute((getY().isSet() && Unit_percent != getY().getUnit()) || !getY().isSet()); 6322169cc62SArmin Le Grand double fY( bYIsAbsolute && getY().isSet() ? getY().solveNonPercentage(*this) : 0.0); 6332169cc62SArmin Le Grand 6342169cc62SArmin Le Grand if (bXIsAbsolute && bYIsAbsolute && bWidthIsAbsolute && bHeightIsAbsolute) 6352169cc62SArmin Le Grand { 636*e92bb418SOliver-Rainer Wittmann return basegfx::B2DRange(fX, fY, fX+fW, fY+fH); 6372169cc62SArmin Le Grand } 6382169cc62SArmin Le Grand else // try to resolve relative values 6392169cc62SArmin Le Grand { 6402169cc62SArmin Le Grand if (!bXIsAbsolute || !bWidthIsAbsolute) 6412169cc62SArmin Le Grand { 6422169cc62SArmin Le Grand // get width of enclosing svg and resolve percentage in x and width 6432169cc62SArmin Le Grand double fWReference(0.0); 6442169cc62SArmin Le Grand bool bHasFoundWidth(false); 6452169cc62SArmin Le Grand seekReferenceWidth(fWReference, bHasFoundWidth); 6462169cc62SArmin Le Grand // referenced values are already in 'user unit' 6472169cc62SArmin Le Grand if (!bXIsAbsolute && bHasFoundWidth) 6482169cc62SArmin Le Grand { 6492169cc62SArmin Le Grand fX = getX().getNumber() * 0.01 * fWReference; 6502169cc62SArmin Le Grand bXIsAbsolute = true; 6512169cc62SArmin Le Grand } 6522169cc62SArmin Le Grand if (!bWidthIsAbsolute && bHasFoundWidth) 6532169cc62SArmin Le Grand { 6542169cc62SArmin Le Grand fW = (getWidth().isSet() ? getWidth().getNumber() *0.01 : 1.0) * fWReference; 6552169cc62SArmin Le Grand bWidthIsAbsolute = true; 6562169cc62SArmin Le Grand } 6572169cc62SArmin Le Grand } 6582169cc62SArmin Le Grand if (!bYIsAbsolute || !bHeightIsAbsolute) 6592169cc62SArmin Le Grand { 6602169cc62SArmin Le Grand // get height of enclosing svg and resolve percentage in y and height 6612169cc62SArmin Le Grand double fHReference(0.0); 6622169cc62SArmin Le Grand bool bHasFoundHeight(false); 6632169cc62SArmin Le Grand seekReferenceHeight(fHReference, bHasFoundHeight); 6642169cc62SArmin Le Grand // referenced values are already in 'user unit' 6652169cc62SArmin Le Grand if (!bYIsAbsolute && bHasFoundHeight) 6662169cc62SArmin Le Grand { 6672169cc62SArmin Le Grand fY = getY().getNumber() * 0.01 * fHReference; 6682169cc62SArmin Le Grand bYIsAbsolute = true; 6692169cc62SArmin Le Grand } 6702169cc62SArmin Le Grand if (!bHeightIsAbsolute && bHasFoundHeight) 6712169cc62SArmin Le Grand { 6722169cc62SArmin Le Grand fH = (getHeight().isSet() ? getHeight().getNumber() *0.01 : 1.0) * fHReference; 6732169cc62SArmin Le Grand bHeightIsAbsolute = true; 6742169cc62SArmin Le Grand } 6752169cc62SArmin Le Grand } 6762169cc62SArmin Le Grand 6772169cc62SArmin Le Grand if (bXIsAbsolute && bYIsAbsolute && bWidthIsAbsolute && bHeightIsAbsolute) 6782169cc62SArmin Le Grand { 679*e92bb418SOliver-Rainer Wittmann return basegfx::B2DRange(fX, fY, fX+fW, fY+fH); 6802169cc62SArmin Le Grand } 6812169cc62SArmin Le Grand else // relative values could not be resolved, there exists no fallback 6822169cc62SArmin Le Grand { 6832169cc62SArmin Le Grand return SvgNode::getCurrentViewPort(); 6842169cc62SArmin Le Grand } 6852169cc62SArmin Le Grand } 6862169cc62SArmin Le Grand } 6872169cc62SArmin Le Grand else //outermost svg 6882169cc62SArmin Le Grand { 6892169cc62SArmin Le Grand // If width or height is not provided, the default would be 100%, see SVG 1.1 section 5.1.2 6902169cc62SArmin Le Grand // But here it cannot be resolved and no fallback exists. 6912169cc62SArmin Le Grand // SVG 1.1 defines in section 5.1.2 that x,y has no meanig for the outermost SVG element. 6922169cc62SArmin Le Grand bool bWidthIsAbsolute(getWidth().isSet() && Unit_percent != getWidth().getUnit()); 6932169cc62SArmin Le Grand double fW( bWidthIsAbsolute ? getWidth().solveNonPercentage(*this) : 0.0); 6942169cc62SArmin Le Grand bool bHeightIsAbsolute(getHeight().isSet() && Unit_percent != getHeight().getUnit()); 6952169cc62SArmin Le Grand double fH( bHeightIsAbsolute ? getHeight().solveNonPercentage(*this) : 0.0); 6962169cc62SArmin Le Grand if (bWidthIsAbsolute && bHeightIsAbsolute) 6972169cc62SArmin Le Grand { 698*e92bb418SOliver-Rainer Wittmann return basegfx::B2DRange(0.0, 0.0, fW, fH); 6992169cc62SArmin Le Grand } 7002169cc62SArmin Le Grand else // no fallback exists 7012169cc62SArmin Le Grand { 7022169cc62SArmin Le Grand return SvgNode::getCurrentViewPort(); 7032169cc62SArmin Le Grand } 7042169cc62SArmin Le Grand } 7052169cc62SArmin Le Grand // ToDo: Is it possible to decompose and use the bounding box of the childs, if even the 7062169cc62SArmin Le Grand // outermost svg has no information to resolve percentage? Is it worth, how expensive is it? 7072169cc62SArmin Le Grand 708ddde725dSArmin Le Grand } 709ddde725dSArmin Le Grand } 710ddde725dSArmin Le Grand 711ddde725dSArmin Le Grand } // end of namespace svgreader 712ddde725dSArmin Le Grand } // end of namespace svgio 713ddde725dSArmin Le Grand 714ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 715ddde725dSArmin Le Grand // eof 716