18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2006 Apple Computer, Inc.
35f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian * Copyright (C) 2009 Google, Inc.
4692e5dbf12901edacf14812a6fae25462920af42Steve Block * Copyright (C) Research In Motion Limited 2010. All rights reserved.
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is free software; you can redistribute it and/or
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modify it under the terms of the GNU Library General Public
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License as published by the Free Software Foundation; either
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version 2 of the License, or (at your option) any later version.
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is distributed in the hope that it will be useful,
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Library General Public License for more details.
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * You should have received a copy of the GNU Library General Public License
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * along with this library; see the file COPYING.LIB.  If not, write to
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Boston, MA 02110-1301, USA.
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if ENABLE(SVG) && ENABLE(SVG_FOREIGN_OBJECT)
2565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include "RenderSVGForeignObject.h"
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "GraphicsContext.h"
28967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch#include "RenderSVGResource.h"
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderView.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SVGForeignObjectElement.h"
315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include "SVGRenderSupport.h"
32692e5dbf12901edacf14812a6fae25462920af42Steve Block#include "SVGSVGElement.h"
33692e5dbf12901edacf14812a6fae25462920af42Steve Block#include "TransformState.h"
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben MurdochRenderSVGForeignObject::RenderSVGForeignObject(SVGForeignObjectElement* node)
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    : RenderSVGBlock(node)
39dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    , m_needsTransformUpdate(true)
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben MurdochRenderSVGForeignObject::~RenderSVGForeignObject()
44a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
45a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
46a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
4765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid RenderSVGForeignObject::paint(PaintInfo& paintInfo, int, int)
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (paintInfo.context->paintingDisabled())
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
52692e5dbf12901edacf14812a6fae25462920af42Steve Block    PaintInfo childPaintInfo(paintInfo);
535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    childPaintInfo.context->save();
54ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    childPaintInfo.applyTransform(localTransform());
55692e5dbf12901edacf14812a6fae25462920af42Steve Block
56ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    if (SVGRenderSupport::isOverflowHidden(this))
57692e5dbf12901edacf14812a6fae25462920af42Steve Block        childPaintInfo.context->clip(m_viewport);
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    float opacity = style()->opacity();
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (opacity < 1.0f)
615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        childPaintInfo.context->beginTransparencyLayer(opacity);
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    RenderBlock::paint(childPaintInfo, 0, 0);
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (opacity < 1.0f)
665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        childPaintInfo.context->endTransparencyLayer();
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    childPaintInfo.context->restore();
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben MurdochIntRect RenderSVGForeignObject::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer)
725f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
73ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    return SVGRenderSupport::clippedOverflowRectForRepaint(this, repaintContainer);
745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
7665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid RenderSVGForeignObject::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& repaintRect, bool fixed)
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
78ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    SVGRenderSupport::computeRectForRepaint(this, repaintContainer, repaintRect, fixed);
795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst AffineTransform& RenderSVGForeignObject::localToParentTransform() const
825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
83692e5dbf12901edacf14812a6fae25462920af42Steve Block    m_localToParentTransform = localTransform();
84692e5dbf12901edacf14812a6fae25462920af42Steve Block    m_localToParentTransform.translate(m_viewport.x(), m_viewport.y());
85692e5dbf12901edacf14812a6fae25462920af42Steve Block    return m_localToParentTransform;
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid RenderSVGForeignObject::computeLogicalWidth()
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
90692e5dbf12901edacf14812a6fae25462920af42Steve Block    // FIXME: Investigate in size rounding issues
91692e5dbf12901edacf14812a6fae25462920af42Steve Block    setWidth(static_cast<int>(roundf(m_viewport.width())));
92692e5dbf12901edacf14812a6fae25462920af42Steve Block}
93692e5dbf12901edacf14812a6fae25462920af42Steve Block
9465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid RenderSVGForeignObject::computeLogicalHeight()
95692e5dbf12901edacf14812a6fae25462920af42Steve Block{
96692e5dbf12901edacf14812a6fae25462920af42Steve Block    // FIXME: Investigate in size rounding issues
97692e5dbf12901edacf14812a6fae25462920af42Steve Block    setHeight(static_cast<int>(roundf(m_viewport.height())));
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid RenderSVGForeignObject::layout()
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(needsLayout());
1035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    ASSERT(!view()->layoutStateEnabled()); // RenderSVGRoot disables layoutState for the SVG rendering tree.
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
105bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
106692e5dbf12901edacf14812a6fae25462920af42Steve Block    SVGForeignObjectElement* foreign = static_cast<SVGForeignObjectElement*>(node());
107dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1085ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    bool updateCachedBoundariesInParents = false;
109dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (m_needsTransformUpdate) {
110dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        m_localTransform = foreign->animatedLocalTransform();
111dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        m_needsTransformUpdate = false;
1125ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        updateCachedBoundariesInParents = true;
113dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
114692e5dbf12901edacf14812a6fae25462920af42Steve Block
1155ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    FloatRect oldViewport = m_viewport;
1165ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
117692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Cache viewport boundaries
118692e5dbf12901edacf14812a6fae25462920af42Steve Block    FloatPoint viewportLocation(foreign->x().value(foreign), foreign->y().value(foreign));
119692e5dbf12901edacf14812a6fae25462920af42Steve Block    m_viewport = FloatRect(viewportLocation, FloatSize(foreign->width().value(foreign), foreign->height().value(foreign)));
1205ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (!updateCachedBoundariesInParents)
1215ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        updateCachedBoundariesInParents = oldViewport != m_viewport;
122692e5dbf12901edacf14812a6fae25462920af42Steve Block
123692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Set box origin to the foreignObject x/y translation, so positioned objects in XHTML content get correct
124692e5dbf12901edacf14812a6fae25462920af42Steve Block    // positions. A regular RenderBoxModelObject would pull this information from RenderStyle - in SVG those
125692e5dbf12901edacf14812a6fae25462920af42Steve Block    // properties are ignored for non <svg> elements, so we mimic what happens when specifying them through CSS.
126692e5dbf12901edacf14812a6fae25462920af42Steve Block
12765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // FIXME: Investigate in location rounding issues - only affects RenderSVGForeignObject & RenderSVGText
128692e5dbf12901edacf14812a6fae25462920af42Steve Block    setLocation(roundedIntPoint(viewportLocation));
129db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
130db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    bool layoutChanged = m_everHadLayout && selfNeedsLayout();
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderBlock::layout();
132db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    ASSERT(!needsLayout());
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1345ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // If our bounds changed, notify the parents.
1355ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (updateCachedBoundariesInParents)
1365ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        RenderSVGBlock::setNeedsBoundariesUpdate();
1375ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
138db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    // Invalidate all resources of this client if our layout changed.
139db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    if (layoutChanged)
140db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        SVGResourcesCache::clientLayoutChanged(this);
141967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch
142692e5dbf12901edacf14812a6fae25462920af42Steve Block    repainter.repaintAfterLayout();
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
14565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochbool RenderSVGForeignObject::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
1465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
147692e5dbf12901edacf14812a6fae25462920af42Steve Block    FloatPoint localPoint = localTransform().inverse().mapPoint(pointInParent);
148692e5dbf12901edacf14812a6fae25462920af42Steve Block
149692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Early exit if local point is not contained in clipped viewport area
150ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    if (SVGRenderSupport::isOverflowHidden(this) && !m_viewport.contains(localPoint))
151692e5dbf12901edacf14812a6fae25462920af42Steve Block        return false;
152692e5dbf12901edacf14812a6fae25462920af42Steve Block
153692e5dbf12901edacf14812a6fae25462920af42Steve Block    IntPoint roundedLocalPoint = roundedIntPoint(localPoint);
154692e5dbf12901edacf14812a6fae25462920af42Steve Block    return RenderBlock::nodeAtPoint(request, result, roundedLocalPoint.x(), roundedLocalPoint.y(), 0, 0, hitTestAction);
1555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
1565f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
15765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochbool RenderSVGForeignObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int, HitTestAction)
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    ASSERT_NOT_REACHED();
1605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return false;
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
16365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid RenderSVGForeignObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState) const
164d0825bca7fe65beaee391d30da42e937db621564Steve Block{
165692e5dbf12901edacf14812a6fae25462920af42Steve Block    // When crawling up the hierachy starting from foreignObject child content, useTransforms may not be set to true.
166692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (!useTransforms)
167692e5dbf12901edacf14812a6fae25462920af42Steve Block        useTransforms = true;
168ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    SVGRenderSupport::mapLocalToContainer(this, repaintContainer, fixed, useTransforms, transformState);
169d0825bca7fe65beaee391d30da42e937db621564Steve Block}
170d0825bca7fe65beaee391d30da42e937db621564Steve Block
171692e5dbf12901edacf14812a6fae25462920af42Steve Block}
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
173692e5dbf12901edacf14812a6fae25462920af42Steve Block#endif
174