Index: Source/core/layout/svg/SVGTextQuery.cpp |
diff --git a/Source/core/layout/svg/SVGTextQuery.cpp b/Source/core/layout/svg/SVGTextQuery.cpp |
index 64cf0d361060b24451b5d067f1c0c94e322bd45f..490237a0386c0c4defe10d7ee1c2c110497d6082 100644 |
--- a/Source/core/layout/svg/SVGTextQuery.cpp |
+++ b/Source/core/layout/svg/SVGTextQuery.cpp |
@@ -24,16 +24,18 @@ |
#include "core/layout/LayoutInline.h" |
#include "core/layout/line/InlineFlowBox.h" |
#include "core/layout/svg/LayoutSVGInlineText.h" |
+#include "core/layout/svg/SVGTextFragment.h" |
#include "core/layout/svg/SVGTextMetrics.h" |
#include "core/layout/svg/line/SVGInlineTextBox.h" |
#include "platform/FloatConversion.h" |
#include "wtf/MathExtras.h" |
+#include "wtf/Vector.h" |
namespace blink { |
// Base structure for callback user data |
-struct SVGTextQuery::Data { |
- Data() |
+struct QueryData { |
+ QueryData() |
: isVerticalText(false) |
, processedCharacters(0) |
, textLayoutObject(0) |
@@ -77,12 +79,7 @@ static inline InlineFlowBox* flowBoxForLayoutObject(LayoutObject* layoutObject) |
return 0; |
} |
-SVGTextQuery::SVGTextQuery(LayoutObject* layoutObject) |
-{ |
- collectTextBoxesInFlowBox(flowBoxForLayoutObject(layoutObject)); |
-} |
- |
-void SVGTextQuery::collectTextBoxesInFlowBox(InlineFlowBox* flowBox) |
+static void collectTextBoxesInFlowBox(InlineFlowBox* flowBox, Vector<SVGInlineTextBox*>& textBoxes) |
{ |
if (!flowBox) |
return; |
@@ -93,23 +90,28 @@ void SVGTextQuery::collectTextBoxesInFlowBox(InlineFlowBox* flowBox) |
if (!child->layoutObject().node()) |
continue; |
- collectTextBoxesInFlowBox(toInlineFlowBox(child)); |
+ collectTextBoxesInFlowBox(toInlineFlowBox(child), textBoxes); |
continue; |
} |
if (child->isSVGInlineTextBox()) |
- m_textBoxes.append(toSVGInlineTextBox(child)); |
+ textBoxes.append(toSVGInlineTextBox(child)); |
} |
} |
-bool SVGTextQuery::executeQuery(Data* queryData, ProcessTextFragmentCallback fragmentCallback) const |
+typedef bool ProcessTextFragmentCallback(QueryData*, const SVGTextFragment&); |
+ |
+static bool executeQuery(LayoutObject* queryRoot, QueryData* queryData, ProcessTextFragmentCallback fragmentCallback) |
{ |
+ Vector<SVGInlineTextBox*> textBoxes; |
+ collectTextBoxesInFlowBox(flowBoxForLayoutObject(queryRoot), textBoxes); |
+ |
unsigned processedCharacters = 0; |
- unsigned textBoxCount = m_textBoxes.size(); |
+ unsigned textBoxCount = textBoxes.size(); |
// Loop over all text boxes |
for (unsigned textBoxPosition = 0; textBoxPosition < textBoxCount; ++textBoxPosition) { |
- queryData->textBox = m_textBoxes.at(textBoxPosition); |
+ queryData->textBox = textBoxes[textBoxPosition]; |
queryData->textLayoutObject = &toLayoutSVGInlineText(queryData->textBox->layoutObject()); |
ASSERT(queryData->textLayoutObject->style()); |
@@ -120,7 +122,7 @@ bool SVGTextQuery::executeQuery(Data* queryData, ProcessTextFragmentCallback fra |
unsigned fragmentCount = fragments.size(); |
for (unsigned i = 0; i < fragmentCount; ++i) { |
const SVGTextFragment& fragment = fragments.at(i); |
- if ((this->*fragmentCallback)(queryData, fragment)) |
+ if (fragmentCallback(queryData, fragment)) |
return true; |
processedCharacters += fragment.length; |
@@ -128,27 +130,10 @@ bool SVGTextQuery::executeQuery(Data* queryData, ProcessTextFragmentCallback fra |
queryData->processedCharacters = processedCharacters; |
} |
- |
return false; |
} |
-bool SVGTextQuery::mapStartEndPositionsIntoFragmentCoordinates(Data* queryData, const SVGTextFragment& fragment, int& startPosition, int& endPosition) const |
-{ |
- // Make <startPosition, endPosition> offsets relative to the current text box. |
- startPosition -= queryData->processedCharacters; |
- endPosition -= queryData->processedCharacters; |
- |
- // Reuse the same logic used for text selection & painting, to map our |
- // query start/length into start/endPositions of the current text fragment. |
- if (!queryData->textBox->mapStartEndPositionsIntoFragmentCoordinates(fragment, startPosition, endPosition)) |
- return false; |
- |
- modifyStartEndPositionsRespectingLigatures(queryData, fragment, startPosition, endPosition); |
- ASSERT(startPosition < endPosition); |
- return true; |
-} |
- |
-void SVGTextQuery::modifyStartEndPositionsRespectingLigatures(Data* queryData, const SVGTextFragment& fragment, int& startPosition, int& endPosition) const |
+static void modifyStartEndPositionsRespectingLigatures(const QueryData* queryData, const SVGTextFragment& fragment, int& startPosition, int& endPosition) |
{ |
const Vector<SVGTextMetrics>& textMetricsValues = queryData->textLayoutObject->layoutAttributes()->textMetricsValues(); |
@@ -180,8 +165,24 @@ void SVGTextQuery::modifyStartEndPositionsRespectingLigatures(Data* queryData, c |
endPosition = fragmentOffset; |
} |
+static bool mapStartEndPositionsIntoFragmentCoordinates(const QueryData* queryData, const SVGTextFragment& fragment, int& startPosition, int& endPosition) |
+{ |
+ // Make <startPosition, endPosition> offsets relative to the current text box. |
+ startPosition -= queryData->processedCharacters; |
+ endPosition -= queryData->processedCharacters; |
+ |
+ // Reuse the same logic used for text selection & painting, to map our |
+ // query start/length into start/endPositions of the current text fragment. |
+ if (!queryData->textBox->mapStartEndPositionsIntoFragmentCoordinates(fragment, startPosition, endPosition)) |
+ return false; |
+ |
+ modifyStartEndPositionsRespectingLigatures(queryData, fragment, startPosition, endPosition); |
+ ASSERT(startPosition < endPosition); |
+ return true; |
+} |
+ |
// numberOfCharacters() implementation |
-bool SVGTextQuery::numberOfCharactersCallback(Data*, const SVGTextFragment&) const |
+static bool numberOfCharactersCallback(QueryData*, const SVGTextFragment&) |
{ |
// no-op |
return false; |
@@ -189,13 +190,13 @@ bool SVGTextQuery::numberOfCharactersCallback(Data*, const SVGTextFragment&) con |
unsigned SVGTextQuery::numberOfCharacters() const |
{ |
- Data data; |
- executeQuery(&data, &SVGTextQuery::numberOfCharactersCallback); |
+ QueryData data; |
+ executeQuery(m_queryRootLayoutObject, &data, numberOfCharactersCallback); |
return data.processedCharacters; |
} |
// textLength() implementation |
-struct TextLengthData : SVGTextQuery::Data { |
+struct TextLengthData : QueryData { |
TextLengthData() |
: textLength(0) |
{ |
@@ -204,7 +205,7 @@ struct TextLengthData : SVGTextQuery::Data { |
float textLength; |
}; |
-bool SVGTextQuery::textLengthCallback(Data* queryData, const SVGTextFragment& fragment) const |
+static bool textLengthCallback(QueryData* queryData, const SVGTextFragment& fragment) |
{ |
TextLengthData* data = static_cast<TextLengthData*>(queryData); |
data->textLength += queryData->isVerticalText ? fragment.height : fragment.width; |
@@ -214,12 +215,12 @@ bool SVGTextQuery::textLengthCallback(Data* queryData, const SVGTextFragment& fr |
float SVGTextQuery::textLength() const |
{ |
TextLengthData data; |
- executeQuery(&data, &SVGTextQuery::textLengthCallback); |
+ executeQuery(m_queryRootLayoutObject, &data, textLengthCallback); |
return data.textLength; |
} |
// subStringLength() implementation |
-struct SubStringLengthData : SVGTextQuery::Data { |
+struct SubStringLengthData : QueryData { |
SubStringLengthData(unsigned queryStartPosition, unsigned queryLength) |
: startPosition(queryStartPosition) |
, length(queryLength) |
@@ -233,7 +234,7 @@ struct SubStringLengthData : SVGTextQuery::Data { |
float subStringLength; |
}; |
-bool SVGTextQuery::subStringLengthCallback(Data* queryData, const SVGTextFragment& fragment) const |
+static bool subStringLengthCallback(QueryData* queryData, const SVGTextFragment& fragment) |
{ |
SubStringLengthData* data = static_cast<SubStringLengthData*>(queryData); |
@@ -250,12 +251,12 @@ bool SVGTextQuery::subStringLengthCallback(Data* queryData, const SVGTextFragmen |
float SVGTextQuery::subStringLength(unsigned startPosition, unsigned length) const |
{ |
SubStringLengthData data(startPosition, length); |
- executeQuery(&data, &SVGTextQuery::subStringLengthCallback); |
+ executeQuery(m_queryRootLayoutObject, &data, subStringLengthCallback); |
return data.subStringLength; |
} |
// startPositionOfCharacter() implementation |
-struct StartPositionOfCharacterData : SVGTextQuery::Data { |
+struct StartPositionOfCharacterData : QueryData { |
StartPositionOfCharacterData(unsigned queryPosition) |
: position(queryPosition) |
{ |
@@ -265,7 +266,7 @@ struct StartPositionOfCharacterData : SVGTextQuery::Data { |
FloatPoint startPosition; |
}; |
-static FloatPoint calculateGlyphPositionWithoutTransform(const SVGTextQuery::Data* queryData, const SVGTextFragment& fragment, int offsetInFragment) |
+static FloatPoint calculateGlyphPositionWithoutTransform(const QueryData* queryData, const SVGTextFragment& fragment, int offsetInFragment) |
{ |
float glyphOffsetInDirection = 0; |
if (offsetInFragment) { |
@@ -290,7 +291,7 @@ static FloatPoint calculateGlyphPositionWithoutTransform(const SVGTextQuery::Dat |
return glyphPosition; |
} |
-static FloatPoint calculateGlyphPosition(const SVGTextQuery::Data* queryData, const SVGTextFragment& fragment, int offsetInFragment) |
+static FloatPoint calculateGlyphPosition(const QueryData* queryData, const SVGTextFragment& fragment, int offsetInFragment) |
{ |
FloatPoint glyphPosition = calculateGlyphPositionWithoutTransform(queryData, fragment, offsetInFragment); |
AffineTransform fragmentTransform; |
@@ -301,7 +302,7 @@ static FloatPoint calculateGlyphPosition(const SVGTextQuery::Data* queryData, co |
return glyphPosition; |
} |
-bool SVGTextQuery::startPositionOfCharacterCallback(Data* queryData, const SVGTextFragment& fragment) const |
+static bool startPositionOfCharacterCallback(QueryData* queryData, const SVGTextFragment& fragment) |
{ |
StartPositionOfCharacterData* data = static_cast<StartPositionOfCharacterData*>(queryData); |
@@ -317,12 +318,12 @@ bool SVGTextQuery::startPositionOfCharacterCallback(Data* queryData, const SVGTe |
FloatPoint SVGTextQuery::startPositionOfCharacter(unsigned position) const |
{ |
StartPositionOfCharacterData data(position); |
- executeQuery(&data, &SVGTextQuery::startPositionOfCharacterCallback); |
+ executeQuery(m_queryRootLayoutObject, &data, startPositionOfCharacterCallback); |
return data.startPosition; |
} |
// endPositionOfCharacter() implementation |
-struct EndPositionOfCharacterData : SVGTextQuery::Data { |
+struct EndPositionOfCharacterData : QueryData { |
EndPositionOfCharacterData(unsigned queryPosition) |
: position(queryPosition) |
{ |
@@ -332,7 +333,7 @@ struct EndPositionOfCharacterData : SVGTextQuery::Data { |
FloatPoint endPosition; |
}; |
-bool SVGTextQuery::endPositionOfCharacterCallback(Data* queryData, const SVGTextFragment& fragment) const |
+static bool endPositionOfCharacterCallback(QueryData* queryData, const SVGTextFragment& fragment) |
{ |
EndPositionOfCharacterData* data = static_cast<EndPositionOfCharacterData*>(queryData); |
@@ -351,12 +352,12 @@ bool SVGTextQuery::endPositionOfCharacterCallback(Data* queryData, const SVGText |
FloatPoint SVGTextQuery::endPositionOfCharacter(unsigned position) const |
{ |
EndPositionOfCharacterData data(position); |
- executeQuery(&data, &SVGTextQuery::endPositionOfCharacterCallback); |
+ executeQuery(m_queryRootLayoutObject, &data, endPositionOfCharacterCallback); |
return data.endPosition; |
} |
// rotationOfCharacter() implementation |
-struct RotationOfCharacterData : SVGTextQuery::Data { |
+struct RotationOfCharacterData : QueryData { |
RotationOfCharacterData(unsigned queryPosition) |
: position(queryPosition) |
, rotation(0) |
@@ -367,7 +368,7 @@ struct RotationOfCharacterData : SVGTextQuery::Data { |
float rotation; |
}; |
-bool SVGTextQuery::rotationOfCharacterCallback(Data* queryData, const SVGTextFragment& fragment) const |
+static bool rotationOfCharacterCallback(QueryData* queryData, const SVGTextFragment& fragment) |
{ |
RotationOfCharacterData* data = static_cast<RotationOfCharacterData*>(queryData); |
@@ -391,12 +392,12 @@ bool SVGTextQuery::rotationOfCharacterCallback(Data* queryData, const SVGTextFra |
float SVGTextQuery::rotationOfCharacter(unsigned position) const |
{ |
RotationOfCharacterData data(position); |
- executeQuery(&data, &SVGTextQuery::rotationOfCharacterCallback); |
+ executeQuery(m_queryRootLayoutObject, &data, rotationOfCharacterCallback); |
return data.rotation; |
} |
// extentOfCharacter() implementation |
-struct ExtentOfCharacterData : SVGTextQuery::Data { |
+struct ExtentOfCharacterData : QueryData { |
ExtentOfCharacterData(unsigned queryPosition) |
: position(queryPosition) |
{ |
@@ -421,7 +422,7 @@ const SVGTextMetrics& findMetricsForCharacter(const Vector<SVGTextMetrics>& text |
return textMetricsValues[textMetricsOffset - 1]; |
} |
-static inline void calculateGlyphBoundaries(SVGTextQuery::Data* queryData, const SVGTextFragment& fragment, int startPosition, FloatRect& extent) |
+static inline void calculateGlyphBoundaries(const QueryData* queryData, const SVGTextFragment& fragment, int startPosition, FloatRect& extent) |
{ |
float scalingFactor = queryData->textLayoutObject->scalingFactor(); |
ASSERT(scalingFactor); |
@@ -467,7 +468,7 @@ static inline FloatRect calculateFragmentBoundaries(const LayoutSVGInlineText& t |
return fragmentTransform.mapRect(fragmentRect); |
} |
-bool SVGTextQuery::extentOfCharacterCallback(Data* queryData, const SVGTextFragment& fragment) const |
+static bool extentOfCharacterCallback(QueryData* queryData, const SVGTextFragment& fragment) |
{ |
ExtentOfCharacterData* data = static_cast<ExtentOfCharacterData*>(queryData); |
@@ -483,12 +484,12 @@ bool SVGTextQuery::extentOfCharacterCallback(Data* queryData, const SVGTextFragm |
FloatRect SVGTextQuery::extentOfCharacter(unsigned position) const |
{ |
ExtentOfCharacterData data(position); |
- executeQuery(&data, &SVGTextQuery::extentOfCharacterCallback); |
+ executeQuery(m_queryRootLayoutObject, &data, extentOfCharacterCallback); |
return data.extent; |
} |
// characterNumberAtPosition() implementation |
-struct CharacterNumberAtPositionData : SVGTextQuery::Data { |
+struct CharacterNumberAtPositionData : QueryData { |
CharacterNumberAtPositionData(const FloatPoint& queryPosition) |
: position(queryPosition) |
{ |
@@ -497,7 +498,7 @@ struct CharacterNumberAtPositionData : SVGTextQuery::Data { |
FloatPoint position; |
}; |
-bool SVGTextQuery::characterNumberAtPositionCallback(Data* queryData, const SVGTextFragment& fragment) const |
+static bool characterNumberAtPositionCallback(QueryData* queryData, const SVGTextFragment& fragment) |
{ |
CharacterNumberAtPositionData* data = static_cast<CharacterNumberAtPositionData*>(queryData); |
@@ -530,7 +531,7 @@ bool SVGTextQuery::characterNumberAtPositionCallback(Data* queryData, const SVGT |
int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const |
{ |
CharacterNumberAtPositionData data(position); |
- if (!executeQuery(&data, &SVGTextQuery::characterNumberAtPositionCallback)) |
+ if (!executeQuery(m_queryRootLayoutObject, &data, characterNumberAtPositionCallback)) |
return -1; |
return data.processedCharacters; |