svgsvgnode.cxx (bca0eb5d) | svgsvgnode.cxx (2169cc62) |
---|---|
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 --- 148 unchanged lines hidden (view full) --- 157 } 158 default: 159 { 160 break; 161 } 162 } 163 } 164 | 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 --- 148 unchanged lines hidden (view full) --- 157 } 158 default: 159 { 160 break; 161 } 162 } 163 } 164 |
165 void SvgSvgNode::seekReferenceWidth(double& fWidth, bool& bHasFound) const 166 { 167 if (!getParent() || bHasFound) 168 { 169 return; 170 } 171 const SvgSvgNode* pParentSvgSvgNode = 0; 172 // enclosing svg might have relative width, need to cumulate them till they are 173 // resolved somewhere up in the node tree 174 double fPercentage(1.0); 175 for(const SvgNode* pParent = getParent(); pParent && !bHasFound; pParent = pParent->getParent()) 176 { 177 // dynamic_cast results Null-pointer for not SvgSvgNode and so skips them in if condition 178 pParentSvgSvgNode = dynamic_cast< const SvgSvgNode* >(pParent); 179 if (pParentSvgSvgNode) 180 { 181 if (pParentSvgSvgNode->getViewBox()) 182 { 183 // viewbox values are already in 'user unit'. 184 fWidth = pParentSvgSvgNode->getViewBox()->getWidth() * fPercentage; 185 bHasFound = true; 186 } 187 else 188 { 189 // take absolute value or cummulate percentage 190 if (pParentSvgSvgNode->getWidth().isSet()) 191 { 192 if (Unit_percent == pParentSvgSvgNode->getWidth().getUnit()) 193 { 194 fPercentage *= pParentSvgSvgNode->getWidth().getNumber() * 0.01; 195 } 196 else 197 { 198 fWidth = pParentSvgSvgNode->getWidth().solveNonPercentage(*pParentSvgSvgNode) * fPercentage; 199 bHasFound = true; 200 } 201 } // not set => width=100% => factor 1, no need for else 202 } 203 } 204 } 205 } 206 207 void SvgSvgNode::seekReferenceHeight(double& fHeight, bool& bHasFound) const 208 { 209 if (!getParent() || bHasFound) 210 { 211 return; 212 } 213 const SvgSvgNode* pParentSvgSvgNode = 0; 214 // enclosing svg might have relative width and height, need to cumulate them till they are 215 // resolved somewhere up in the node tree 216 double fPercentage(1.0); 217 for(const SvgNode* pParent = getParent(); pParent && !bHasFound; pParent = pParent->getParent()) 218 { 219 // dynamic_cast results Null-pointer for not SvgSvgNode and so skips them in if condition 220 pParentSvgSvgNode = dynamic_cast< const SvgSvgNode* >(pParent); 221 if (pParentSvgSvgNode) 222 { 223 if (pParentSvgSvgNode->getViewBox()) 224 { 225 // viewbox values are already in 'user unit'. 226 fHeight = pParentSvgSvgNode->getViewBox()->getHeight() * fPercentage; 227 bHasFound = true; 228 } 229 else 230 { 231 // take absolute value or cummulate percentage 232 if (pParentSvgSvgNode->getHeight().isSet()) 233 { 234 if (Unit_percent == pParentSvgSvgNode->getHeight().getUnit()) 235 { 236 fPercentage *= pParentSvgSvgNode->getHeight().getNumber() * 0.01; 237 } 238 else 239 { 240 fHeight = pParentSvgSvgNode->getHeight().solveNonPercentage(*pParentSvgSvgNode) * fPercentage; 241 bHasFound = true; 242 } 243 } // not set => height=100% => factor 1, no need for else 244 } 245 } 246 } 247 } 248 249// ToDo: Consider attribute overflow in method decomposeSvgNode |
|
165 void SvgSvgNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const 166 { 167 drawinglayer::primitive2d::Primitive2DSequence aSequence; 168 169 // decompose childs 170 SvgNode::decomposeSvgNode(aSequence, bReferenced); 171 172 if(aSequence.hasElements()) 173 { 174 if(getParent()) 175 { | 250 void SvgSvgNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const 251 { 252 drawinglayer::primitive2d::Primitive2DSequence aSequence; 253 254 // decompose childs 255 SvgNode::decomposeSvgNode(aSequence, bReferenced); 256 257 if(aSequence.hasElements()) 258 { 259 if(getParent()) 260 { |
176 const bool bWidthIsRelative(!getWidth().isSet() || Unit_percent == getWidth().getUnit()); 177 const bool bHeightIsRelative(!getWidth().isSet() || Unit_percent == getWidth().getUnit()); 178 const SvgSvgNode* pParentSvgSvgNode = 0; 179 double fW(0.0); 180 double fH(0.0); 181 182 // #122594# if width/height is not given, it's 100% (see 5.1.2 The �svg� element in SVG1.1 spec). | 261 // #122594# if width/height is not given, it's 100% (see 5.1.2 The 'svg' element in SVG1.1 spec). |
183 // If it is relative, the question is to what. The previous implementatin assumed relative to the 184 // local ViewBox which is implied by (4.2 Basic data types): 185 // 186 // "Note that the non-property <length> definition also allows a percentage unit identifier. 187 // The meaning of a percentage length value depends on the attribute for which the percentage 188 // length value has been specified. Two common cases are: (a) when a percentage length value 189 // represents a percentage of the viewport width or height (refer to the section that discusses 190 // units in general), and (b) when a percentage length value represents a percentage of the 191 // bounding box width or height on a given object (refer to the section that describes object 192 // bounding box units)." | 262 // If it is relative, the question is to what. The previous implementatin assumed relative to the 263 // local ViewBox which is implied by (4.2 Basic data types): 264 // 265 // "Note that the non-property <length> definition also allows a percentage unit identifier. 266 // The meaning of a percentage length value depends on the attribute for which the percentage 267 // length value has been specified. Two common cases are: (a) when a percentage length value 268 // represents a percentage of the viewport width or height (refer to the section that discusses 269 // units in general), and (b) when a percentage length value represents a percentage of the 270 // bounding box width or height on a given object (refer to the section that describes object 271 // bounding box units)." |
193 // 194 // This is not closer specified for the SVG element itself as non-outmost element, but comparisons 195 // with common browsers shows that it's mostly interpreted relative to the viewBox of the parent. 196 // Adding code to search the parent SVG element and calculating width/height relative to it's 197 // viewBox width/height (and no longer to the local viewBox). 198 if(bWidthIsRelative || bHeightIsRelative) | 272 273 // Comparisons with commom browsers show, that it's mostly interpreted relative to the viewport 274 // of the parent, and so does the new implementation. 275 276 // Extract known viewport data 277 // bXXXIsAbsolute tracks whether relative values could be resolved to absolute values 278 279 // If width or height is not provided, the default 100% is used, see SVG 1.1 section 5.1.2 280 // value 0.0 here is only to initialize variable 281 bool bWidthIsAbsolute(getWidth().isSet() && Unit_percent != getWidth().getUnit()); 282 double fW( bWidthIsAbsolute ? getWidth().solveNonPercentage(*this) : 0.0); 283 284 bool bHeightIsAbsolute(getHeight().isSet() && Unit_percent != getHeight().getUnit()); 285 double fH( bHeightIsAbsolute ? getHeight().solveNonPercentage(*this) : 0.0); 286 287 // If x or y not provided, then default 0.0 is used, see SVG 1.1 Section 5.1.2 288 bool bXIsAbsolute((getX().isSet() && Unit_percent != getX().getUnit()) || !getX().isSet()); 289 double fX( bXIsAbsolute && getX().isSet() ? getX().solveNonPercentage(*this) : 0.0); 290 291 bool bYIsAbsolute((getY().isSet() && Unit_percent != getY().getUnit()) || !getY().isSet()); 292 double fY( bYIsAbsolute && getY().isSet() ? getY().solveNonPercentage(*this) : 0.0); 293 294 if ( !bXIsAbsolute || !bWidthIsAbsolute) |
199 { | 295 { |
200 for(const SvgNode* pParent = getParent(); pParent && !pParentSvgSvgNode; pParent = pParent->getParent()) | 296 // get width of enclosing svg and resolve percentage in x and width; 297 double fWReference(0.0); 298 bool bHasFoundWidth(false); 299 seekReferenceWidth(fWReference, bHasFoundWidth); 300 if (!bHasFoundWidth) |
201 { | 301 { |
202 pParentSvgSvgNode = dynamic_cast< const SvgSvgNode* >(pParent); | 302 // Even outermost svg has not all information to resolve relative values, 303 // I use content itself as fallback to set missing values for viewport 304 // Any better idea for such ill structures svg documents? 305 const basegfx::B2DRange aChildRange( 306 drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence( 307 aSequence, 308 drawinglayer::geometry::ViewInformation2D())); 309 fWReference = aChildRange.getWidth(); |
203 } | 310 } |
311 // referenced values are already in 'user unit' 312 if (!bXIsAbsolute) 313 { 314 fX = getX().getNumber() * 0.01 * fWReference; 315 } 316 if (!bWidthIsAbsolute) 317 { 318 fW = (getWidth().isSet() ? getWidth().getNumber() *0.01 : 1.0) * fWReference; 319 } |
|
204 } 205 | 320 } 321 |
206 if(bWidthIsRelative) | 322 if ( !bYIsAbsolute || !bHeightIsAbsolute) |
207 { | 323 { |
208 fW = getWidth().isSet() ? getWidth().getNumber() * 0.01 : 1.0; 209 210 if(pParentSvgSvgNode) | 324 // get height of enclosing svg and resolve percentage in y and height 325 double fHReference(0.0); 326 bool bHasFoundHeight(false); 327 seekReferenceHeight(fHReference, bHasFoundHeight); 328 if (!bHasFoundHeight) |
211 { | 329 { |
212 fW *= pParentSvgSvgNode->getViewBox()->getWidth(); | 330 // Even outermost svg has not all information to resolve relative values, 331 // I use content itself as fallback to set missing values for viewport 332 // Any better idea for such ill structures svg documents? 333 const basegfx::B2DRange aChildRange( 334 drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence( 335 aSequence, 336 drawinglayer::geometry::ViewInformation2D())); 337 fHReference = aChildRange.getHeight(); |
213 } | 338 } |
214 } 215 else 216 { 217 fW = getWidth().solve(*this, xcoordinate); 218 } | |
219 | 339 |
220 if(bHeightIsRelative) 221 { 222 fH = getHeight().isSet() ? getHeight().getNumber() * 0.01 : 1.0; 223 224 if(pParentSvgSvgNode) | 340 // referenced values are already in 'user unit' 341 if (!bYIsAbsolute) |
225 { | 342 { |
226 fH *= pParentSvgSvgNode->getViewBox()->getHeight(); | 343 fY = getY().getNumber() * 0.01 * fHReference; |
227 } | 344 } |
345 if (!bHeightIsAbsolute) 346 { 347 fH = (getHeight().isSet() ? getHeight().getNumber() *0.01 : 1.0) * fHReference; 348 } |
|
228 } | 349 } |
229 else 230 { 231 fH = getHeight().solve(*this, ycoordinate); 232 } | |
233 234 if(getViewBox()) 235 { | 350 351 if(getViewBox()) 352 { |
236 // Svg defines that with no width or no height the viewBox content is empty, 237 // so both need to exist 238 if(!basegfx::fTools::equalZero(getViewBox()->getWidth()) && !basegfx::fTools::equalZero(getViewBox()->getHeight())) | 353 // SVG 1.1 defines in section 7.7 that a negative value for width or height 354 // in viewBox is an error and that 0.0 disables rendering 355 if(basegfx::fTools::more(getViewBox()->getWidth(),0.0) && basegfx::fTools::more(getViewBox()->getHeight(),0.0)) |
239 { | 356 { |
240 // create target range homing x,y, width and height as given 241 const double fX(getX().isSet() ? getX().solve(*this, xcoordinate) : 0.0); 242 const double fY(getY().isSet() ? getY().solve(*this, ycoordinate) : 0.0); | 357 // create target range homing x,y, width and height as calculated above |
243 const basegfx::B2DRange aTarget(fX, fY, fX + fW, fY + fH); 244 245 if(aTarget.equal(*getViewBox())) 246 { 247 // no mapping needed, append 248 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aSequence); 249 } 250 else 251 { 252 // create mapping | 358 const basegfx::B2DRange aTarget(fX, fY, fX + fW, fY + fH); 359 360 if(aTarget.equal(*getViewBox())) 361 { 362 // no mapping needed, append 363 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aSequence); 364 } 365 else 366 { 367 // create mapping |
253 const SvgAspectRatio& rRatio = getSvgAspectRatio(); | 368 // #i122610 SVG 1.1 defines in section 5.1.2 that if the attribute perserveAspectRatio is not specified, 369 // then the effect is as if a value of 'xMidYMid meet' were specified. 370 SvgAspectRatio aRatioDefault(Align_xMidYMid,false,true); 371 const SvgAspectRatio& rRatio = getSvgAspectRatio().isSet()? getSvgAspectRatio() : aRatioDefault; |
254 | 372 |
255 if(rRatio.isSet()) 256 { 257 // let mapping be created from SvgAspectRatio 258 const basegfx::B2DHomMatrix aEmbeddingTransform( 259 rRatio.createMapping(aTarget, *getViewBox())); | 373 // let mapping be created from SvgAspectRatio 374 const basegfx::B2DHomMatrix aEmbeddingTransform( 375 rRatio.createMapping(aTarget, *getViewBox())); |
260 | 376 |
261 // prepare embedding in transformation 262 const drawinglayer::primitive2d::Primitive2DReference xRef( 263 new drawinglayer::primitive2d::TransformPrimitive2D( 264 aEmbeddingTransform, 265 aSequence)); | 377 // prepare embedding in transformation 378 const drawinglayer::primitive2d::Primitive2DReference xRef( 379 new drawinglayer::primitive2d::TransformPrimitive2D( 380 aEmbeddingTransform, 381 aSequence)); |
266 | 382 |
267 if(rRatio.isMeetOrSlice()) 268 { 269 // embed in transformation 270 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xRef); 271 } 272 else 273 { 274 // need to embed in MaskPrimitive2D, too 275 const drawinglayer::primitive2d::Primitive2DReference xMask( 276 new drawinglayer::primitive2d::MaskPrimitive2D( 277 basegfx::B2DPolyPolygon(basegfx::tools::createPolygonFromRect(aTarget)), 278 drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1))); 279 280 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xMask); 281 } | 383 if(rRatio.isMeetOrSlice()) 384 { 385 // embed in transformation 386 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xRef); |
282 } 283 else 284 { | 387 } 388 else 389 { |
285 // choose default mapping 286 const basegfx::B2DHomMatrix aEmbeddingTransform( 287 rRatio.createLinearMapping( 288 aTarget, *getViewBox())); 289 290 // embed in transformation 291 const drawinglayer::primitive2d::Primitive2DReference xTransform( 292 new drawinglayer::primitive2d::TransformPrimitive2D( 293 aEmbeddingTransform, 294 aSequence)); | 390 // need to embed in MaskPrimitive2D, too 391 const drawinglayer::primitive2d::Primitive2DReference xMask( 392 new drawinglayer::primitive2d::MaskPrimitive2D( 393 basegfx::B2DPolyPolygon(basegfx::tools::createPolygonFromRect(aTarget)), 394 drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1))); |
295 | 395 |
296 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xTransform); | 396 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xMask); |
297 } 298 } 299 } 300 } | 397 } 398 } 399 } 400 } |
301 else | 401 else // no viewBox attribute |
302 { 303 // Svg defines that a negative value is an error and that 0.0 disables rendering 304 if(basegfx::fTools::more(fW, 0.0) && basegfx::fTools::more(fH, 0.0)) 305 { | 402 { 403 // Svg defines that a negative value is an error and that 0.0 disables rendering 404 if(basegfx::fTools::more(fW, 0.0) && basegfx::fTools::more(fH, 0.0)) 405 { |
306 // check if we have a x,y position 307 const double fX(getX().isSet() ? getX().solve(*this, xcoordinate) : 0.0); 308 const double fY(getY().isSet() ? getY().solve(*this, ycoordinate) : 0.0); 309 | |
310 if(!basegfx::fTools::equalZero(fX) || !basegfx::fTools::equalZero(fY)) 311 { 312 // embed in transform 313 const drawinglayer::primitive2d::Primitive2DReference xRef( 314 new drawinglayer::primitive2d::TransformPrimitive2D( 315 basegfx::tools::createTranslateB2DHomMatrix(fX, fY), 316 aSequence)); 317 --- 8 unchanged lines hidden (view full) --- 326 basegfx::B2DRange(fX, fY, fX + fW, fY + fH))), 327 aSequence)); 328 329 // append 330 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xMask); 331 } 332 } 333 } | 406 if(!basegfx::fTools::equalZero(fX) || !basegfx::fTools::equalZero(fY)) 407 { 408 // embed in transform 409 const drawinglayer::primitive2d::Primitive2DReference xRef( 410 new drawinglayer::primitive2d::TransformPrimitive2D( 411 basegfx::tools::createTranslateB2DHomMatrix(fX, fY), 412 aSequence)); 413 --- 8 unchanged lines hidden (view full) --- 422 basegfx::B2DRange(fX, fY, fX + fW, fY + fH))), 423 aSequence)); 424 425 // append 426 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xMask); 427 } 428 } 429 } |
334 else | 430 else // Outermost SVG element |
335 { | 431 { |
336 // Outermost SVG element; create target range homing width and height as given. 337 // SVG defines that x,y has no meanig for the outermost SVG element. Use a fallback 338 // width and height of din A 4 (21 x 29,7 cm) 339 double fW(getWidth().isSet() ? getWidth().solve(*this, xcoordinate) : (210.0 * 3.543307)); 340 double fH(getHeight().isSet() ? getHeight().solve(*this, ycoordinate) : (297.0 * 3.543307)); | 432 double fW = 0.0; // effective value depends on viewBox 433 double fH = 0.0; |
341 342 // Svg defines that a negative value is an error and that 0.0 disables rendering | 434 435 // Svg defines that a negative value is an error and that 0.0 disables rendering |
343 if(basegfx::fTools::more(fW, 0.0) && basegfx::fTools::more(fH, 0.0)) | 436 // isPositive() not usable because it allows 0.0 in contrast to mathematical definition of 'positive' 437 const bool bWidthInvalid(getWidth().isSet() && basegfx::fTools::lessOrEqual(getWidth().getNumber(), 0.0)); 438 const bool bHeightInvalid(getHeight().isSet() && basegfx::fTools::lessOrEqual(getHeight().getNumber(), 0.0)); 439 if(!bWidthInvalid && !bHeightInvalid) |
344 { | 440 { |
345 const basegfx::B2DRange aSvgCanvasRange(0.0, 0.0, fW, fH); 346 | 441 basegfx::B2DRange aSvgCanvasRange; // effective value depends on viewBox |
347 if(getViewBox()) 348 { | 442 if(getViewBox()) 443 { |
349 if(!basegfx::fTools::equalZero(getViewBox()->getWidth()) && !basegfx::fTools::equalZero(getViewBox()->getHeight())) | 444 // SVG 1.1 defines in section 7.7 that a negative value for width or height 445 // in viewBox is an error and that 0.0 disables rendering 446 const double fViewBoxWidth = getViewBox()->getWidth(); 447 const double fViewBoxHeight = getViewBox()->getHeight(); 448 if(basegfx::fTools::more(fViewBoxWidth,0.0) && basegfx::fTools::more(fViewBoxHeight,0.0)) |
350 { | 449 { |
351 // create mapping 352 const SvgAspectRatio& rRatio = getSvgAspectRatio(); 353 basegfx::B2DHomMatrix aViewBoxMapping; 354 355 if(rRatio.isSet()) | 450 // The intrinsic aspect ratio of the svg element is given by absolute values of both width and height 451 // or if one or both of them is relative by the width and height of the viewBox 452 // see SVG 1.1 section 7.12 453 const bool bWidthIsAbsolute(getWidth().isSet() && Unit_percent != getWidth().getUnit()); 454 const bool bHeightIsAbsolute(getHeight().isSet() && Unit_percent != getHeight().getUnit()); 455 if(bWidthIsAbsolute && bHeightIsAbsolute) |
356 { | 456 { |
357 // let mapping be created from SvgAspectRatio 358 aViewBoxMapping = rRatio.createMapping(aSvgCanvasRange, *getViewBox()); 359 360 // no need to check ratio here for slice, the outermost Svg will 361 // be clipped anyways (see below) | 457 fW =getWidth().solveNonPercentage(*this); 458 fH =getHeight().solveNonPercentage(*this); |
362 } | 459 } |
460 else if (bWidthIsAbsolute) 461 { 462 fW = getWidth().solveNonPercentage(*this); 463 fH = fW * fViewBoxWidth / fViewBoxHeight ; 464 } 465 else if (bHeightIsAbsolute) 466 { 467 fH = getHeight().solveNonPercentage(*this); 468 fW = fH * fViewBoxWidth / fViewBoxHeight ; 469 } |
|
363 else 364 { | 470 else 471 { |
365 // choose default mapping 366 aViewBoxMapping = rRatio.createLinearMapping(aSvgCanvasRange, *getViewBox()); | 472 fW = fViewBoxWidth; 473 fH = fViewBoxHeight; |
367 } | 474 } |
475 // SVG 1.1 defines in section 5.1.2 that x,y has no meanig for the outermost SVG element. 476 aSvgCanvasRange = basegfx::B2DRange(0.0, 0.0, fW, fH); |
|
368 | 477 |
478 // create mapping 479 // SVG 1.1 defines in section 5.1.2 that if the attribute perserveAspectRatio is not specified, 480 // then the effect is as if a value of 'xMidYMid meet' were specified. 481 SvgAspectRatio aRatioDefault(Align_xMidYMid,false,true); 482 const SvgAspectRatio& rRatio = getSvgAspectRatio().isSet()? getSvgAspectRatio() : aRatioDefault; 483 484 basegfx::B2DHomMatrix aViewBoxMapping; 485 aViewBoxMapping = rRatio.createMapping(aSvgCanvasRange, *getViewBox()); 486 // no need to check ratio here for slice, the outermost Svg will 487 // be clipped anyways (see below) 488 |
|
369 // scale content to viewBox definitions 370 const drawinglayer::primitive2d::Primitive2DReference xTransform( 371 new drawinglayer::primitive2d::TransformPrimitive2D( 372 aViewBoxMapping, 373 aSequence)); 374 375 aSequence = drawinglayer::primitive2d::Primitive2DSequence(&xTransform, 1); 376 } 377 } | 489 // scale content to viewBox definitions 490 const drawinglayer::primitive2d::Primitive2DReference xTransform( 491 new drawinglayer::primitive2d::TransformPrimitive2D( 492 aViewBoxMapping, 493 aSequence)); 494 495 aSequence = drawinglayer::primitive2d::Primitive2DSequence(&xTransform, 1); 496 } 497 } |
498 else // no viewbox 499 { 500 // There exists no parent to resolve relative width or height. 501 // Use child size as fallback. 502 const bool bWidthIsAbsolute(getWidth().isSet() && Unit_percent != getWidth().getUnit()); 503 const bool bHeightIsAbsolute(getHeight().isSet() && Unit_percent != getHeight().getUnit()); 504 if (bWidthIsAbsolute && bHeightIsAbsolute) 505 { 506 fW =getWidth().solveNonPercentage(*this); 507 fH =getHeight().solveNonPercentage(*this); |
|
378 | 508 |
509 } 510 else 511 { 512 const basegfx::B2DRange aChildRange( 513 drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence( 514 aSequence, 515 drawinglayer::geometry::ViewInformation2D())); 516 const double fChildWidth(aChildRange.getWidth()); 517 const double fChildHeight(aChildRange.getHeight()); 518 fW = bWidthIsAbsolute ? getWidth().solveNonPercentage(*this) : fChildWidth; 519 fH = bHeightIsAbsolute ? getHeight().solveNonPercentage(*this) : fChildHeight; 520 } 521 // SVG 1.1 defines in section 5.1.2 that x,y has no meanig for the outermost SVG element. 522 aSvgCanvasRange = basegfx::B2DRange(0.0, 0.0, fW, fH); 523 } 524 |
|
379 // to be completely correct in Svg sense it is necessary to clip 380 // the whole content to the given canvas. I choose here to do this 381 // initially despite I found various examples of Svg files out there 382 // which have no correct values for this clipping. It's correct 383 // due to the Svg spec. 384 bool bDoCorrectCanvasClipping(true); 385 386 if(bDoCorrectCanvasClipping) --- 44 unchanged lines hidden (view full) --- 431 // not inside, no overlap. Empty Svg 432 aSequence.realloc(0); 433 } 434 } 435 436 if(aSequence.hasElements()) 437 { 438 // embed in transform primitive to scale to 1/100th mm | 525 // to be completely correct in Svg sense it is necessary to clip 526 // the whole content to the given canvas. I choose here to do this 527 // initially despite I found various examples of Svg files out there 528 // which have no correct values for this clipping. It's correct 529 // due to the Svg spec. 530 bool bDoCorrectCanvasClipping(true); 531 532 if(bDoCorrectCanvasClipping) --- 44 unchanged lines hidden (view full) --- 577 // not inside, no overlap. Empty Svg 578 aSequence.realloc(0); 579 } 580 } 581 582 if(aSequence.hasElements()) 583 { 584 // embed in transform primitive to scale to 1/100th mm |
439 // where 1 mm == 3.543307 px to get from Svg coordinates to 440 // drawinglayer ones 441 const double fScaleTo100thmm(100.0 / 3.543307); | 585 // where 1 inch == 25.4 mm to get from Svg coordinates (px) to 586 // drawinglayer coordinates 587 const double fScaleTo100thmm(25.4 * 100.0 / F_SVG_PIXEL_PER_INCH); |
442 const basegfx::B2DHomMatrix aTransform( 443 basegfx::tools::createScaleB2DHomMatrix( 444 fScaleTo100thmm, 445 fScaleTo100thmm)); 446 447 const drawinglayer::primitive2d::Primitive2DReference xTransform( 448 new drawinglayer::primitive2d::TransformPrimitive2D( 449 aTransform, --- 10 unchanged lines hidden (view full) --- 460 } 461 462 const basegfx::B2DRange* SvgSvgNode::getCurrentViewPort() const 463 { 464 if(getViewBox()) 465 { 466 return getViewBox(); 467 } | 588 const basegfx::B2DHomMatrix aTransform( 589 basegfx::tools::createScaleB2DHomMatrix( 590 fScaleTo100thmm, 591 fScaleTo100thmm)); 592 593 const drawinglayer::primitive2d::Primitive2DReference xTransform( 594 new drawinglayer::primitive2d::TransformPrimitive2D( 595 aTransform, --- 10 unchanged lines hidden (view full) --- 606 } 607 608 const basegfx::B2DRange* SvgSvgNode::getCurrentViewPort() const 609 { 610 if(getViewBox()) 611 { 612 return getViewBox(); 613 } |
468 else | 614 else // viewport should be given by x, y, width, and height |
469 { | 615 { |
470 return SvgNode::getCurrentViewPort(); | 616 // Extract known viewport data 617 // bXXXIsAbsolute tracks whether relative values could be resolved to absolute values 618 if (getParent()) 619 { 620 // If width or height is not provided, the default 100% is used, see SVG 1.1 section 5.1.2 621 // value 0.0 here is only to initialize variable 622 bool bWidthIsAbsolute(getWidth().isSet() && Unit_percent != getWidth().getUnit()); 623 double fW( bWidthIsAbsolute ? getWidth().solveNonPercentage(*this) : 0.0); 624 bool bHeightIsAbsolute(getHeight().isSet() && Unit_percent != getHeight().getUnit()); 625 double fH( bHeightIsAbsolute ? getHeight().solveNonPercentage(*this) : 0.0); 626 627 // If x or y not provided, then default 0.0 is used, see SVG 1.1 Section 5.1.2 628 bool bXIsAbsolute((getX().isSet() && Unit_percent != getX().getUnit()) || !getX().isSet()); 629 double fX( bXIsAbsolute && getX().isSet() ? getX().solveNonPercentage(*this) : 0.0); 630 631 bool bYIsAbsolute((getY().isSet() && Unit_percent != getY().getUnit()) || !getY().isSet()); 632 double fY( bYIsAbsolute && getY().isSet() ? getY().solveNonPercentage(*this) : 0.0); 633 634 if (bXIsAbsolute && bYIsAbsolute && bWidthIsAbsolute && bHeightIsAbsolute) 635 { 636 return &basegfx::B2DRange(fX, fY, fX+fW, fY+fH); 637 } 638 else // try to resolve relative values 639 { 640 if (!bXIsAbsolute || !bWidthIsAbsolute) 641 { 642 // get width of enclosing svg and resolve percentage in x and width 643 double fWReference(0.0); 644 bool bHasFoundWidth(false); 645 seekReferenceWidth(fWReference, bHasFoundWidth); 646 // referenced values are already in 'user unit' 647 if (!bXIsAbsolute && bHasFoundWidth) 648 { 649 fX = getX().getNumber() * 0.01 * fWReference; 650 bXIsAbsolute = true; 651 } 652 if (!bWidthIsAbsolute && bHasFoundWidth) 653 { 654 fW = (getWidth().isSet() ? getWidth().getNumber() *0.01 : 1.0) * fWReference; 655 bWidthIsAbsolute = true; 656 } 657 } 658 if (!bYIsAbsolute || !bHeightIsAbsolute) 659 { 660 // get height of enclosing svg and resolve percentage in y and height 661 double fHReference(0.0); 662 bool bHasFoundHeight(false); 663 seekReferenceHeight(fHReference, bHasFoundHeight); 664 // referenced values are already in 'user unit' 665 if (!bYIsAbsolute && bHasFoundHeight) 666 { 667 fY = getY().getNumber() * 0.01 * fHReference; 668 bYIsAbsolute = true; 669 } 670 if (!bHeightIsAbsolute && bHasFoundHeight) 671 { 672 fH = (getHeight().isSet() ? getHeight().getNumber() *0.01 : 1.0) * fHReference; 673 bHeightIsAbsolute = true; 674 } 675 } 676 677 if (bXIsAbsolute && bYIsAbsolute && bWidthIsAbsolute && bHeightIsAbsolute) 678 { 679 return &basegfx::B2DRange(fX, fY, fX+fW, fY+fH); 680 } 681 else // relative values could not be resolved, there exists no fallback 682 { 683 return SvgNode::getCurrentViewPort(); 684 } 685 } 686 } 687 else //outermost svg 688 { 689 // If width or height is not provided, the default would be 100%, see SVG 1.1 section 5.1.2 690 // But here it cannot be resolved and no fallback exists. 691 // SVG 1.1 defines in section 5.1.2 that x,y has no meanig for the outermost SVG element. 692 bool bWidthIsAbsolute(getWidth().isSet() && Unit_percent != getWidth().getUnit()); 693 double fW( bWidthIsAbsolute ? getWidth().solveNonPercentage(*this) : 0.0); 694 bool bHeightIsAbsolute(getHeight().isSet() && Unit_percent != getHeight().getUnit()); 695 double fH( bHeightIsAbsolute ? getHeight().solveNonPercentage(*this) : 0.0); 696 if (bWidthIsAbsolute && bHeightIsAbsolute) 697 { 698 return &basegfx::B2DRange(0.0, 0.0, fW, fH); 699 } 700 else // no fallback exists 701 { 702 return SvgNode::getCurrentViewPort(); 703 } 704 } 705// ToDo: Is it possible to decompose and use the bounding box of the childs, if even the 706// outermost svg has no information to resolve percentage? Is it worth, how expensive is it? 707 |
471 } 472 } 473 474 } // end of namespace svgreader 475} // end of namespace svgio 476 477////////////////////////////////////////////////////////////////////////////// 478// eof | 708 } 709 } 710 711 } // end of namespace svgreader 712} // end of namespace svgio 713 714////////////////////////////////////////////////////////////////////////////// 715// eof |