blob: 43115a8dc9f39dc9d1fefb4d2299ed387f5d9f9e [file] [log] [blame]
/*
* Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
* Copyright (C) 2006 Apple Inc. All rights reserved.
* Copyright (C) Research In Motion Limited 2010. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "core/layout/svg/LayoutSVGInline.h"
#include "core/layout/LayoutView.h"
#include "core/layout/svg/LayoutSVGText.h"
#include "core/layout/svg/SVGLayoutSupport.h"
#include "core/layout/svg/SVGResourcesCache.h"
#include "core/layout/svg/line/SVGInlineFlowBox.h"
#include "core/svg/SVGAElement.h"
namespace blink {
bool LayoutSVGInline::isChildAllowed(LayoutObject* child,
const ComputedStyle& style) const {
if (child->isText())
return SVGLayoutSupport::isLayoutableTextNode(child);
if (isSVGAElement(*node())) {
// Disallow direct descendant 'a'.
if (isSVGAElement(*child->node()))
return false;
}
if (!child->isSVGInline() && !child->isSVGInlineText())
return false;
return LayoutInline::isChildAllowed(child, style);
}
LayoutSVGInline::LayoutSVGInline(Element* element) : LayoutInline(element) {
setAlwaysCreateLineBoxes();
}
InlineFlowBox* LayoutSVGInline::createInlineFlowBox() {
InlineFlowBox* box = new SVGInlineFlowBox(LineLayoutItem(this));
box->setHasVirtualLogicalHeight();
return box;
}
FloatRect LayoutSVGInline::objectBoundingBox() const {
if (const LayoutSVGText* textRoot =
LayoutSVGText::locateLayoutSVGTextAncestor(this))
return textRoot->objectBoundingBox();
return FloatRect();
}
FloatRect LayoutSVGInline::strokeBoundingBox() const {
if (const LayoutSVGText* textRoot =
LayoutSVGText::locateLayoutSVGTextAncestor(this))
return textRoot->strokeBoundingBox();
return FloatRect();
}
FloatRect LayoutSVGInline::paintInvalidationRectInLocalSVGCoordinates() const {
if (const LayoutSVGText* textRoot =
LayoutSVGText::locateLayoutSVGTextAncestor(this))
return textRoot->paintInvalidationRectInLocalSVGCoordinates();
return FloatRect();
}
LayoutRect LayoutSVGInline::absoluteClippedOverflowRect() const {
return SVGLayoutSupport::clippedOverflowRectForPaintInvalidation(*this,
*view());
}
void LayoutSVGInline::mapLocalToAncestor(const LayoutBoxModelObject* ancestor,
TransformState& transformState,
MapCoordinatesFlags flags) const {
SVGLayoutSupport::mapLocalToAncestor(this, ancestor, transformState, flags);
}
const LayoutObject* LayoutSVGInline::pushMappingToContainer(
const LayoutBoxModelObject* ancestorToStopAt,
LayoutGeometryMap& geometryMap) const {
return SVGLayoutSupport::pushMappingToContainer(this, ancestorToStopAt,
geometryMap);
}
void LayoutSVGInline::absoluteQuads(Vector<FloatQuad>& quads) const {
const LayoutSVGText* textRoot =
LayoutSVGText::locateLayoutSVGTextAncestor(this);
if (!textRoot)
return;
FloatRect textBoundingBox = textRoot->strokeBoundingBox();
for (InlineFlowBox* box = firstLineBox(); box; box = box->nextLineBox())
quads.append(
localToAbsoluteQuad(FloatRect(textBoundingBox.x() + box->x().toFloat(),
textBoundingBox.y() + box->y().toFloat(),
box->logicalWidth().toFloat(),
box->logicalHeight().toFloat()),
false));
}
void LayoutSVGInline::willBeDestroyed() {
SVGResourcesCache::clientDestroyed(this);
LayoutInline::willBeDestroyed();
}
void LayoutSVGInline::styleDidChange(StyleDifference diff,
const ComputedStyle* oldStyle) {
if (diff.needsFullLayout())
setNeedsBoundariesUpdate();
LayoutInline::styleDidChange(diff, oldStyle);
SVGResourcesCache::clientStyleChanged(this, diff, styleRef());
}
void LayoutSVGInline::addChild(LayoutObject* child, LayoutObject* beforeChild) {
LayoutInline::addChild(child, beforeChild);
SVGResourcesCache::clientWasAddedToTree(child, child->styleRef());
if (LayoutSVGText* textLayoutObject =
LayoutSVGText::locateLayoutSVGTextAncestor(this))
textLayoutObject->subtreeChildWasAdded();
}
void LayoutSVGInline::removeChild(LayoutObject* child) {
SVGResourcesCache::clientWillBeRemovedFromTree(child);
if (LayoutSVGText* textLayoutObject =
LayoutSVGText::locateLayoutSVGTextAncestor(this))
textLayoutObject->subtreeChildWillBeRemoved();
LayoutInline::removeChild(child);
}
void LayoutSVGInline::invalidateTreeIfNeeded(
const PaintInvalidationState& paintInvalidationState) {
// TODO(wangxianzhu): Verify if the inherited
// LayoutBoxModelObject::invalidateTreeIfNeeded() is applicable here.
// If yes, remove this overriding method.
LayoutObject::invalidateTreeIfNeeded(paintInvalidationState);
}
} // namespace blink