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

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 mishap during rebase in svg.css 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 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 m_height->setBaseValueAsString(value, parseError); 251 m_height->setBaseValueAsString(value, parseError);
252 } else if (SVGFitToViewBox::parseAttribute(name, value, document(), parseErr or)) { 252 } else if (SVGFitToViewBox::parseAttribute(name, value, document(), parseErr or)) {
253 } else if (SVGZoomAndPan::parseAttribute(name, value)) { 253 } else if (SVGZoomAndPan::parseAttribute(name, value)) {
254 } else { 254 } else {
255 SVGGraphicsElement::parseAttribute(name, value); 255 SVGGraphicsElement::parseAttribute(name, value);
256 } 256 }
257 257
258 reportAttributeParsingError(parseError, name, value); 258 reportAttributeParsingError(parseError, name, value);
259 } 259 }
260 260
261 bool SVGSVGElement::isPresentationAttribute(const QualifiedName& name) const
262 {
263 if (isOutermostSVGSVGElement() && (name == SVGNames::widthAttr || name == SV GNames::heightAttr))
264 return true;
265 return SVGGraphicsElement::isPresentationAttribute(name);
266 }
267
268 void SVGSVGElement::collectStyleForPresentationAttribute(const QualifiedName& na me, const AtomicString& value, MutableStylePropertySet* style)
269 {
270 if (isOutermostSVGSVGElement() && (name == SVGNames::widthAttr || name == SV GNames::heightAttr)) {
271 RefPtr<SVGLength> length = SVGLength::create(LengthModeOther);
272 length->setValueAsString(value, IGNORE_EXCEPTION);
273 if (length->unitType() != LengthTypeUnknown) {
274 if (name == SVGNames::widthAttr)
275 addPropertyToPresentationAttributeStyle(style, CSSPropertyWidth, value);
276 else if (name == SVGNames::heightAttr)
277 addPropertyToPresentationAttributeStyle(style, CSSPropertyHeight , value);
278 }
279 } else {
280 SVGGraphicsElement::collectStyleForPresentationAttribute(name, value, st yle);
281 }
282 }
283
261 void SVGSVGElement::svgAttributeChanged(const QualifiedName& attrName) 284 void SVGSVGElement::svgAttributeChanged(const QualifiedName& attrName)
262 { 285 {
263 bool updateRelativeLengthsOrViewBox = false; 286 bool updateRelativeLengthsOrViewBox = false;
264 bool widthChanged = attrName == SVGNames::widthAttr; 287 bool widthChanged = attrName == SVGNames::widthAttr;
265 if (widthChanged 288 bool heightChanged = attrName == SVGNames::heightAttr;
266 || attrName == SVGNames::heightAttr 289 if (widthChanged || heightChanged
267 || attrName == SVGNames::xAttr 290 || attrName == SVGNames::xAttr
268 || attrName == SVGNames::yAttr) { 291 || attrName == SVGNames::yAttr) {
269 updateRelativeLengthsOrViewBox = true; 292 updateRelativeLengthsOrViewBox = true;
270 updateRelativeLengthsInformation(); 293 updateRelativeLengthsInformation();
271 invalidateRelativeLengthClients(); 294 invalidateRelativeLengthClients();
272 295
273 // At the SVG/HTML boundary (aka RenderSVGRoot), the width attribute can 296 // At the SVG/HTML boundary (aka RenderSVGRoot), the width and
274 // affect the replaced size so we need to mark it for updating. 297 // height attributes can affect the replaced size so we need
275 if (widthChanged) { 298 // to mark it for updating.
299 //
300 // FIXME: For width/height animated as XML attributes on SVG
301 // roots, there is an attribute synchronization missing. See
302 // http://crbug.com/364807
303 if (widthChanged || heightChanged) {
276 RenderObject* renderObject = renderer(); 304 RenderObject* renderObject = renderer();
277 if (renderObject && renderObject->isSVGRoot()) 305 if (renderObject && renderObject->isSVGRoot()) {
278 toRenderSVGRoot(renderObject)->setNeedsLayoutAndPrefWidthsRecalc (); 306 invalidateSVGPresentationAttributeStyle();
307 setNeedsStyleRecalc(LocalStyleChange);
308 }
279 } 309 }
280 } 310 }
281 311
282 if (SVGFitToViewBox::isKnownAttribute(attrName)) { 312 if (SVGFitToViewBox::isKnownAttribute(attrName)) {
283 updateRelativeLengthsOrViewBox = true; 313 updateRelativeLengthsOrViewBox = true;
284 if (RenderObject* object = renderer()) 314 if (RenderObject* object = renderer())
285 object->setNeedsTransformUpdate(); 315 object->setNeedsTransformUpdate();
286 } 316 }
287 317
288 SVGElementInstance::InvalidationGuard invalidationGuard(this); 318 SVGElementInstance::InvalidationGuard invalidationGuard(this);
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 return m_viewSpec ? m_viewSpec->viewBox()->currentValue()->value() : Flo atRect(); 618 return m_viewSpec ? m_viewSpec->viewBox()->currentValue()->value() : Flo atRect();
589 619
590 FloatRect useViewBox = viewBox()->currentValue()->value(); 620 FloatRect useViewBox = viewBox()->currentValue()->value();
591 if (!useViewBox.isEmpty()) 621 if (!useViewBox.isEmpty())
592 return useViewBox; 622 return useViewBox;
593 if (!renderer() || !renderer()->isSVGRoot()) 623 if (!renderer() || !renderer()->isSVGRoot())
594 return FloatRect(); 624 return FloatRect();
595 if (!toRenderSVGRoot(renderer())->isEmbeddedThroughSVGImage()) 625 if (!toRenderSVGRoot(renderer())->isEmbeddedThroughSVGImage())
596 return FloatRect(); 626 return FloatRect();
597 627
598 Length intrinsicWidth = this->intrinsicWidth();
599 Length intrinsicHeight = this->intrinsicHeight();
600 if (!intrinsicWidth.isFixed() || !intrinsicHeight.isFixed())
601 return FloatRect();
602
603 // If no viewBox is specified but non-relative width/height values, then we 628 // If no viewBox is specified but non-relative width/height values, then we
604 // should always synthesize a viewBox if we're embedded through a SVGImage. 629 // should always synthesize a viewBox if we're embedded through a SVGImage.
605 return FloatRect(FloatPoint(), FloatSize(floatValueForLength(intrinsicWidth, 0), floatValueForLength(intrinsicHeight, 0))); 630 return FloatRect(FloatPoint(), FloatSize(floatValueForLength(intrinsicWidth( ), 0), floatValueForLength(intrinsicHeight(), 0)));
606 } 631 }
607 632
608 FloatSize SVGSVGElement::currentViewportSize() const 633 FloatSize SVGSVGElement::currentViewportSize() const
609 { 634 {
610 Length intrinsicWidth = this->intrinsicWidth(); 635 if (hasIntrinsicWidth() && hasIntrinsicHeight()) {
611 Length intrinsicHeight = this->intrinsicHeight(); 636 Length intrinsicWidth = this->intrinsicWidth();
612 if (intrinsicWidth.isFixed() && intrinsicHeight.isFixed()) 637 Length intrinsicHeight = this->intrinsicHeight();
613 return FloatSize(floatValueForLength(intrinsicWidth, 0), floatValueForLe ngth(intrinsicHeight, 0)); 638 return FloatSize(floatValueForLength(intrinsicWidth, 0), floatValueForLe ngth(intrinsicHeight, 0));
639 }
614 640
615 if (!renderer()) 641 if (!renderer())
616 return FloatSize(); 642 return FloatSize();
617 643
618 if (renderer()->isSVGRoot()) { 644 if (renderer()->isSVGRoot()) {
619 LayoutRect contentBoxRect = toRenderSVGRoot(renderer())->contentBoxRect( ); 645 LayoutRect contentBoxRect = toRenderSVGRoot(renderer())->contentBoxRect( );
620 return FloatSize(contentBoxRect.width() / renderer()->style()->effective Zoom(), contentBoxRect.height() / renderer()->style()->effectiveZoom()); 646 return FloatSize(contentBoxRect.width() / renderer()->style()->effective Zoom(), contentBoxRect.height() / renderer()->style()->effectiveZoom());
621 } 647 }
622 648
623 FloatRect viewportRect = toRenderSVGViewportContainer(renderer())->viewport( ); 649 FloatRect viewportRect = toRenderSVGViewportContainer(renderer())->viewport( );
624 return FloatSize(viewportRect.width(), viewportRect.height()); 650 return FloatSize(viewportRect.width(), viewportRect.height());
625 } 651 }
626 652
627 bool SVGSVGElement::widthAttributeEstablishesViewport() const 653 bool SVGSVGElement::hasIntrinsicWidth() const
628 { 654 {
629 if (!renderer() || renderer()->isSVGViewportContainer()) 655 return width()->currentValue()->unitType() != LengthTypePercentage;
630 return true;
631
632 // Spec: http://www.w3.org/TR/SVG/coords.html#ViewportSpace
633 // The ‘width’ attribute on the outermost svg element establishes the viewpo rt's width, unless the following conditions are met:
634 // - the SVG content is a separately stored resource that is embedded by ref erence (such as the ‘object’ element in XHTML [XHTML]), or
635 // the SVG content is embedded inline within a containing document;
636 // - and the referencing element or containing document is styled using CSS [CSS2] or XSL [XSL];
637 // - and there are CSS-compatible positioning properties ([CSS2], section 9. 3) specified on the referencing element (e.g., the ‘object’ element)
638 // or on the containing document's outermost svg element that are sufficie nt to establish the width of the viewport. Under these conditions,
639 // the positioning properties establish the viewport's width.
640 RenderSVGRoot* root = toRenderSVGRoot(renderer());
641
642 // SVG embedded through object/embed/iframe.
643 if (root->isEmbeddedThroughFrameContainingSVGDocument())
644 return !root->hasReplacedLogicalWidth() && !document().frame()->ownerRen derer()->hasReplacedLogicalWidth();
645
646 // SVG embedded via SVGImage (background-image/border-image/etc) / Inline SV G.
647 if (root->isEmbeddedThroughSVGImage() || document().documentElement() != thi s)
648 return !root->hasReplacedLogicalWidth();
649
650 return true;
651 } 656 }
652 657
653 bool SVGSVGElement::heightAttributeEstablishesViewport() const 658 bool SVGSVGElement::hasIntrinsicHeight() const
654 { 659 {
655 if (!renderer() || renderer()->isSVGViewportContainer()) 660 return height()->currentValue()->unitType() != LengthTypePercentage;
656 return true;
657
658 // Spec: http://www.w3.org/TR/SVG/coords.html#IntrinsicSizing
659 // Similarly, if there are positioning properties specified on the referenci ng element or on the outermost svg element
660 // that are sufficient to establish the height of the viewport, then these p ositioning properties establish the viewport's
661 // height; otherwise, the ‘height’ attribute on the outermost svg element es tablishes the viewport's height.
662 RenderSVGRoot* root = toRenderSVGRoot(renderer());
663
664 // SVG embedded through object/embed/iframe.
665 if (root->isEmbeddedThroughFrameContainingSVGDocument())
666 return !root->hasReplacedLogicalHeight() && !document().frame()->ownerRe nderer()->hasReplacedLogicalHeight();
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->hasReplacedLogicalHeight();
671
672 return true;
673 } 661 }
674 662
675 Length SVGSVGElement::intrinsicWidth(ConsiderCSSMode mode) const 663 Length SVGSVGElement::intrinsicWidth() const
676 { 664 {
677 if (widthAttributeEstablishesViewport() || mode == IgnoreCSSProperties) { 665 if (width()->currentValue()->unitType() == LengthTypePercentage)
678 if (m_width->currentValue()->unitType() == LengthTypePercentage) 666 return Length(0, Fixed);
679 return Length(m_width->currentValue()->valueAsPercentage() * 100, Pe rcent);
680 667
681 SVGLengthContext lengthContext(this); 668 SVGLengthContext lengthContext(this);
682 return Length(m_width->currentValue()->value(lengthContext), Fixed); 669 return Length(width()->currentValue()->value(lengthContext), Fixed);
683 }
684
685 ASSERT(renderer());
686 return renderer()->style()->width();
687 } 670 }
688 671
689 Length SVGSVGElement::intrinsicHeight(ConsiderCSSMode mode) const 672 Length SVGSVGElement::intrinsicHeight() const
690 { 673 {
691 if (heightAttributeEstablishesViewport() || mode == IgnoreCSSProperties) { 674 if (height()->currentValue()->unitType() == LengthTypePercentage)
692 if (m_height->currentValue()->unitType() == LengthTypePercentage) 675 return Length(0, Fixed);
693 return Length(m_height->currentValue()->valueAsPercentage() * 100, P ercent);
694 676
695 SVGLengthContext lengthContext(this); 677 SVGLengthContext lengthContext(this);
696 return Length(m_height->currentValue()->value(lengthContext), Fixed); 678 return Length(height()->currentValue()->value(lengthContext), Fixed);
697 }
698
699 ASSERT(renderer());
700 return renderer()->style()->height();
701 } 679 }
702 680
703 AffineTransform SVGSVGElement::viewBoxToViewTransform(float viewWidth, float vie wHeight) const 681 AffineTransform SVGSVGElement::viewBoxToViewTransform(float viewWidth, float vie wHeight) const
704 { 682 {
705 if (!m_useCurrentView || !m_viewSpec) 683 if (!m_useCurrentView || !m_viewSpec)
706 return SVGFitToViewBox::viewBoxToViewTransform(currentViewBoxRect(), pre serveAspectRatio()->currentValue(), viewWidth, viewHeight); 684 return SVGFitToViewBox::viewBoxToViewTransform(currentViewBoxRect(), pre serveAspectRatio()->currentValue(), viewWidth, viewHeight);
707 685
708 AffineTransform ctm = SVGFitToViewBox::viewBoxToViewTransform(currentViewBox Rect(), m_viewSpec->preserveAspectRatio()->currentValue(), viewWidth, viewHeight ); 686 AffineTransform ctm = SVGFitToViewBox::viewBoxToViewTransform(currentViewBox Rect(), m_viewSpec->preserveAspectRatio()->currentValue(), viewWidth, viewHeight );
709 RefPtr<SVGTransformList> transformList = m_viewSpec->transform(); 687 RefPtr<SVGTransformList> transformList = m_viewSpec->transform();
710 if (transformList->isEmpty()) 688 if (transformList->isEmpty())
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 // Fall back to traversing our subtree. Duplicate ids are allowed, the first found will 780 // Fall back to traversing our subtree. Duplicate ids are allowed, the first found will
803 // be returned. 781 // be returned.
804 for (Element* element = ElementTraversal::firstWithin(*this); element; eleme nt = ElementTraversal::next(*element, this)) { 782 for (Element* element = ElementTraversal::firstWithin(*this); element; eleme nt = ElementTraversal::next(*element, this)) {
805 if (element->getIdAttribute() == id) 783 if (element->getIdAttribute() == id)
806 return element; 784 return element;
807 } 785 }
808 return 0; 786 return 0;
809 } 787 }
810 788
811 } 789 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698