📄 svgtextcontentelement.cpp
字号:
/* Copyright (C) 2004, 2005, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> 2004, 2005, 2006, 2007, 2008 Rob Buis <buis@kde.org> 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 "config.h"#if ENABLE(SVG)#include "SVGTextContentElement.h"#include "CSSPropertyNames.h"#include "CSSValueKeywords.h"#include "ExceptionCode.h"#include "FloatPoint.h"#include "FloatRect.h"#include "Frame.h"#include "Position.h"#include "RenderSVGText.h"#include "SelectionController.h"#include "SVGCharacterLayoutInfo.h"#include "SVGRootInlineBox.h"#include "SVGLength.h"#include "SVGInlineTextBox.h"#include "SVGNames.h"#include "XMLNames.h"#include <wtf/StdLibExtras.h>namespace WebCore {char SVGTextContentElementIdentifier[] = "SVGTextContentElement";SVGTextContentElement::SVGTextContentElement(const QualifiedName& tagName, Document* doc) : SVGStyledElement(tagName, doc) , SVGTests() , SVGLangSpace() , SVGExternalResourcesRequired() , m_textLength(this, SVGNames::textLengthAttr, LengthModeOther) , m_lengthAdjust(this, SVGNames::lengthAdjustAttr, LENGTHADJUST_SPACING){}SVGTextContentElement::~SVGTextContentElement(){}static inline float cumulativeCharacterRangeLength(const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end, SVGInlineTextBox* textBox, int startOffset, long startPosition, long length, bool isVerticalText, long& atCharacter){ if (!length) return 0.0f; float textLength = 0.0f; RenderStyle* style = textBox->textRenderer()->style(); bool usesFullRange = (startPosition == -1 && length == -1); for (Vector<SVGChar>::iterator it = start; it != end; ++it) { if (usesFullRange || (atCharacter >= startPosition && atCharacter <= startPosition + length)) { unsigned int newOffset = textBox->start() + (it - start) + startOffset; // Take RTL text into account and pick right glyph width/height. if (textBox->direction() == RTL) newOffset = textBox->start() + textBox->end() - newOffset; // FIXME: does this handle multichar glyphs ok? not sure int charsConsumed = 0; String glyphName; if (isVerticalText) textLength += textBox->calculateGlyphHeight(style, newOffset, 0); else textLength += textBox->calculateGlyphWidth(style, newOffset, 0, charsConsumed, glyphName); } if (!usesFullRange) { if (atCharacter == startPosition + length - 1) break; atCharacter++; } } return textLength;}// Helper class for querying certain glyph informationstruct SVGInlineTextBoxQueryWalker { typedef enum { NumberOfCharacters, TextLength, SubStringLength, StartPosition, EndPosition, Extent, Rotation, CharacterNumberAtPosition } QueryMode; SVGInlineTextBoxQueryWalker(const SVGTextContentElement* reference, QueryMode mode) : m_reference(reference) , m_mode(mode) , m_queryStartPosition(0) , m_queryLength(0) , m_queryPointInput() , m_queryLongResult(0) , m_queryFloatResult(0.0f) , m_queryPointResult() , m_queryRectResult() , m_stopProcessing(true) , m_atCharacter(0) { } void chunkPortionCallback(SVGInlineTextBox* textBox, int startOffset, const TransformationMatrix&, const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end) { RenderStyle* style = textBox->textRenderer()->style(); bool isVerticalText = style->svgStyle()->writingMode() == WM_TBRL || style->svgStyle()->writingMode() == WM_TB; switch (m_mode) { case NumberOfCharacters: { m_queryLongResult += (end - start); m_stopProcessing = false; return; } case TextLength: { float textLength = cumulativeCharacterRangeLength(start, end, textBox, startOffset, -1, -1, isVerticalText, m_atCharacter); if (isVerticalText) m_queryFloatResult += textLength; else m_queryFloatResult += textLength; m_stopProcessing = false; return; } case SubStringLength: { long startPosition = m_queryStartPosition; long length = m_queryLength; float textLength = cumulativeCharacterRangeLength(start, end, textBox, startOffset, startPosition, length, isVerticalText, m_atCharacter); if (isVerticalText) m_queryFloatResult += textLength; else m_queryFloatResult += textLength; if (m_atCharacter == startPosition + length) m_stopProcessing = true; else m_stopProcessing = false; return; } case StartPosition: { for (Vector<SVGChar>::iterator it = start; it != end; ++it) { if (m_atCharacter == m_queryStartPosition) { m_queryPointResult = FloatPoint(it->x, it->y); m_stopProcessing = true; return; } m_atCharacter++; } m_stopProcessing = false; return; } case EndPosition: { for (Vector<SVGChar>::iterator it = start; it != end; ++it) { if (m_atCharacter == m_queryStartPosition) { unsigned int newOffset = textBox->start() + (it - start) + startOffset; // Take RTL text into account and pick right glyph width/height. if (textBox->direction() == RTL) newOffset = textBox->start() + textBox->end() - newOffset; int charsConsumed; String glyphName; // calculateGlyph{Height,Width} will consume at least one character. This is the number of characters available // to them beyond that first one. int extraCharactersAvailable = end - it - 1; if (isVerticalText) m_queryPointResult.move(it->x, it->y + textBox->calculateGlyphHeight(style, newOffset, extraCharactersAvailable)); else m_queryPointResult.move(it->x + textBox->calculateGlyphWidth(style, newOffset, extraCharactersAvailable, charsConsumed, glyphName), it->y); m_stopProcessing = true; return; } m_atCharacter++; } m_stopProcessing = false; return; } case Extent: { for (Vector<SVGChar>::iterator it = start; it != end; ++it) { if (m_atCharacter == m_queryStartPosition) { unsigned int newOffset = textBox->start() + (it - start) + startOffset; m_queryRectResult = textBox->calculateGlyphBoundaries(style, newOffset, *it); m_stopProcessing = true; return; } m_atCharacter++; } m_stopProcessing = false; return; } case Rotation: { for (Vector<SVGChar>::iterator it = start; it != end; ++it) { if (m_atCharacter == m_queryStartPosition) { m_queryFloatResult = it->angle; m_stopProcessing = true; return; } m_atCharacter++; } m_stopProcessing = false; return; } case CharacterNumberAtPosition: { int offset = 0; SVGChar* charAtPos = textBox->closestCharacterToPosition(m_queryPointInput.x(), m_queryPointInput.y(), offset); offset += m_atCharacter; if (charAtPos && offset > m_queryLongResult) m_queryLongResult = offset; m_atCharacter += end - start; m_stopProcessing = false; return; } default: ASSERT_NOT_REACHED(); m_stopProcessing = true; return; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -