Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |