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