Warning, file /frameworks/khtml/src/rendering/RenderSVGRoot.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
0003                   2004, 2005, 2007 Rob Buis <buis@kde.org>
0004                   2007 Eric Seidel <eric@webkit.org>
0005 
0006     This file is part of the KDE project
0007 
0008     This library is free software; you can redistribute it and/or
0009     modify it under the terms of the GNU Library General Public
0010     License as published by the Free Software Foundation; either
0011     version 2 of the License, or (at your option) any later version.
0012 
0013     This library is distributed in the hope that it will be useful,
0014     but WITHOUT ANY WARRANTY; without even the implied warranty of
0015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0016     Library General Public License for more details.
0017 
0018     You should have received a copy of the GNU Library General Public License
0019     aint with this library; see the file COPYING.LIB.  If not, write to
0020     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0021     Boston, MA 02110-1301, USA.
0022 */
0023 
0024 #include "wtf/Platform.h"
0025 #include "Document.h"
0026 
0027 #if ENABLE(SVG)
0028 #include "RenderSVGRoot.h"
0029 
0030 /*#include "GraphicsContext.h"
0031 #include "RenderPath.h"
0032 #include "RenderSVGContainer.h"
0033 #include "RenderView.h"*/
0034 #include "SVGLength.h"
0035 /*#include "SVGRenderSupport.h"
0036 #include "SVGResourceClipper.h"
0037 #include "SVGResourceFilter.h"
0038 #include "SVGResourceMasker.h"*/
0039 #include "SVGSVGElement.h"
0040 #include "SVGStyledElement.h"
0041 /*#include "SVGURIReference.h"*/
0042 
0043 namespace WebCore
0044 {
0045 
0046 RenderSVGRoot::RenderSVGRoot(SVGStyledElement *node)
0047     : RenderBox(node) /*RenderContainer(node)*/
0048 {
0049     setReplaced(true);
0050 }
0051 
0052 RenderSVGRoot::~RenderSVGRoot()
0053 {
0054 }
0055 
0056 short RenderSVGRoot::lineHeight(bool b) const
0057 {
0058     Q_UNUSED(b);
0059     return height() + marginTop() + marginBottom();
0060 }
0061 
0062 short RenderSVGRoot::baselinePosition(bool b) const
0063 {
0064     Q_UNUSED(b);
0065     return height() + marginTop() + marginBottom();
0066 }
0067 
0068 void RenderSVGRoot::calcMinMaxWidth()
0069 {
0070 //    KHTMLAssert( !minMaxKnown() );
0071 
0072     int width = calcReplacedWidth() + paddingLeft() + paddingRight() + borderLeft() + borderRight();
0073     if (style()->width().isPercent() || (style()->width().isAuto() && style()->height().isPercent())) {
0074         m_minWidth = 0;
0075         m_maxWidth = width;
0076     } else {
0077         m_minWidth = m_maxWidth = width;
0078     }
0079 
0080     setMinMaxKnown();
0081 }
0082 
0083 void RenderSVGRoot::layout()
0084 {
0085     ASSERT(needsLayout());
0086 
0087     calcViewport();
0088 
0089     // Arbitrary affine transforms are incompatible with LayoutState.
0090     //FIXME vtokarev: view()->disableLayoutState();
0091     //canvas()->disableLayoutState();
0092 
0093     /*IntRect oldBounds = m_absoluteBounds;
0094     IntRect oldOutlineBox;
0095     bool checkForRepaint = checkForRepaintDuringLayout() && selfNeedsLayout();
0096     if (checkForRepaint)
0097         oldOutlineBox = absoluteOutlineBox();*/
0098 
0099     calcWidth();
0100     calcHeight();
0101 
0102     //m_absoluteBounds = absoluteClippedOverflowRect();
0103     SVGSVGElement *svg = static_cast<SVGSVGElement *>(element());
0104     m_width = static_cast<int>(m_width * svg->currentScale());
0105     m_height = static_cast<int>(m_height * svg->currentScale());
0106 
0107     for (RenderObject *child = firstChild(); child; child = child->nextSibling()) {
0108         // ### TODO: we only want to relayout if our size/transform changed kids
0109         if (child->isText()) {
0110             continue;
0111         }
0112         child->setNeedsLayout(true);
0113         child->layoutIfNeeded();
0114         // ASSERT(!child->needsLayout());
0115     }
0116 
0117     /*if (checkForRepaint)
0118         repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);*/
0119 
0120     //FIXME vtokarev view()->enableLayoutState();
0121     //canvas()->enableLayoutState();
0122     setNeedsLayout(false);
0123 }
0124 
0125 /*void RenderSVGRoot::applyContentTransforms(PaintInfo& paintInfo, int parentX, int parentY)
0126 {
0127     // Translate from parent offsets (html renderers) to a relative transform (svg renderers)
0128     IntPoint origin;
0129     origin.move(parentX, parentY);
0130     origin.move(m_x, m_y);
0131     origin.move(borderLeft(), borderTop());
0132     origin.move(paddingLeft(), paddingTop());
0133 
0134     if (origin.x() || origin.y()) {
0135         paintInfo.context->concatCTM(AffineTransform().translate(origin.x(), origin.y()));
0136         paintInfo.rect.move(-origin.x(), -origin.y());
0137     }
0138 
0139     // Respect scroll offset caused by html parents
0140     AffineTransform ctm = RenderContainer::absoluteTransform();
0141     paintInfo.rect.move(static_cast<int>(ctm.e()), static_cast<int>(ctm.f()));
0142 
0143     SVGSVGElement* svg = static_cast<SVGSVGElement*>(element());
0144     paintInfo.context->concatCTM(AffineTransform().scale(svg->currentScale()));
0145 
0146     if (!viewport().isEmpty()) {
0147         if (style()->overflowX() != OVISIBLE)
0148             paintInfo.context->clip(enclosingIntRect(viewport())); // FIXME: Eventually we'll want float-precision clipping
0149 
0150         paintInfo.context->concatCTM(AffineTransform().translate(viewport().x(), viewport().y()));
0151     }
0152 
0153     paintInfo.context->concatCTM(AffineTransform().translate(svg->currentTranslate().x(), svg->currentTranslate().y()));
0154 }*/
0155 
0156 void RenderSVGRoot::paint(PaintInfo &paintInfo, int parentX, int parentY)
0157 {
0158     calcViewport();
0159 
0160     //SVGSVGElement* svg = static_cast<SVGSVGElement*>(element());
0161     if (viewport().width() <= 0. || viewport().height() <= 0.) {
0162         return;
0163     }
0164 
0165     if (shouldPaintBackgroundOrBorder()) {
0166         paintBoxDecorations(paintInfo, m_x + parentX, m_y + parentY);
0167     }
0168 
0169     RenderObject::PaintInfo childPaintInfo(paintInfo);
0170     childPaintInfo.p->save();
0171     childPaintInfo.p->setRenderHint(QPainter::Antialiasing);
0172     childPaintInfo.p->setRenderHint(QPainter::SmoothPixmapTransform);
0173 
0174     RenderBox::paint(childPaintInfo, 0, 0);
0175 
0176     childPaintInfo.p->restore();
0177 
0178 #if 0
0179     // qCDebug(KHTML_LOG) << "in paint()";
0180     /*if (!paintInfo.context) {
0181         GraphicsContext context(paintInfo.p);
0182         paintInfo.context = &context;
0183         // qCDebug(KHTML_LOG) << "context:" << &context;
0184     }*/
0185     if (paintInfo.context->paintingDisabled()) {
0186         return;
0187     }
0188 
0189     calcViewport();
0190 
0191     SVGSVGElement *svg = static_cast<SVGSVGElement *>(element());
0192     // A value of zero disables rendering of the element.
0193     // qCDebug(KHTML_LOG) << "viewport:" << viewport().width() << viewport().height();
0194     if (viewport().width() <= 0. || viewport().height() <= 0.) {
0195         return;
0196     }
0197     // qCDebug(KHTML_LOG) << "painting:" << parentX << parentY << viewport().width() << viewport().height();
0198 
0199     // This should only exist for <svg> renderers
0200     /*if (hasBoxDecorations() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection))*/
0201     paintBoxDecorations(paintInfo, m_x + parentX, m_y + parentY);
0202 
0203     /*if (!firstChild()) {
0204     #if ENABLE(SVG_FILTERS)
0205         // Spec: groups w/o children still may render filter content.
0206         const SVGRenderStyle* svgStyle = style()->svgStyle();
0207         AtomicString filterId(SVGURIReference::getTarget(svgStyle->filter()));
0208         SVGResourceFilter* filter = getFilterById(document(), filterId);
0209         if (!filter)
0210     #endif
0211             return;
0212     }*/
0213     paintInfo.p->fillRect(parentX, parentY, viewport().width(), viewport().height(), QBrush(Qt::green));
0214 
0215     RenderObject::PaintInfo childPaintInfo(paintInfo);
0216     childPaintInfo.context->save();
0217     // qCDebug(KHTML_LOG) << "context= " << childPaintInfo.context << "parent=" << paintInfo.context;
0218 
0219     /*applyContentTransforms(childPaintInfo, parentX, parentY);
0220 
0221     SVGResourceFilter* filter = 0;
0222 
0223     FloatRect boundingBox = relativeBBox(true);
0224     if (childPaintInfo.phase == PaintPhaseForeground)
0225         prepareToRenderSVGContent(this, childPaintInfo, boundingBox, filter);*/
0226 
0227     //childPaintInfo.context->concatCTM(svg->viewBoxToViewTransform(width(), height()));
0228     /*RenderContainer*/RenderBox::paint(childPaintInfo, 0, 0);
0229 
0230     /*if (childPaintInfo.phase == PaintPhaseForeground)
0231         finishRenderSVGContent(this, childPaintInfo, boundingBox, filter, paintInfo.context);*/
0232 
0233     childPaintInfo.context->restore();
0234 
0235     /*if ((childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE)
0236         paintOutline(childPaintInfo.context, m_absoluteBounds.x(), m_absoluteBounds.y(), m_absoluteBounds.width(), m_absoluteBounds.height(), style());*/
0237 #endif
0238 }
0239 
0240 FloatRect RenderSVGRoot::viewport() const
0241 {
0242     return m_viewport;
0243 }
0244 
0245 void RenderSVGRoot::calcViewport()
0246 {
0247     SVGElement *svgelem = static_cast<SVGElement *>(element());
0248     if (svgelem->hasTagName(SVGNames::svgTag)) {
0249         SVGSVGElement *svg = static_cast<SVGSVGElement *>(element());
0250 
0251         if (!selfNeedsLayout() && !svg->hasRelativeValues()) {
0252             return;
0253         }
0254 
0255         float w, h;
0256         SVGLength width = svg->width();
0257         if (width.unitType() == LengthTypePercentage && svg->hasSetContainerSize()) {
0258             w = svg->relativeWidthValue();
0259         } else {
0260             w = width.value();
0261         }
0262 
0263         SVGLength height = svg->height();
0264         if (height.unitType() == LengthTypePercentage && svg->hasSetContainerSize()) {
0265             h = svg->relativeHeightValue();
0266         } else {
0267             h = height.value();
0268         }
0269         m_viewport = FloatRect(0, 0, w, h);
0270     }
0271 }
0272 
0273 IntRect RenderSVGRoot::absoluteClippedOverflowRect()
0274 {
0275     /*IntRect repaintRect;
0276 
0277     for (RenderObject* current = firstChild(); current != 0; current = current->nextSibling())
0278         repaintRect.unite(current->absoluteClippedOverflowRect());
0279 
0280     #if ENABLE(SVG_FILTERS)
0281     // Filters can expand the bounding box
0282     SVGResourceFilter* filter = getFilterById(document(), SVGURIReference::getTarget(style()->svgStyle()->filter()));
0283     if (filter)
0284         repaintRect.unite(enclosingIntRect(filter->filterBBoxForItemBBox(repaintRect)));
0285     #endif
0286 
0287     return repaintRect;*/
0288     ASSERT(false);
0289     return IntRect();
0290 }
0291 
0292 /*void RenderSVGRoot::addFocusRingRects(GraphicsContext* graphicsContext, int, int)
0293 {
0294     graphicsContext->addFocusRingRect(m_absoluteBounds);
0295 }*/
0296 
0297 void RenderSVGRoot::absoluteRects(Vector<IntRect> &rects, int, int)
0298 {
0299     Q_UNUSED(rects);
0300     /*for (RenderObject* current = firstChild(); current != 0; current = current->nextSibling())
0301         current->absoluteRects(rects, 0, 0);*/
0302 }
0303 
0304 AffineTransform RenderSVGRoot::absoluteTransform() const
0305 {
0306     AffineTransform ctm = RenderContainer::absoluteTransform();
0307     ctm.translate(m_x, m_y);
0308     SVGSVGElement *svg = static_cast<SVGSVGElement *>(element());
0309     ctm.scale(svg->currentScale());
0310     ctm.translate(svg->currentTranslate().x(), svg->currentTranslate().y());
0311     ctm.translate(viewport().x(), viewport().y());
0312     return svg->viewBoxToViewTransform(width(), height()) * ctm;
0313 }
0314 
0315 FloatRect RenderSVGRoot::relativeBBox(bool includeStroke) const
0316 {
0317     Q_UNUSED(includeStroke);
0318     FloatRect rect;
0319 
0320     //RenderObject* current = firstChild();
0321     /*for (; current != 0; current = current->nextSibling()) {
0322         FloatRect childBBox = current->relativeBBox(includeStroke);
0323         FloatRect mappedBBox = current->localTransform().mapRect(childBBox);
0324         // <svg> can have a viewBox contributing to the bbox
0325         if (current->isSVGContainer())
0326             mappedBBox = static_cast<RenderSVGContainer*>(current)->viewportTransform().mapRect(mappedBBox);
0327         rect.unite(mappedBBox);
0328     }*/
0329 
0330     return rect;
0331 }
0332 
0333 AffineTransform RenderSVGRoot::localTransform() const
0334 {
0335     return AffineTransform();
0336 }
0337 
0338 /*bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
0339 {
0340     AffineTransform ctm = RenderContainer::absoluteTransform();
0341 
0342     int sx = (_tx - static_cast<int>(ctm.e())); // scroll offset
0343     int sy = (_ty - static_cast<int>(ctm.f())); // scroll offset
0344 
0345     if (!viewport().isEmpty()
0346         && style()->overflowX() == OHIDDEN
0347         && style()->overflowY() == OHIDDEN) {
0348         int tx = m_x - _tx + sx;
0349         int ty = m_y - _ty + sy;
0350 
0351         // Check if we need to do anything at all.
0352         IntRect overflowBox = overflowRect(false);
0353         overflowBox.move(tx, ty);
0354         ctm.translate(viewport().x(), viewport().y());
0355         double localX, localY;
0356         ctm.inverse().map(_x - _tx, _y - _ty, &localX, &localY);
0357         if (!overflowBox.contains((int)localX, (int)localY))
0358             return false;
0359     }
0360 
0361     for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
0362         if (child->nodeAtPoint(request, result, _x - sx, _y - sy, 0, 0, hitTestAction)) {
0363             updateHitTestResult(result, IntPoint(_x - _tx, _y - _ty));
0364             return true;
0365         }
0366     }
0367 
0368     // Spec: Only graphical elements can be targeted by the mouse, period.
0369     // 16.4: "If there are no graphics elements whose relevant graphics content is under the pointer (i.e., there is no target element), the event is not dispatched."
0370     return false;
0371 }*/
0372 
0373 }
0374 
0375 #endif // ENABLE(SVG)
0376