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)) { |
| 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) { |
| 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 |