Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(93)

Side by Side Diff: Source/core/svg/SVGSVGElement.cpp

Issue 26390004: Rework SVG sizing (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Fix test that was disabled on linux and stand alone svg in error mode Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2004, 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org> 2 * Copyright (C) 2004, 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Rob Buis <buis@kde.org> 3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Rob Buis <buis@kde.org>
4 * Copyright (C) 2007 Apple Inc. All rights reserved. 4 * Copyright (C) 2007 Apple Inc. All rights reserved.
5 * Copyright (C) 2014 Google, Inc. 5 * Copyright (C) 2014 Google, Inc.
6 * 6 *
7 * This library is free software; you can redistribute it and/or 7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public 8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version. 10 * version 2 of the License, or (at your option) any later version.
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 m_height->setBaseValueAsString(value, parseError); 275 m_height->setBaseValueAsString(value, parseError);
276 } else if (SVGFitToViewBox::parseAttribute(name, value, document(), parseErr or)) { 276 } else if (SVGFitToViewBox::parseAttribute(name, value, document(), parseErr or)) {
277 } else if (SVGZoomAndPan::parseAttribute(name, value)) { 277 } else if (SVGZoomAndPan::parseAttribute(name, value)) {
278 } else { 278 } else {
279 SVGGraphicsElement::parseAttribute(name, value); 279 SVGGraphicsElement::parseAttribute(name, value);
280 } 280 }
281 281
282 reportAttributeParsingError(parseError, name, value); 282 reportAttributeParsingError(parseError, name, value);
283 } 283 }
284 284
285 bool SVGSVGElement::isPresentationAttribute(const QualifiedName& name) const
286 {
287 if (isOutermostSVGSVGElement() && (name == SVGNames::widthAttr || name == SV GNames::heightAttr))
288 return true;
289 return SVGGraphicsElement::isPresentationAttribute(name);
290 }
291
292 void SVGSVGElement::collectStyleForPresentationAttribute(const QualifiedName& na me, const AtomicString& value, MutableStylePropertySet* style)
293 {
294 const bool outermost = isOutermostSVGSVGElement();
295 if (outermost && (name == SVGNames::widthAttr || name == SVGNames::heightAtt r)) {
pdr. 2014/04/16 18:17:04 May be cleaner just to move outermost in: if (isOu
davve 2014/04/17 11:39:22 Will do.
296 RefPtr<SVGLength> length = SVGLength::create(LengthModeOther);
297 length->setValueAsString(value, IGNORE_EXCEPTION);
298 if (length->unitType() != LengthTypeUnknown) {
299 if (name == SVGNames::widthAttr)
300 addPropertyToPresentationAttributeStyle(style, CSSPropertyWidth, value);
301 else if (name == SVGNames::heightAttr)
302 addPropertyToPresentationAttributeStyle(style, CSSPropertyHeight , value);
303 }
304 } else {
305 SVGGraphicsElement::collectStyleForPresentationAttribute(name, value, st yle);
306 }
307 }
308
285 void SVGSVGElement::svgAttributeChanged(const QualifiedName& attrName) 309 void SVGSVGElement::svgAttributeChanged(const QualifiedName& attrName)
286 { 310 {
287 bool updateRelativeLengthsOrViewBox = false; 311 bool updateRelativeLengthsOrViewBox = false;
288 bool widthChanged = attrName == SVGNames::widthAttr; 312 bool widthChanged = attrName == SVGNames::widthAttr;
289 if (widthChanged 313 if (widthChanged
290 || attrName == SVGNames::heightAttr 314 || attrName == SVGNames::heightAttr
291 || attrName == SVGNames::xAttr 315 || attrName == SVGNames::xAttr
292 || attrName == SVGNames::yAttr) { 316 || attrName == SVGNames::yAttr) {
293 updateRelativeLengthsOrViewBox = true; 317 updateRelativeLengthsOrViewBox = true;
294 updateRelativeLengthsInformation(); 318 updateRelativeLengthsInformation();
295 invalidateRelativeLengthClients(); 319 invalidateRelativeLengthClients();
296 320
297 // At the SVG/HTML boundary (aka RenderSVGRoot), the width attribute can 321 // At the SVG/HTML boundary (aka RenderSVGRoot), the width attribute can
298 // affect the replaced size so we need to mark it for updating. 322 // affect the replaced size so we need to mark it for updating.
299 if (widthChanged) { 323 if (widthChanged) {
300 RenderObject* renderObject = renderer(); 324 RenderObject* renderObject = renderer();
301 if (renderObject && renderObject->isSVGRoot()) 325 if (renderObject && renderObject->isSVGRoot())
302 toRenderSVGRoot(renderObject)->setNeedsLayoutAndPrefWidthsRecalc (); 326 toRenderSVGRoot(renderObject)->setNeedsLayoutAndPrefWidthsRecalc ();
303 } 327 }
304 } 328 }
305 329
330 if (widthChanged || attrName == SVGNames::heightAttr) {
pdr. 2014/04/16 18:17:04 Do you need to check isSVGRoot here?
davve 2014/04/17 11:39:22 Shuffling stuff around here led me to discover a r
331 invalidateSVGPresentationAttributeStyle();
332 setNeedsStyleRecalc(LocalStyleChange);
333 }
334
306 if (SVGFitToViewBox::isKnownAttribute(attrName)) { 335 if (SVGFitToViewBox::isKnownAttribute(attrName)) {
307 updateRelativeLengthsOrViewBox = true; 336 updateRelativeLengthsOrViewBox = true;
308 if (RenderObject* object = renderer()) 337 if (RenderObject* object = renderer())
309 object->setNeedsTransformUpdate(); 338 object->setNeedsTransformUpdate();
310 } 339 }
311 340
312 SVGElementInstance::InvalidationGuard invalidationGuard(this); 341 SVGElementInstance::InvalidationGuard invalidationGuard(this);
313 342
314 if (updateRelativeLengthsOrViewBox 343 if (updateRelativeLengthsOrViewBox
315 || SVGZoomAndPan::isKnownAttribute(attrName)) { 344 || SVGZoomAndPan::isKnownAttribute(attrName)) {
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
610 return m_viewSpec ? m_viewSpec->viewBox()->currentValue()->value() : Flo atRect(); 639 return m_viewSpec ? m_viewSpec->viewBox()->currentValue()->value() : Flo atRect();
611 640
612 FloatRect useViewBox = viewBox()->currentValue()->value(); 641 FloatRect useViewBox = viewBox()->currentValue()->value();
613 if (!useViewBox.isEmpty()) 642 if (!useViewBox.isEmpty())
614 return useViewBox; 643 return useViewBox;
615 if (!renderer() || !renderer()->isSVGRoot()) 644 if (!renderer() || !renderer()->isSVGRoot())
616 return FloatRect(); 645 return FloatRect();
617 if (!toRenderSVGRoot(renderer())->isEmbeddedThroughSVGImage()) 646 if (!toRenderSVGRoot(renderer())->isEmbeddedThroughSVGImage())
618 return FloatRect(); 647 return FloatRect();
619 648
620 Length intrinsicWidth = this->intrinsicWidth();
621 Length intrinsicHeight = this->intrinsicHeight();
622 if (!intrinsicWidth.isFixed() || !intrinsicHeight.isFixed())
623 return FloatRect();
624
625 // If no viewBox is specified but non-relative width/height values, then we 649 // If no viewBox is specified but non-relative width/height values, then we
626 // should always synthesize a viewBox if we're embedded through a SVGImage. 650 // should always synthesize a viewBox if we're embedded through a SVGImage.
627 return FloatRect(FloatPoint(), FloatSize(floatValueForLength(intrinsicWidth, 0), floatValueForLength(intrinsicHeight, 0))); 651 return FloatRect(FloatPoint(), FloatSize(floatValueForLength(intrinsicWidth( ), 0), floatValueForLength(intrinsicHeight(), 0)));
628 } 652 }
629 653
630 FloatSize SVGSVGElement::currentViewportSize() const 654 FloatSize SVGSVGElement::currentViewportSize() const
631 { 655 {
632 Length intrinsicWidth = this->intrinsicWidth(); 656 if (hasIntrinsicWidth() && hasIntrinsicHeight()) {
633 Length intrinsicHeight = this->intrinsicHeight(); 657 Length intrinsicWidth = this->intrinsicWidth();
634 if (intrinsicWidth.isFixed() && intrinsicHeight.isFixed()) 658 Length intrinsicHeight = this->intrinsicHeight();
635 return FloatSize(floatValueForLength(intrinsicWidth, 0), floatValueForLe ngth(intrinsicHeight, 0)); 659 return FloatSize(floatValueForLength(intrinsicWidth, 0), floatValueForLe ngth(intrinsicHeight, 0));
660 }
636 661
637 if (!renderer()) 662 if (!renderer())
638 return FloatSize(); 663 return FloatSize();
639 664
640 if (renderer()->isSVGRoot()) { 665 if (renderer()->isSVGRoot()) {
641 LayoutRect contentBoxRect = toRenderSVGRoot(renderer())->contentBoxRect( ); 666 LayoutRect contentBoxRect = toRenderSVGRoot(renderer())->contentBoxRect( );
642 return FloatSize(contentBoxRect.width() / renderer()->style()->effective Zoom(), contentBoxRect.height() / renderer()->style()->effectiveZoom()); 667 return FloatSize(contentBoxRect.width() / renderer()->style()->effective Zoom(), contentBoxRect.height() / renderer()->style()->effectiveZoom());
643 } 668 }
644 669
645 FloatRect viewportRect = toRenderSVGViewportContainer(renderer())->viewport( ); 670 FloatRect viewportRect = toRenderSVGViewportContainer(renderer())->viewport( );
646 return FloatSize(viewportRect.width(), viewportRect.height()); 671 return FloatSize(viewportRect.width(), viewportRect.height());
647 } 672 }
648 673
649 bool SVGSVGElement::widthAttributeEstablishesViewport() const 674 bool SVGSVGElement::hasIntrinsicWidth() const
650 { 675 {
651 if (!renderer() || renderer()->isSVGViewportContainer()) 676 return width()->currentValue()->unitType() != LengthTypePercentage;
652 return true;
653
654 // Spec: http://www.w3.org/TR/SVG/coords.html#ViewportSpace
655 // The ‘width’ attribute on the outermost svg element establishes the viewpo rt's width, unless the following conditions are met:
656 // - the SVG content is a separately stored resource that is embedded by ref erence (such as the ‘object’ element in XHTML [XHTML]), or
657 // the SVG content is embedded inline within a containing document;
658 // - and the referencing element or containing document is styled using CSS [CSS2] or XSL [XSL];
659 // - and there are CSS-compatible positioning properties ([CSS2], section 9. 3) specified on the referencing element (e.g., the ‘object’ element)
660 // or on the containing document's outermost svg element that are sufficie nt to establish the width of the viewport. Under these conditions,
661 // the positioning properties establish the viewport's width.
662 RenderSVGRoot* root = toRenderSVGRoot(renderer());
663
664 // SVG embedded through object/embed/iframe.
665 if (root->isEmbeddedThroughFrameContainingSVGDocument())
666 return !root->hasReplacedLogicalWidth() && !document().frame()->ownerRen derer()->hasReplacedLogicalWidth();
667
668 // SVG embedded via SVGImage (background-image/border-image/etc) / Inline SV G.
669 if (root->isEmbeddedThroughSVGImage() || document().documentElement() != thi s)
670 return !root->hasReplacedLogicalWidth();
671
672 return true;
673 } 677 }
674 678
675 bool SVGSVGElement::heightAttributeEstablishesViewport() const 679 bool SVGSVGElement::hasIntrinsicHeight() const
676 { 680 {
677 if (!renderer() || renderer()->isSVGViewportContainer()) 681 return height()->currentValue()->unitType() != LengthTypePercentage;
678 return true;
679
680 // Spec: http://www.w3.org/TR/SVG/coords.html#IntrinsicSizing
681 // Similarly, if there are positioning properties specified on the referenci ng element or on the outermost svg element
682 // that are sufficient to establish the height of the viewport, then these p ositioning properties establish the viewport's
683 // height; otherwise, the ‘height’ attribute on the outermost svg element es tablishes the viewport's height.
684 RenderSVGRoot* root = toRenderSVGRoot(renderer());
685
686 // SVG embedded through object/embed/iframe.
687 if (root->isEmbeddedThroughFrameContainingSVGDocument())
688 return !root->hasReplacedLogicalHeight() && !document().frame()->ownerRe nderer()->hasReplacedLogicalHeight();
689
690 // SVG embedded via SVGImage (background-image/border-image/etc) / Inline SV G.
691 if (root->isEmbeddedThroughSVGImage() || document().documentElement() != thi s)
692 return !root->hasReplacedLogicalHeight();
693
694 return true;
695 } 682 }
696 683
697 Length SVGSVGElement::intrinsicWidth(ConsiderCSSMode mode) const 684 Length SVGSVGElement::intrinsicWidth() const
698 { 685 {
699 if (widthAttributeEstablishesViewport() || mode == IgnoreCSSProperties) { 686 if (width()->currentValue()->unitType() == LengthTypePercentage)
700 if (m_width->currentValue()->unitType() == LengthTypePercentage) 687 return Length(0, Fixed);
701 return Length(m_width->currentValue()->valueAsPercentage() * 100, Pe rcent);
702 688
703 SVGLengthContext lengthContext(this); 689 SVGLengthContext lengthContext(this);
704 return Length(m_width->currentValue()->value(lengthContext), Fixed); 690 return Length(width()->currentValue()->value(lengthContext), Fixed);
705 }
706
707 ASSERT(renderer());
708 return renderer()->style()->width();
709 } 691 }
710 692
711 Length SVGSVGElement::intrinsicHeight(ConsiderCSSMode mode) const 693 Length SVGSVGElement::intrinsicHeight() const
712 { 694 {
713 if (heightAttributeEstablishesViewport() || mode == IgnoreCSSProperties) { 695 if (height()->currentValue()->unitType() == LengthTypePercentage)
714 if (m_height->currentValue()->unitType() == LengthTypePercentage) 696 return Length(0, Fixed);
715 return Length(m_height->currentValue()->valueAsPercentage() * 100, P ercent);
716 697
717 SVGLengthContext lengthContext(this); 698 SVGLengthContext lengthContext(this);
718 return Length(m_height->currentValue()->value(lengthContext), Fixed); 699 return Length(height()->currentValue()->value(lengthContext), Fixed);
719 }
720
721 ASSERT(renderer());
722 return renderer()->style()->height();
723 } 700 }
724 701
725 AffineTransform SVGSVGElement::viewBoxToViewTransform(float viewWidth, float vie wHeight) const 702 AffineTransform SVGSVGElement::viewBoxToViewTransform(float viewWidth, float vie wHeight) const
726 { 703 {
727 if (!m_useCurrentView || !m_viewSpec) 704 if (!m_useCurrentView || !m_viewSpec)
728 return SVGFitToViewBox::viewBoxToViewTransform(currentViewBoxRect(), pre serveAspectRatio()->currentValue(), viewWidth, viewHeight); 705 return SVGFitToViewBox::viewBoxToViewTransform(currentViewBoxRect(), pre serveAspectRatio()->currentValue(), viewWidth, viewHeight);
729 706
730 AffineTransform ctm = SVGFitToViewBox::viewBoxToViewTransform(currentViewBox Rect(), m_viewSpec->preserveAspectRatio()->currentValue(), viewWidth, viewHeight ); 707 AffineTransform ctm = SVGFitToViewBox::viewBoxToViewTransform(currentViewBox Rect(), m_viewSpec->preserveAspectRatio()->currentValue(), viewWidth, viewHeight );
731 RefPtr<SVGTransformList> transformList = m_viewSpec->transform(); 708 RefPtr<SVGTransformList> transformList = m_viewSpec->transform();
732 if (transformList->isEmpty()) 709 if (transformList->isEmpty())
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
824 // Fall back to traversing our subtree. Duplicate ids are allowed, the first found will 801 // Fall back to traversing our subtree. Duplicate ids are allowed, the first found will
825 // be returned. 802 // be returned.
826 for (Element* element = ElementTraversal::firstWithin(*this); element; eleme nt = ElementTraversal::next(*element, this)) { 803 for (Element* element = ElementTraversal::firstWithin(*this); element; eleme nt = ElementTraversal::next(*element, this)) {
827 if (element->getIdAttribute() == id) 804 if (element->getIdAttribute() == id)
828 return element; 805 return element;
829 } 806 }
830 return 0; 807 return 0;
831 } 808 }
832 809
833 } 810 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698