2 Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
3 2004, 2005, 2007 Rob Buis <buis@kde.org>
4 2007 Eric Seidel <eric@webkit.org>
6 This file is part of the KDE project
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
18 You should have received a copy of the GNU Library General Public License
19 aint with this library; see the file COPYING.LIB. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA.
25 #include "wtf/Platform.h"
29 #include "RenderSVGRoot.h"
31 /*#include "GraphicsContext.h"
32 #include "RenderPath.h"
33 #include "RenderSVGContainer.h"
34 #include "RenderView.h"*/
35 #include "SVGLength.h"
36 /*#include "SVGRenderSupport.h"
37 #include "SVGResourceClipper.h"
38 #include "SVGResourceFilter.h"
39 #include "SVGResourceMasker.h"*/
40 #include "SVGSVGElement.h"
41 #include "SVGStyledElement.h"
42 /*#include "SVGURIReference.h"*/
46 RenderSVGRoot::RenderSVGRoot(SVGStyledElement
* node
)
47 : RenderBox(node
) /*RenderContainer(node)*/
52 RenderSVGRoot::~RenderSVGRoot()
56 short RenderSVGRoot::lineHeight(bool b
, bool isRootLineBox
) const
58 return height() + marginTop() + marginBottom();
61 short RenderSVGRoot::baselinePosition(bool b
, bool isRootLineBox
) const
63 return height() + marginTop() + marginBottom();
66 void RenderSVGRoot::calcMinMaxWidth()
68 // KHTMLAssert( !minMaxKnown() );
70 int width
= calcReplacedWidth() + paddingLeft() + paddingRight() + borderLeft() + borderRight();
71 if (style()->width().isPercent() || (style()->width().isVariable() && style()->height().isPercent())) {
75 m_minWidth
= m_maxWidth
= width
;
80 void RenderSVGRoot::layout()
82 ASSERT(needsLayout());
86 // Arbitrary affine transforms are incompatible with LayoutState.
87 //FIXME vtokarev: view()->disableLayoutState();
88 //canvas()->disableLayoutState();
90 IntRect oldBounds
= m_absoluteBounds
;
91 IntRect oldOutlineBox
;
92 /*bool checkForRepaint = checkForRepaintDuringLayout() && selfNeedsLayout();
94 oldOutlineBox = absoluteOutlineBox();*/
99 //m_absoluteBounds = absoluteClippedOverflowRect();
100 SVGSVGElement
* svg
= static_cast<SVGSVGElement
*>(element());
101 m_width
= static_cast<int>(m_width
* svg
->currentScale());
102 m_height
= static_cast<int>(m_height
* svg
->currentScale());
104 for (RenderObject
* child
= firstChild(); child
; child
= child
->nextSibling()) {
105 if (child
->isText()) continue;
106 if (selfNeedsLayout()) // either bounds or transform changed, force kids to relayout
107 child
->setNeedsLayout(true);
109 child
->layoutIfNeeded();
110 //FIXME VTOKAREV ASSERT(!child->needsLayout());
113 /*if (checkForRepaint)
114 repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);*/
116 //FIXME vtokarev view()->enableLayoutState();
117 //canvas()->enableLayoutState();
118 setNeedsLayout(false);
121 /*void RenderSVGRoot::applyContentTransforms(PaintInfo& paintInfo, int parentX, int parentY)
123 // Translate from parent offsets (html renderers) to a relative transform (svg renderers)
125 origin.move(parentX, parentY);
126 origin.move(m_x, m_y);
127 origin.move(borderLeft(), borderTop());
128 origin.move(paddingLeft(), paddingTop());
130 if (origin.x() || origin.y()) {
131 paintInfo.context->concatCTM(AffineTransform().translate(origin.x(), origin.y()));
132 paintInfo.rect.move(-origin.x(), -origin.y());
135 // Respect scroll offset caused by html parents
136 AffineTransform ctm = RenderContainer::absoluteTransform();
137 paintInfo.rect.move(static_cast<int>(ctm.e()), static_cast<int>(ctm.f()));
139 SVGSVGElement* svg = static_cast<SVGSVGElement*>(element());
140 paintInfo.context->concatCTM(AffineTransform().scale(svg->currentScale()));
142 if (!viewport().isEmpty()) {
143 if (style()->overflowX() != OVISIBLE)
144 paintInfo.context->clip(enclosingIntRect(viewport())); // FIXME: Eventually we'll want float-precision clipping
146 paintInfo.context->concatCTM(AffineTransform().translate(viewport().x(), viewport().y()));
149 paintInfo.context->concatCTM(AffineTransform().translate(svg->currentTranslate().x(), svg->currentTranslate().y()));
152 void RenderSVGRoot::paint(PaintInfo
& paintInfo
, int parentX
, int parentY
)
156 SVGSVGElement
* svg
= static_cast<SVGSVGElement
*>(element());
157 if (viewport().width() <= 0. || viewport().height() <= 0.)
160 if (shouldPaintBackgroundOrBorder()) {
161 paintBoxDecorations(paintInfo
, m_x
+ parentX
, m_y
+ parentY
);
164 RenderObject::PaintInfo
childPaintInfo(paintInfo
);
165 childPaintInfo
.p
->save();
166 childPaintInfo
.p
->setRenderHint(QPainter::Antialiasing
);
167 childPaintInfo
.p
->setRenderHint(QPainter::SmoothPixmapTransform
);
169 RenderBox::paint(childPaintInfo
, 0, 0);
171 childPaintInfo
.p
->restore();
174 kDebug() << "in paint()" << endl
;
175 /*if (!paintInfo.context) {
176 GraphicsContext context(paintInfo.p);
177 paintInfo.context = &context;
178 kDebug() << "context:" << &context << endl;
180 if (paintInfo
.context
->paintingDisabled())
185 SVGSVGElement
* svg
= static_cast<SVGSVGElement
*>(element());
186 // A value of zero disables rendering of the element.
187 kDebug() << "viewport:" << viewport().width() << viewport().height() << endl
;
188 if (viewport().width() <= 0. || viewport().height() <= 0.)
190 kDebug() << "painting:" << parentX
<< parentY
<< viewport().width() << viewport().height() << endl
;
193 // This should only exist for <svg> renderers
194 /*if (hasBoxDecorations() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection))*/
195 paintBoxDecorations(paintInfo
, m_x
+ parentX
, m_y
+ parentY
);
197 /*if (!firstChild()) {
198 #if ENABLE(SVG_FILTERS)
199 // Spec: groups w/o children still may render filter content.
200 const SVGRenderStyle* svgStyle = style()->svgStyle();
201 AtomicString filterId(SVGURIReference::getTarget(svgStyle->filter()));
202 SVGResourceFilter* filter = getFilterById(document(), filterId);
207 paintInfo
.p
->fillRect(parentX
, parentY
, viewport().width(), viewport().height(), QBrush(Qt::green
));
209 RenderObject::PaintInfo
childPaintInfo(paintInfo
);
210 childPaintInfo
.context
->save();
211 kDebug() << "context= " << childPaintInfo
.context
<< "parent=" << paintInfo
.context
<< endl
;
213 /*applyContentTransforms(childPaintInfo, parentX, parentY);
215 SVGResourceFilter* filter = 0;
217 FloatRect boundingBox = relativeBBox(true);
218 if (childPaintInfo.phase == PaintPhaseForeground)
219 prepareToRenderSVGContent(this, childPaintInfo, boundingBox, filter);*/
221 //childPaintInfo.context->concatCTM(svg->viewBoxToViewTransform(width(), height()));
222 /*RenderContainer*/RenderBox::paint(childPaintInfo
, 0, 0);
224 /*if (childPaintInfo.phase == PaintPhaseForeground)
225 finishRenderSVGContent(this, childPaintInfo, boundingBox, filter, paintInfo.context);*/
227 childPaintInfo
.context
->restore();
229 /*if ((childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE)
230 paintOutline(childPaintInfo.context, m_absoluteBounds.x(), m_absoluteBounds.y(), m_absoluteBounds.width(), m_absoluteBounds.height(), style());*/
234 FloatRect
RenderSVGRoot::viewport() const
239 void RenderSVGRoot::calcViewport()
241 SVGElement
* svgelem
= static_cast<SVGElement
*>(element());
242 if (svgelem
->hasTagName(SVGNames::svgTag
)) {
243 SVGSVGElement
* svg
= static_cast<SVGSVGElement
*>(element());
245 if (!selfNeedsLayout() && !svg
->hasRelativeValues())
249 SVGLength width
= svg
->width();
250 if (width
.unitType() == LengthTypePercentage
&& svg
->hasSetContainerSize())
251 w
= svg
->relativeWidthValue();
255 SVGLength height
= svg
->height();
256 if (height
.unitType() == LengthTypePercentage
&& svg
->hasSetContainerSize())
257 h
= svg
->relativeHeightValue();
260 m_viewport
= FloatRect(0, 0, w
, h
);
264 IntRect
RenderSVGRoot::absoluteClippedOverflowRect()
266 /*IntRect repaintRect;
268 for (RenderObject* current = firstChild(); current != 0; current = current->nextSibling())
269 repaintRect.unite(current->absoluteClippedOverflowRect());
271 #if ENABLE(SVG_FILTERS)
272 // Filters can expand the bounding box
273 SVGResourceFilter* filter = getFilterById(document(), SVGURIReference::getTarget(style()->svgStyle()->filter()));
275 repaintRect.unite(enclosingIntRect(filter->filterBBoxForItemBBox(repaintRect)));
278 return repaintRect;*/
283 /*void RenderSVGRoot::addFocusRingRects(GraphicsContext* graphicsContext, int, int)
285 graphicsContext->addFocusRingRect(m_absoluteBounds);
288 void RenderSVGRoot::absoluteRects(Vector
<IntRect
>& rects
, int, int)
290 /*for (RenderObject* current = firstChild(); current != 0; current = current->nextSibling())
291 current->absoluteRects(rects, 0, 0);*/
294 AffineTransform
RenderSVGRoot::absoluteTransform() const
296 AffineTransform ctm
= RenderContainer::absoluteTransform();
297 ctm
.translate(m_x
, m_y
);
298 SVGSVGElement
* svg
= static_cast<SVGSVGElement
*>(element());
299 ctm
.scale(svg
->currentScale());
300 ctm
.translate(svg
->currentTranslate().x(), svg
->currentTranslate().y());
301 ctm
.translate(viewport().x(), viewport().y());
302 return svg
->viewBoxToViewTransform(width(), height()) * ctm
;
305 FloatRect
RenderSVGRoot::relativeBBox(bool includeStroke
) const
309 RenderObject
* current
= firstChild();
310 /*for (; current != 0; current = current->nextSibling()) {
311 FloatRect childBBox = current->relativeBBox(includeStroke);
312 FloatRect mappedBBox = current->localTransform().mapRect(childBBox);
313 // <svg> can have a viewBox contributing to the bbox
314 if (current->isSVGContainer())
315 mappedBBox = static_cast<RenderSVGContainer*>(current)->viewportTransform().mapRect(mappedBBox);
316 rect.unite(mappedBBox);
322 AffineTransform
RenderSVGRoot::localTransform() const
324 return AffineTransform();
327 /*bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
329 AffineTransform ctm = RenderContainer::absoluteTransform();
331 int sx = (_tx - static_cast<int>(ctm.e())); // scroll offset
332 int sy = (_ty - static_cast<int>(ctm.f())); // scroll offset
334 if (!viewport().isEmpty()
335 && style()->overflowX() == OHIDDEN
336 && style()->overflowY() == OHIDDEN) {
337 int tx = m_x - _tx + sx;
338 int ty = m_y - _ty + sy;
340 // Check if we need to do anything at all.
341 IntRect overflowBox = overflowRect(false);
342 overflowBox.move(tx, ty);
343 ctm.translate(viewport().x(), viewport().y());
344 double localX, localY;
345 ctm.inverse().map(_x - _tx, _y - _ty, &localX, &localY);
346 if (!overflowBox.contains((int)localX, (int)localY))
350 for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
351 if (child->nodeAtPoint(request, result, _x - sx, _y - sy, 0, 0, hitTestAction)) {
352 updateHitTestResult(result, IntPoint(_x - _tx, _y - _ty));
357 // Spec: Only graphical elements can be targeted by the mouse, period.
358 // 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."
365 #endif // ENABLE(SVG)