Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1404)

Unified Diff: Source/core/layout/svg/SVGTextChunkBuilder.cpp

Issue 1162653002: Drop SVGTextChunk::m_boxes (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Pass reference. Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/layout/svg/SVGTextChunkBuilder.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/layout/svg/SVGTextChunkBuilder.cpp
diff --git a/Source/core/layout/svg/SVGTextChunkBuilder.cpp b/Source/core/layout/svg/SVGTextChunkBuilder.cpp
index 2e1109d3d39d867567e803c65efda1a7f0993e55..84e2dc5f37c48b90447383654ce3962d281fb7c9 100644
--- a/Source/core/layout/svg/SVGTextChunkBuilder.cpp
+++ b/Source/core/layout/svg/SVGTextChunkBuilder.cpp
@@ -28,57 +28,12 @@
namespace blink {
-SVGTextChunkBuilder::SVGTextChunkBuilder()
-{
-}
-
-void SVGTextChunkBuilder::processTextChunks(const Vector<SVGInlineTextBox*>& lineLayoutBoxes)
-{
- if (lineLayoutBoxes.isEmpty())
- return;
-
- bool foundStart = false;
- unsigned lastChunkStartPosition = 0;
- unsigned boxPosition = 0;
- unsigned boxCount = lineLayoutBoxes.size();
- for (; boxPosition < boxCount; ++boxPosition) {
- SVGInlineTextBox* textBox = lineLayoutBoxes[boxPosition];
- if (!textBox->startsNewTextChunk())
- continue;
-
- if (!foundStart) {
- foundStart = true;
- } else {
- ASSERT(boxPosition > lastChunkStartPosition);
- handleTextChunk(lineLayoutBoxes, lastChunkStartPosition, boxPosition);
- }
- lastChunkStartPosition = boxPosition;
- }
-
- if (!foundStart)
- return;
-
- if (boxPosition - lastChunkStartPosition > 0)
- handleTextChunk(lineLayoutBoxes, lastChunkStartPosition, boxPosition);
-}
+namespace {
-SVGTextPathChunkBuilder::SVGTextPathChunkBuilder()
- : SVGTextChunkBuilder()
- , m_totalLength(0)
- , m_totalCharacters(0)
- , m_totalTextAnchorShift(0)
+SVGTextChunk createTextChunk(const SVGInlineTextBox& textBox)
{
-}
-
-static SVGTextChunk createTextChunk(const Vector<SVGInlineTextBox*>& lineLayoutBoxes, unsigned boxStart, unsigned boxCount)
-{
- SVGInlineTextBox* textBox = lineLayoutBoxes[boxStart];
- ASSERT(textBox);
-
- LayoutSVGInlineText& textLayoutObject = toLayoutSVGInlineText(textBox->layoutObject());
-
- const ComputedStyle& style = toLayoutSVGInlineText(textBox->layoutObject()).styleRef();
-
+ LayoutSVGInlineText& textLayoutObject = toLayoutSVGInlineText(textBox.layoutObject());
+ const ComputedStyle& style = textLayoutObject.styleRef();
const SVGComputedStyle& svgStyle = style.svgStyle();
// Build chunk style flags.
@@ -102,7 +57,7 @@ static SVGTextChunk createTextChunk(const Vector<SVGInlineTextBox*>& lineLayoutB
case TA_END:
chunkStyle |= SVGTextChunk::EndAnchor;
break;
- };
+ }
// Handle 'lengthAdjust' property.
float desiredTextLength = 0;
@@ -122,31 +77,122 @@ static SVGTextChunk createTextChunk(const Vector<SVGInlineTextBox*>& lineLayoutB
case SVGLengthAdjustSpacingAndGlyphs:
chunkStyle |= SVGTextChunk::LengthAdjustSpacingAndGlyphs;
break;
- };
+ }
+ }
+
+ return SVGTextChunk(chunkStyle, desiredTextLength);
+}
+
+class ChunkLengthAccumulator {
+public:
+ ChunkLengthAccumulator(bool isVertical)
+ : m_numCharacters(0)
+ , m_length(0)
+ , m_isVertical(isVertical)
+ {
+ }
+
+ typedef Vector<SVGInlineTextBox*>::const_iterator BoxListConstIterator;
+
+ void processRange(BoxListConstIterator boxStart, BoxListConstIterator boxEnd);
+ void reset()
+ {
+ m_numCharacters = 0;
+ m_length = 0;
+ }
+
+ float length() const { return m_length; }
+ unsigned numCharacters() const { return m_numCharacters; }
+
+private:
+ unsigned m_numCharacters;
+ float m_length;
+ const bool m_isVertical;
+};
+
+void ChunkLengthAccumulator::processRange(BoxListConstIterator boxStart, BoxListConstIterator boxEnd)
+{
+ SVGTextFragment* lastFragment = nullptr;
+ for (auto boxIter = boxStart; boxIter != boxEnd; ++boxIter) {
+ for (SVGTextFragment& fragment : (*boxIter)->textFragments()) {
+ m_numCharacters += fragment.length;
+
+ if (m_isVertical)
+ m_length += fragment.height;
+ else
+ m_length += fragment.width;
+
+ if (!lastFragment) {
+ lastFragment = &fragment;
+ continue;
+ }
+
+ // Respect gap between chunks.
+ if (m_isVertical)
+ m_length += fragment.y - (lastFragment->y + lastFragment->height);
+ else
+ m_length += fragment.x - (lastFragment->x + lastFragment->width);
+
+ lastFragment = &fragment;
+ }
+ }
+}
+
+}
+
+SVGTextChunkBuilder::SVGTextChunkBuilder()
+{
+}
+
+void SVGTextChunkBuilder::processTextChunks(const Vector<SVGInlineTextBox*>& lineLayoutBoxes)
+{
+ if (lineLayoutBoxes.isEmpty())
+ return;
+
+ bool foundStart = false;
+ auto boxIter = lineLayoutBoxes.begin();
+ auto endBox = lineLayoutBoxes.end();
+ auto chunkStartBox = boxIter;
+ for (; boxIter != endBox; ++boxIter) {
+ if (!(*boxIter)->startsNewTextChunk())
+ continue;
+
+ if (!foundStart) {
+ foundStart = true;
+ } else {
+ ASSERT(boxIter != chunkStartBox);
+ handleTextChunk(chunkStartBox, boxIter);
+ }
+ chunkStartBox = boxIter;
}
- SVGTextChunk chunk(chunkStyle, desiredTextLength);
+ if (!foundStart)
+ return;
- Vector<SVGInlineTextBox*>& boxes = chunk.boxes();
- for (unsigned i = boxStart; i < boxStart + boxCount; ++i)
- boxes.append(lineLayoutBoxes[i]);
+ if (boxIter != chunkStartBox)
+ handleTextChunk(chunkStartBox, boxIter);
+}
- return chunk;
+SVGTextPathChunkBuilder::SVGTextPathChunkBuilder()
+ : SVGTextChunkBuilder()
+ , m_totalLength(0)
+ , m_totalCharacters(0)
+ , m_totalTextAnchorShift(0)
+{
}
-void SVGTextPathChunkBuilder::handleTextChunk(const Vector<SVGInlineTextBox*>& boxes, unsigned boxStart, unsigned boxEnd)
+void SVGTextPathChunkBuilder::handleTextChunk(BoxListConstIterator boxStart, BoxListConstIterator boxEnd)
{
- SVGTextChunk chunk = createTextChunk(boxes, boxStart, boxEnd - boxStart);
+ SVGTextChunk chunk = createTextChunk(**boxStart);
- float length = 0;
- unsigned characters = 0;
- chunk.calculateLength(length, characters);
+ ChunkLengthAccumulator lengthAccumulator(chunk.isVerticalText());
+ lengthAccumulator.processRange(boxStart, boxEnd);
// Handle text-anchor as additional start offset for text paths.
- m_totalTextAnchorShift += chunk.calculateTextAnchorShift(length);
+ m_totalTextAnchorShift += chunk.calculateTextAnchorShift(lengthAccumulator.length());
- m_totalLength += length;
- m_totalCharacters += characters;
+ m_totalLength += lengthAccumulator.length();
+ m_totalCharacters += lengthAccumulator.numCharacters();
}
static void buildSpacingAndGlyphsTransform(bool isVerticalText, float scale, const SVGTextFragment& fragment, AffineTransform& spacingAndGlyphsTransform)
@@ -161,44 +207,47 @@ static void buildSpacingAndGlyphsTransform(bool isVerticalText, float scale, con
spacingAndGlyphsTransform.translate(-fragment.x, -fragment.y);
}
-void SVGTextChunkBuilder::handleTextChunk(const Vector<SVGInlineTextBox*>& lineBoxes, unsigned boxStart, unsigned boxEnd)
+void SVGTextChunkBuilder::handleTextChunk(BoxListConstIterator boxStart, BoxListConstIterator boxEnd)
{
- SVGTextChunk chunk = createTextChunk(lineBoxes, boxStart, boxEnd - boxStart);
+ SVGTextChunk chunk = createTextChunk(**boxStart);
bool processTextLength = chunk.hasDesiredTextLength();
bool processTextAnchor = chunk.hasTextAnchor();
if (!processTextAnchor && !processTextLength)
return;
- const Vector<SVGInlineTextBox*>& boxes = chunk.boxes();
- unsigned boxCount = boxes.size();
- if (!boxCount)
- return;
+ bool isVerticalText = chunk.isVerticalText();
// Calculate absolute length of whole text chunk (starting from text box 'start', spanning 'length' text boxes).
- float chunkLength = 0;
- unsigned chunkCharacters = 0;
- chunk.calculateLength(chunkLength, chunkCharacters);
+ ChunkLengthAccumulator lengthAccumulator(isVerticalText);
+ lengthAccumulator.processRange(boxStart, boxEnd);
- bool isVerticalText = chunk.isVerticalText();
if (processTextLength) {
+ float chunkLength = lengthAccumulator.length();
if (chunk.hasLengthAdjustSpacing()) {
- float textLengthShift = (chunk.desiredTextLength() - chunkLength) / chunkCharacters;
+ float textLengthShift = (chunk.desiredTextLength() - chunkLength) / lengthAccumulator.numCharacters();
unsigned atCharacter = 0;
- for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) {
- Vector<SVGTextFragment>& fragments = boxes[boxPosition]->textFragments();
+ for (auto boxIter = boxStart; boxIter != boxEnd; ++boxIter) {
+ Vector<SVGTextFragment>& fragments = (*boxIter)->textFragments();
if (fragments.isEmpty())
continue;
processTextLengthSpacingCorrection(isVerticalText, textLengthShift, fragments, atCharacter);
}
+
+ // Fragments have been adjusted, we have to recalculate the chunk
+ // length, to be able to apply the text-anchor shift.
+ if (processTextAnchor) {
+ lengthAccumulator.reset();
+ lengthAccumulator.processRange(boxStart, boxEnd);
+ }
} else {
ASSERT(chunk.hasLengthAdjustSpacingAndGlyphs());
float textLengthScale = chunk.desiredTextLength() / chunkLength;
AffineTransform spacingAndGlyphsTransform;
bool foundFirstFragment = false;
- for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) {
- SVGInlineTextBox* textBox = boxes[boxPosition];
+ for (auto boxIter = boxStart; boxIter != boxEnd; ++boxIter) {
+ SVGInlineTextBox* textBox = *boxIter;
Vector<SVGTextFragment>& fragments = textBox->textFragments();
if (fragments.isEmpty())
continue;
@@ -216,16 +265,9 @@ void SVGTextChunkBuilder::handleTextChunk(const Vector<SVGInlineTextBox*>& lineB
if (!processTextAnchor)
return;
- // If we previously applied a lengthAdjust="spacing" correction, we have to recalculate the chunk length, to be able to apply the text-anchor shift.
- if (processTextLength && chunk.hasLengthAdjustSpacing()) {
- chunkLength = 0;
- chunkCharacters = 0;
- chunk.calculateLength(chunkLength, chunkCharacters);
- }
-
- float textAnchorShift = chunk.calculateTextAnchorShift(chunkLength);
- for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) {
- Vector<SVGTextFragment>& fragments = boxes[boxPosition]->textFragments();
+ float textAnchorShift = chunk.calculateTextAnchorShift(lengthAccumulator.length());
+ for (auto boxIter = boxStart; boxIter != boxEnd; ++boxIter) {
+ Vector<SVGTextFragment>& fragments = (*boxIter)->textFragments();
if (fragments.isEmpty())
continue;
processTextAnchorCorrection(isVerticalText, textAnchorShift, fragments);
« no previous file with comments | « Source/core/layout/svg/SVGTextChunkBuilder.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698