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