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 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |