IntSize SVGImage::containerSize() const { if (!m_page) return IntSize(); Frame* frame = m_page->mainFrame(); SVGSVGElement* rootElement = toSVGDocument(frame->document())->rootElement(); if (!rootElement) return IntSize(); RenderSVGRoot* renderer = toRenderSVGRoot(rootElement->renderer()); if (!renderer) return IntSize(); // If a container size is available it has precedence. IntSize containerSize = renderer->containerSize(); if (!containerSize.isEmpty()) return containerSize; // Assure that a container size is always given for a non-identity zoom level. ASSERT(renderer->style()->effectiveZoom() == 1); FloatSize currentSize; if (rootElement->intrinsicWidth().isFixed() && rootElement->intrinsicHeight().isFixed()) currentSize = rootElement->currentViewportSize(); else currentSize = rootElement->currentViewBoxRect().size(); if (!currentSize.isEmpty()) return IntSize(static_cast<int>(ceilf(currentSize.width())), static_cast<int>(ceilf(currentSize.height()))); // As last resort, use CSS default intrinsic size. return IntSize(300, 150); }
bool SVGSVGElement::widthAttributeEstablishesViewport() const { if (!renderer() || renderer()->isSVGViewportContainer()) return true; // Spec: http://www.w3.org/TR/SVG/coords.html#ViewportSpace // The ‘width’ attribute on the outermost svg element establishes the viewport's width, unless the following conditions are met: // - the SVG content is a separately stored resource that is embedded by reference (such as the ‘object’ element in XHTML [XHTML]), or // the SVG content is embedded inline within a containing document; // - and the referencing element or containing document is styled using CSS [CSS2] or XSL [XSL]; // - and there are CSS-compatible positioning properties ([CSS2], section 9.3) specified on the referencing element (e.g., the ‘object’ element) // or on the containing document's outermost svg element that are sufficient to establish the width of the viewport. Under these conditions, // the positioning properties establish the viewport's width. RenderSVGRoot* root = toRenderSVGRoot(renderer()); // SVG embedded through object/embed/iframe. if (root->isEmbeddedThroughFrameContainingSVGDocument()) return !root->hasReplacedLogicalWidth() && !document()->frame()->ownerRenderer()->hasReplacedLogicalWidth(); // SVG embedded via SVGImage (background-image/border-image/etc) / Inline SVG. if (root->isEmbeddedThroughSVGImage() || document()->documentElement() != this) return !root->hasReplacedLogicalWidth(); return true; }
void SVGImage::drawSVGToImageBuffer(ImageBuffer* buffer, const IntSize& size, float zoom, ShouldClearBuffer shouldClear) { // FIXME: This doesn't work correctly with animations. If an image contains animations, that say run for 2 seconds, // and we currently have one <img> that displays us. If we open another document referencing the same SVGImage it // will display the document at a time where animations already ran - even though it has its own ImageBuffer. // We currently don't implement SVGSVGElement::setCurrentTime, and can NOT go back in time, once animations started. // There's no way to fix this besides avoiding style/attribute mutations from SVGAnimationElement. ASSERT(buffer); ASSERT(!size.isEmpty()); if (!m_page) return; Frame* frame = m_page->mainFrame(); SVGSVGElement* rootElement = static_cast<SVGDocument*>(frame->document())->rootElement(); if (!rootElement) return; RenderSVGRoot* renderer = toRenderSVGRoot(rootElement->renderer()); if (!renderer) return; // Draw image at requested size. ImageObserver* observer = imageObserver(); ASSERT(observer); // Temporarily reset image observer, we don't want to receive any changeInRect() calls due this relayout. setImageObserver(0); renderer->setContainerSize(size); frame->view()->resize(this->size()); if (zoom != 1) frame->setPageZoomFactor(zoom); // Eventually clear image buffer. IntRect rect(IntPoint(), size); if (shouldClear == ClearImageBuffer) buffer->context()->clearRect(rect); // Draw SVG on top of ImageBuffer. draw(buffer->context(), rect, rect, ColorSpaceDeviceRGB, CompositeSourceOver); // Reset container size & zoom to initial state. Otherwhise the size() of this // image would return whatever last size was set by drawSVGToImageBuffer(). if (zoom != 1) frame->setPageZoomFactor(1); renderer->setContainerSize(IntSize()); frame->view()->resize(this->size()); if (frame->view()->needsLayout()) frame->view()->layout(); setImageObserver(observer); }
void write(TextStream& ts, const RenderSVGRoot& root, int indent) { writeIndent(ts, indent); ts << root.renderName(); if (root.element()) { String tagName = getTagName(static_cast<SVGStyledElement*>(root.element())); if (!tagName.isEmpty()) ts << " {" << tagName << "}"; } ts << root << "\n"; for (RenderObject* child = root.firstChild(); child; child = child->nextSibling()) write(ts, *child, indent + 1); }
void SVGImage::setContainerSize(const FloatSize& size) { if (!m_page || !usesContainerSize()) return; SVGSVGElement* rootElement = toSVGDocument(m_page->mainFrame().document())->rootElement(); if (!rootElement) return; RenderSVGRoot* renderer = toRenderSVGRoot(rootElement->renderer()); if (!renderer) return; FrameView* view = frameView(); view->resize(this->containerSize()); renderer->setContainerSize(IntSize(size)); }
bool SVGSVGElement::heightAttributeEstablishesViewport() const { if (!renderer() || renderer()->isSVGViewportContainer()) return true; // Spec: http://www.w3.org/TR/SVG/coords.html#IntrinsicSizing // Similarly, if there are positioning properties specified on the referencing element or on the outermost svg element // that are sufficient to establish the height of the viewport, then these positioning properties establish the viewport's // height; otherwise, the ‘height’ attribute on the outermost svg element establishes the viewport's height. RenderSVGRoot* root = toRenderSVGRoot(renderer()); // SVG embedded through object/embed/iframe. if (root->isEmbeddedThroughFrameContainingSVGDocument()) return !root->hasReplacedLogicalHeight() && !document()->frame()->ownerRenderer()->hasReplacedLogicalHeight(); // SVG embedded via SVGImage (background-image/border-image/etc) / Inline SVG. if (root->isEmbeddedThroughSVGImage() || document()->documentElement() != this) return !root->hasReplacedLogicalHeight(); return true; }