1/*
2 * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
3 * Copyright (C) 2006 Apple Inc. All rights reserved.
4 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB.  If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22#include "config.h"
23
24#include "core/rendering/svg/RenderSVGInline.h"
25
26#include "core/rendering/svg/RenderSVGText.h"
27#include "core/rendering/svg/SVGInlineFlowBox.h"
28#include "core/rendering/svg/SVGRenderSupport.h"
29#include "core/rendering/svg/SVGResourcesCache.h"
30#include "core/svg/SVGAElement.h"
31
32namespace blink {
33
34bool RenderSVGInline::isChildAllowed(RenderObject* child, RenderStyle* style) const
35{
36    if (child->isText())
37        return SVGRenderSupport::isRenderableTextNode(child);
38
39    if (isSVGAElement(*node())) {
40        // Disallow direct descendant 'a'.
41        if (isSVGAElement(*child->node()))
42            return false;
43    }
44
45    if (!child->isSVGInline() && !child->isSVGInlineText())
46        return false;
47
48    return RenderInline::isChildAllowed(child, style);
49}
50
51RenderSVGInline::RenderSVGInline(Element* element)
52    : RenderInline(element)
53{
54    setAlwaysCreateLineBoxes();
55}
56
57InlineFlowBox* RenderSVGInline::createInlineFlowBox()
58{
59    InlineFlowBox* box = new SVGInlineFlowBox(*this);
60    box->setHasVirtualLogicalHeight();
61    return box;
62}
63
64FloatRect RenderSVGInline::objectBoundingBox() const
65{
66    if (const RenderObject* object = RenderSVGText::locateRenderSVGTextAncestor(this))
67        return object->objectBoundingBox();
68
69    return FloatRect();
70}
71
72FloatRect RenderSVGInline::strokeBoundingBox() const
73{
74    if (const RenderObject* object = RenderSVGText::locateRenderSVGTextAncestor(this))
75        return object->strokeBoundingBox();
76
77    return FloatRect();
78}
79
80FloatRect RenderSVGInline::paintInvalidationRectInLocalCoordinates() const
81{
82    if (const RenderObject* object = RenderSVGText::locateRenderSVGTextAncestor(this))
83        return object->paintInvalidationRectInLocalCoordinates();
84
85    return FloatRect();
86}
87
88LayoutRect RenderSVGInline::clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, const PaintInvalidationState* paintInvalidationState) const
89{
90    return SVGRenderSupport::clippedOverflowRectForPaintInvalidation(this, paintInvalidationContainer, paintInvalidationState);
91}
92
93void RenderSVGInline::computeFloatRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, FloatRect& paintInvalidationRect, const PaintInvalidationState* paintInvalidationState) const
94{
95    SVGRenderSupport::computeFloatRectForPaintInvalidation(this, paintInvalidationContainer, paintInvalidationRect, paintInvalidationState);
96}
97
98void RenderSVGInline::mapLocalToContainer(const RenderLayerModelObject* paintInvalidationContainer, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed, const PaintInvalidationState* paintInvalidationState) const
99{
100    SVGRenderSupport::mapLocalToContainer(this, paintInvalidationContainer, transformState, wasFixed, paintInvalidationState);
101}
102
103const RenderObject* RenderSVGInline::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
104{
105    return SVGRenderSupport::pushMappingToContainer(this, ancestorToStopAt, geometryMap);
106}
107
108void RenderSVGInline::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
109{
110    const RenderObject* object = RenderSVGText::locateRenderSVGTextAncestor(this);
111    if (!object)
112        return;
113
114    FloatRect textBoundingBox = object->strokeBoundingBox();
115    for (InlineFlowBox* box = firstLineBox(); box; box = box->nextLineBox())
116        quads.append(localToAbsoluteQuad(FloatRect(textBoundingBox.x() + box->x(), textBoundingBox.y() + box->y(), box->logicalWidth(), box->logicalHeight()), false, wasFixed));
117}
118
119void RenderSVGInline::willBeDestroyed()
120{
121    SVGResourcesCache::clientDestroyed(this);
122    RenderInline::willBeDestroyed();
123}
124
125void RenderSVGInline::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
126{
127    if (diff.needsFullLayout())
128        setNeedsBoundariesUpdate();
129
130    RenderInline::styleDidChange(diff, oldStyle);
131    SVGResourcesCache::clientStyleChanged(this, diff, style());
132}
133
134void RenderSVGInline::addChild(RenderObject* child, RenderObject* beforeChild)
135{
136    RenderInline::addChild(child, beforeChild);
137    SVGResourcesCache::clientWasAddedToTree(child, child->style());
138
139    if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this))
140        textRenderer->subtreeChildWasAdded(child);
141}
142
143void RenderSVGInline::removeChild(RenderObject* child)
144{
145    SVGResourcesCache::clientWillBeRemovedFromTree(child);
146
147    RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this);
148    if (!textRenderer) {
149        RenderInline::removeChild(child);
150        return;
151    }
152    Vector<SVGTextLayoutAttributes*, 2> affectedAttributes;
153    textRenderer->subtreeChildWillBeRemoved(child, affectedAttributes);
154    RenderInline::removeChild(child);
155    textRenderer->subtreeChildWasRemoved(affectedAttributes);
156}
157
158}
159