RenderSVGInlineText.cpp [plain text]
#include "config.h"
#if ENABLE(SVG)
#include "RenderSVGInlineText.h"
#include "FloatConversion.h"
#include "RenderBlock.h"
#include "RenderSVGRoot.h"
#include "SVGInlineTextBox.h"
#include "SVGRootInlineBox.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::absoluteRects(Vector<IntRect>& rects, int, int, bool)
{
rects.append(computeAbsoluteRectForRange(0, textLength()));
}
IntRect RenderSVGInlineText::selectionRect(bool)
{
ASSERT(!needsLayout());
IntRect rect;
if (selectionState() == SelectionNone)
return rect;
if (isChildOfHiddenContainer(this))
return rect;
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 rect;
return computeAbsoluteRectForRange(startPos, endPos);
}
IntRect RenderSVGInlineText::computeAbsoluteRectForRange(int startPos, int endPos)
{
IntRect rect;
RenderBlock* cb = containingBlock();
if (!cb || !cb->container())
return rect;
RenderSVGRoot* root = findSVGRootObject(parent());
if (!root)
return rect;
for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
rect.unite(box->selectionRect(0, 0, startPos, endPos));
int x, y;
cb->container()->absolutePosition(x, y);
AffineTransform htmlParentCtm = root->RenderContainer::absoluteTransform();
FloatRect fixedRect(narrowPrecisionToFloat(rect.x() + x - xPos() - htmlParentCtm.e()), narrowPrecisionToFloat(rect.y() + y - yPos() - htmlParentCtm.f()), rect.width(), rect.height());
return enclosingIntRect(absoluteTransform().mapRect(fixedRect));
}
InlineTextBox* RenderSVGInlineText::createInlineTextBox()
{
return new (renderArena()) SVGInlineTextBox(this);
}
IntRect RenderSVGInlineText::caretRect(int offset, EAffinity affinity, int* extraWidthToEndOfLine)
{
return IntRect();
}
VisiblePosition RenderSVGInlineText::positionForCoordinates(int x, int y)
{
SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(firstTextBox());
if (!textBox || textLength() == 0)
return VisiblePosition(element(), 0, DOWNSTREAM);
SVGRootInlineBox* rootBox = textBox->svgRootInlineBox();
RenderObject* object = rootBox ? rootBox->object() : 0;
if (!object)
return VisiblePosition(element(), 0, DOWNSTREAM);
int offset = 0;
for (SVGInlineTextBox* box = textBox; box; box = static_cast<SVGInlineTextBox*>(box->nextTextBox())) {
if (box->svgCharacterHitsPosition(x + object->xPos(), y + object->yPos(), offset)) {
if (!box->m_reversed) {
if (offset <= (int) box->end() + 1)
break;
} else {
if (offset > (int) box->start())
break;
}
}
}
return VisiblePosition(element(), offset, DOWNSTREAM);
}
}
#endif // ENABLE(SVG)