📄 svgtextcontentelement.cpp
字号:
void setQueryInputParameters(long startPosition, long length, FloatPoint referencePoint) { m_queryStartPosition = startPosition; m_queryLength = length; m_queryPointInput = referencePoint; } long longResult() const { return m_queryLongResult; } float floatResult() const { return m_queryFloatResult; } FloatPoint pointResult() const { return m_queryPointResult; } FloatRect rectResult() const { return m_queryRectResult; } bool stopProcessing() const { return m_stopProcessing; }private: const SVGTextContentElement* m_reference; QueryMode m_mode; long m_queryStartPosition; long m_queryLength; FloatPoint m_queryPointInput; long m_queryLongResult; float m_queryFloatResult; FloatPoint m_queryPointResult; FloatRect m_queryRectResult; bool m_stopProcessing; long m_atCharacter;};static Vector<SVGInlineTextBox*> findInlineTextBoxInTextChunks(const SVGTextContentElement* element, const Vector<SVGTextChunk>& chunks){ Vector<SVGTextChunk>::const_iterator it = chunks.begin(); const Vector<SVGTextChunk>::const_iterator end = chunks.end(); Vector<SVGInlineTextBox*> boxes; for (; it != end; ++it) { Vector<SVGInlineBoxCharacterRange>::const_iterator boxIt = it->boxes.begin(); const Vector<SVGInlineBoxCharacterRange>::const_iterator boxEnd = it->boxes.end(); for (; boxIt != boxEnd; ++boxIt) { SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(boxIt->box); Node* textElement = textBox->textRenderer()->parent()->node(); ASSERT(textElement); if (textElement == element || textElement->parent() == element) boxes.append(textBox); } } return boxes;}static inline SVGRootInlineBox* rootInlineBoxForTextContentElement(const SVGTextContentElement* element){ RenderObject* object = element->renderer(); if (!object || !object->isSVGText() || object->isText()) return 0; RenderSVGText* svgText = static_cast<RenderSVGText*>(object); // Find root inline box SVGRootInlineBox* rootBox = static_cast<SVGRootInlineBox*>(svgText->firstRootBox()); if (!rootBox) { // Layout is not sync yet! element->document()->updateLayoutIgnorePendingStylesheets(); rootBox = static_cast<SVGRootInlineBox*>(svgText->firstRootBox()); } ASSERT(rootBox); return rootBox;}static inline SVGInlineTextBoxQueryWalker executeTextQuery(const SVGTextContentElement* element, SVGInlineTextBoxQueryWalker::QueryMode mode, long startPosition = 0, long length = 0, FloatPoint referencePoint = FloatPoint()){ SVGRootInlineBox* rootBox = rootInlineBoxForTextContentElement(element); if (!rootBox) return SVGInlineTextBoxQueryWalker(0, mode); // Find all inline text box associated with our renderer Vector<SVGInlineTextBox*> textBoxes = findInlineTextBoxInTextChunks(element, rootBox->svgTextChunks()); // Walk text chunks to find chunks associated with our inline text box SVGInlineTextBoxQueryWalker walkerCallback(element, mode); walkerCallback.setQueryInputParameters(startPosition, length, referencePoint); SVGTextChunkWalker<SVGInlineTextBoxQueryWalker> walker(&walkerCallback, &SVGInlineTextBoxQueryWalker::chunkPortionCallback); Vector<SVGInlineTextBox*>::iterator it = textBoxes.begin(); Vector<SVGInlineTextBox*>::iterator end = textBoxes.end(); for (; it != end; ++it) { rootBox->walkTextChunks(&walker, *it); if (walkerCallback.stopProcessing()) break; } return walkerCallback;}long SVGTextContentElement::getNumberOfChars() const{ document()->updateLayoutIgnorePendingStylesheets(); return executeTextQuery(this, SVGInlineTextBoxQueryWalker::NumberOfCharacters).longResult();}float SVGTextContentElement::getComputedTextLength() const{ document()->updateLayoutIgnorePendingStylesheets(); return executeTextQuery(this, SVGInlineTextBoxQueryWalker::TextLength).floatResult();}float SVGTextContentElement::getSubStringLength(long charnum, long nchars, ExceptionCode& ec) const{ document()->updateLayoutIgnorePendingStylesheets(); long numberOfChars = getNumberOfChars(); if (charnum < 0 || nchars < 0 || charnum >= numberOfChars) { ec = INDEX_SIZE_ERR; return 0.0f; } return executeTextQuery(this, SVGInlineTextBoxQueryWalker::SubStringLength, charnum, nchars).floatResult();}FloatPoint SVGTextContentElement::getStartPositionOfChar(long charnum, ExceptionCode& ec) const{ document()->updateLayoutIgnorePendingStylesheets(); if (charnum < 0 || charnum > getNumberOfChars()) { ec = INDEX_SIZE_ERR; return FloatPoint(); } return executeTextQuery(this, SVGInlineTextBoxQueryWalker::StartPosition, charnum).pointResult();}FloatPoint SVGTextContentElement::getEndPositionOfChar(long charnum, ExceptionCode& ec) const{ document()->updateLayoutIgnorePendingStylesheets(); if (charnum < 0 || charnum > getNumberOfChars()) { ec = INDEX_SIZE_ERR; return FloatPoint(); } return executeTextQuery(this, SVGInlineTextBoxQueryWalker::EndPosition, charnum).pointResult();}FloatRect SVGTextContentElement::getExtentOfChar(long charnum, ExceptionCode& ec) const{ document()->updateLayoutIgnorePendingStylesheets(); if (charnum < 0 || charnum > getNumberOfChars()) { ec = INDEX_SIZE_ERR; return FloatRect(); } return executeTextQuery(this, SVGInlineTextBoxQueryWalker::Extent, charnum).rectResult();}float SVGTextContentElement::getRotationOfChar(long charnum, ExceptionCode& ec) const{ document()->updateLayoutIgnorePendingStylesheets(); if (charnum < 0 || charnum > getNumberOfChars()) { ec = INDEX_SIZE_ERR; return 0.0f; } return executeTextQuery(this, SVGInlineTextBoxQueryWalker::Rotation, charnum).floatResult();}long SVGTextContentElement::getCharNumAtPosition(const FloatPoint& point) const{ document()->updateLayoutIgnorePendingStylesheets(); return executeTextQuery(this, SVGInlineTextBoxQueryWalker::CharacterNumberAtPosition, 0.0f, 0.0f, point).longResult();}void SVGTextContentElement::selectSubString(long charnum, long nchars, ExceptionCode& ec) const{ long numberOfChars = getNumberOfChars(); if (charnum < 0 || nchars < 0 || charnum >= numberOfChars) { ec = INDEX_SIZE_ERR; return; } if (nchars > numberOfChars - charnum) nchars = numberOfChars - charnum; ASSERT(document()); ASSERT(document()->frame()); SelectionController* controller = document()->frame()->selection(); if (!controller) return; // Find selection start VisiblePosition start(const_cast<SVGTextContentElement*>(this), 0, SEL_DEFAULT_AFFINITY); for (long i = 0; i < charnum; ++i) start = start.next(); // Find selection end VisiblePosition end(start); for (long i = 0; i < nchars; ++i) end = end.next(); controller->setSelection(VisibleSelection(start, end));}void SVGTextContentElement::parseMappedAttribute(MappedAttribute* attr){ if (attr->name() == SVGNames::lengthAdjustAttr) { if (attr->value() == "spacing") setLengthAdjustBaseValue(LENGTHADJUST_SPACING); else if (attr->value() == "spacingAndGlyphs") setLengthAdjustBaseValue(LENGTHADJUST_SPACINGANDGLYPHS); } else if (attr->name() == SVGNames::textLengthAttr) { setTextLengthBaseValue(SVGLength(LengthModeOther, attr->value())); if (textLengthBaseValue().value(this) < 0.0) document()->accessSVGExtensions()->reportError("A negative value for text attribute <textLength> is not allowed"); } else { if (SVGTests::parseMappedAttribute(attr)) return; if (SVGLangSpace::parseMappedAttribute(attr)) { if (attr->name().matches(XMLNames::spaceAttr)) { DEFINE_STATIC_LOCAL(const AtomicString, preserveString, ("preserve")); if (attr->value() == preserveString) addCSSProperty(attr, CSSPropertyWhiteSpace, CSSValuePre); else addCSSProperty(attr, CSSPropertyWhiteSpace, CSSValueNowrap); } return; } if (SVGExternalResourcesRequired::parseMappedAttribute(attr)) return; SVGStyledElement::parseMappedAttribute(attr); }}bool SVGTextContentElement::isKnownAttribute(const QualifiedName& attrName){ return (attrName.matches(SVGNames::lengthAdjustAttr) || attrName.matches(SVGNames::textLengthAttr) || SVGTests::isKnownAttribute(attrName) || SVGLangSpace::isKnownAttribute(attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName) || SVGStyledElement::isKnownAttribute(attrName));}}#endif // ENABLE(SVG)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -