RenderSVGInlineText.cpp [plain text]
#include "config.h"
#if ENABLE(SVG)
#include "RenderSVGInlineText.h"
#include "FloatConversion.h"
#include "FloatQuad.h"
#include "RenderBlock.h"
#include "RenderSVGRoot.h"
#include "SVGInlineTextBox.h"
#include "SVGRootInlineBox.h"
#include "VisiblePosition.h"
namespace WebCore {
static inline bool isChildOfHiddenContainer(RenderObject* start)
{
while (start) {
if (start->isSVGHiddenContainer())
return true;
start = start->parent();
}
return false;
}
RenderSVGInlineText::RenderSVGInlineText(Node* n, PassRefPtr<StringImpl> str)
: RenderText(n, str)
{
}
void RenderSVGInlineText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderObject::styleDidChange(diff, oldStyle);
if (RefPtr<StringImpl> textToTransform = originalText())
setText(textToTransform.release(), true);
}
void RenderSVGInlineText::absoluteRects(Vector<IntRect>& rects, int, int)
{
rects.append(computeRepaintRectForRange(0, 0, textLength()));
}
void RenderSVGInlineText::absoluteQuads(Vector<FloatQuad>& quads)
{
quads.append(computeRepaintQuadForRange(0, 0, textLength()));
}
IntRect RenderSVGInlineText::selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool )
{
ASSERT(!needsLayout());
if (selectionState() == SelectionNone)
return IntRect();
if (isChildOfHiddenContainer(this))
return IntRect();
int startPos, endPos;
if (selectionState() == SelectionInside) {
startPos = 0;
endPos = textLength();
} else {
selectionStartEnd(startPos, endPos);
if (selectionState() == SelectionStart)
endPos = textLength();
else if (selectionState() == SelectionEnd)
startPos = 0;
}
if (startPos == endPos)
return IntRect();
return computeRepaintRectForRange(repaintContainer, startPos, endPos);
}
IntRect RenderSVGInlineText::computeRepaintRectForRange(RenderBoxModelObject* repaintContainer, int startPos, int endPos)
{
FloatQuad repaintQuad = computeRepaintQuadForRange(repaintContainer, startPos, endPos);
return enclosingIntRect(repaintQuad.boundingBox());
}
FloatQuad RenderSVGInlineText::computeRepaintQuadForRange(RenderBoxModelObject* repaintContainer, int startPos, int endPos)
{
RenderBlock* cb = containingBlock();
if (!cb || !cb->container())
return FloatQuad();
RenderSVGRoot* root = findSVGRootObject(parent());
if (!root)
return FloatQuad();
IntRect rect;
for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
rect.unite(box->selectionRect(0, 0, startPos, endPos));
return localToContainerQuad(FloatQuad(rect), repaintContainer);
}
InlineTextBox* RenderSVGInlineText::createTextBox()
{
InlineTextBox* box = new (renderArena()) SVGInlineTextBox(this);
box->setHasVirtualHeight();
return box;
}
IntRect RenderSVGInlineText::localCaretRect(InlineBox*, int, int*)
{
return IntRect();
}
VisiblePosition RenderSVGInlineText::positionForPoint(const IntPoint& point)
{
SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(firstTextBox());
if (!textBox || textLength() == 0)
return createVisiblePosition(0, DOWNSTREAM);
SVGRootInlineBox* rootBox = textBox->svgRootInlineBox();
RenderBlock* object = rootBox ? rootBox->block() : 0;
if (!object)
return createVisiblePosition(0, DOWNSTREAM);
int closestOffsetInBox = 0;
for (SVGInlineTextBox* box = textBox; box; box = static_cast<SVGInlineTextBox*>(box->nextTextBox())) {
if (box->svgCharacterHitsPosition(point.x() + object->x(), point.y() + object->y(), closestOffsetInBox)) {
if (box->direction() == LTR) {
if (closestOffsetInBox <= (int) box->end() + 1)
break;
} else {
if (closestOffsetInBox > (int) box->start())
break;
}
}
}
return createVisiblePosition(closestOffsetInBox, DOWNSTREAM);
}
void RenderSVGInlineText::destroy()
{
if (!documentBeingDestroyed()) {
setNeedsLayoutAndPrefWidthsRecalc();
repaint();
}
RenderText::destroy();
}
}
#endif // ENABLE(SVG)