summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp')
-rw-r--r--Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp241
1 files changed, 41 insertions, 200 deletions
diff --git a/Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp b/Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp
index 26ab67e25..68b2d4875 100644
--- a/Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp
+++ b/Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -18,8 +19,6 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "SVGTextChunkBuilder.h"
#include "SVGElement.h"
@@ -32,229 +31,71 @@ SVGTextChunkBuilder::SVGTextChunkBuilder()
{
}
-void SVGTextChunkBuilder::transformationForTextBox(SVGInlineTextBox* textBox, AffineTransform& transform) const
+unsigned SVGTextChunkBuilder::totalCharacters() const
{
- DEFINE_STATIC_LOCAL(const AffineTransform, s_identityTransform, ());
- if (!m_textBoxTransformations.contains(textBox)) {
- transform = s_identityTransform;
- return;
- }
-
- transform = m_textBoxTransformations.get(textBox);
+ unsigned characters = 0;
+ for (const auto& chunk : m_textChunks)
+ characters += chunk.totalCharacters();
+ return characters;
}
-void SVGTextChunkBuilder::buildTextChunks(Vector<SVGInlineTextBox*>& lineLayoutBoxes)
+float SVGTextChunkBuilder::totalLength() const
{
- 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) {
- lastChunkStartPosition = boxPosition;
- foundStart = true;
- } else {
- ASSERT_WITH_SECURITY_IMPLICATION(boxPosition > lastChunkStartPosition);
- addTextChunk(lineLayoutBoxes, lastChunkStartPosition, boxPosition - lastChunkStartPosition);
- lastChunkStartPosition = boxPosition;
- }
- }
-
- if (!foundStart)
- return;
-
- if (boxPosition - lastChunkStartPosition > 0)
- addTextChunk(lineLayoutBoxes, lastChunkStartPosition, boxPosition - lastChunkStartPosition);
+ float length = 0;
+ for (const auto& chunk : m_textChunks)
+ length += chunk.totalLength();
+ return length;
}
-void SVGTextChunkBuilder::layoutTextChunks(Vector<SVGInlineTextBox*>& lineLayoutBoxes)
+float SVGTextChunkBuilder::totalAnchorShift() const
{
- buildTextChunks(lineLayoutBoxes);
- if (m_textChunks.isEmpty())
- return;
-
- unsigned chunkCount = m_textChunks.size();
- for (unsigned i = 0; i < chunkCount; ++i)
- processTextChunk(m_textChunks[i]);
-
- m_textChunks.clear();
+ float anchorShift = 0;
+ for (const auto& chunk : m_textChunks)
+ anchorShift += chunk.totalAnchorShift();
+ return anchorShift;
}
-void SVGTextChunkBuilder::addTextChunk(Vector<SVGInlineTextBox*>& lineLayoutBoxes, unsigned boxStart, unsigned boxCount)
+AffineTransform SVGTextChunkBuilder::transformationForTextBox(SVGInlineTextBox* textBox) const
{
- SVGInlineTextBox* textBox = lineLayoutBoxes[boxStart];
- ASSERT(textBox);
-
- const RenderStyle& style = textBox->renderer().style();
-
- const SVGRenderStyle& svgStyle = style.svgStyle();
-
- // Build chunk style flags.
- unsigned chunkStyle = SVGTextChunk::DefaultStyle;
-
- // Handle 'direction' property.
- if (!style.isLeftToRightDirection())
- chunkStyle |= SVGTextChunk::RightToLeftText;
-
- // Handle 'writing-mode' property.
- if (svgStyle.isVerticalWritingMode())
- chunkStyle |= SVGTextChunk::VerticalText;
-
- // Handle 'text-anchor' property.
- switch (svgStyle.textAnchor()) {
- case TA_START:
- break;
- case TA_MIDDLE:
- chunkStyle |= SVGTextChunk::MiddleAnchor;
- break;
- case TA_END:
- chunkStyle |= SVGTextChunk::EndAnchor;
- break;
- };
-
- // Handle 'lengthAdjust' property.
- float desiredTextLength = 0;
- if (SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromRenderer(textBox->renderer().parent())) {
- SVGLengthContext lengthContext(textContentElement);
- desiredTextLength = textContentElement->specifiedTextLength().value(lengthContext);
-
- switch (textContentElement->lengthAdjust()) {
- case SVGLengthAdjustUnknown:
- break;
- case SVGLengthAdjustSpacing:
- chunkStyle |= SVGTextChunk::LengthAdjustSpacing;
- break;
- case SVGLengthAdjustSpacingAndGlyphs:
- chunkStyle |= SVGTextChunk::LengthAdjustSpacingAndGlyphs;
- break;
- };
- }
-
- SVGTextChunk chunk(chunkStyle, desiredTextLength);
-
- Vector<SVGInlineTextBox*>& boxes = chunk.boxes();
- for (unsigned i = boxStart; i < boxStart + boxCount; ++i)
- boxes.append(lineLayoutBoxes[i]);
-
- m_textChunks.append(chunk);
+ auto it = m_textBoxTransformations.find(textBox);
+ return it == m_textBoxTransformations.end() ? AffineTransform() : it->value;
}
-void SVGTextChunkBuilder::processTextChunk(const SVGTextChunk& chunk)
+void SVGTextChunkBuilder::buildTextChunks(const Vector<SVGInlineTextBox*>& lineLayoutBoxes)
{
- 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;
-
- // 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);
-
- bool isVerticalText = chunk.isVerticalText();
- if (processTextLength) {
- if (chunk.hasLengthAdjustSpacing()) {
- float textLengthShift = (chunk.desiredTextLength() - chunkLength) / chunkCharacters;
- unsigned atCharacter = 0;
- for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) {
- Vector<SVGTextFragment>& fragments = boxes[boxPosition]->textFragments();
- if (fragments.isEmpty())
- continue;
- processTextLengthSpacingCorrection(isVerticalText, textLengthShift, fragments, atCharacter);
- }
- } 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];
- Vector<SVGTextFragment>& fragments = textBox->textFragments();
- if (fragments.isEmpty())
- continue;
-
- if (!foundFirstFragment) {
- foundFirstFragment = true;
- buildSpacingAndGlyphsTransform(isVerticalText, textLengthScale, fragments.first(), spacingAndGlyphsTransform);
- }
-
- m_textBoxTransformations.set(textBox, spacingAndGlyphsTransform);
- }
- }
- }
-
- if (!processTextAnchor)
+ if (lineLayoutBoxes.isEmpty())
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);
- }
+ unsigned limit = lineLayoutBoxes.size();
+ unsigned first = limit;
- float textAnchorShift = chunk.calculateTextAnchorShift(chunkLength);
- for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) {
- Vector<SVGTextFragment>& fragments = boxes[boxPosition]->textFragments();
- if (fragments.isEmpty())
+ for (unsigned i = 0; i < limit; ++i) {
+ if (!lineLayoutBoxes[i]->startsNewTextChunk())
continue;
- processTextAnchorCorrection(isVerticalText, textAnchorShift, fragments);
- }
-}
-
-void SVGTextChunkBuilder::processTextLengthSpacingCorrection(bool isVerticalText, float textLengthShift, Vector<SVGTextFragment>& fragments, unsigned& atCharacter)
-{
- unsigned fragmentCount = fragments.size();
- for (unsigned i = 0; i < fragmentCount; ++i) {
- SVGTextFragment& fragment = fragments[i];
- if (isVerticalText)
- fragment.y += textLengthShift * atCharacter;
- else
- fragment.x += textLengthShift * atCharacter;
-
- atCharacter += fragment.length;
+ if (first == limit)
+ first = i;
+ else {
+ ASSERT_WITH_SECURITY_IMPLICATION(first != i);
+ m_textChunks.append(SVGTextChunk(lineLayoutBoxes, first, i));
+ first = i;
+ }
}
-}
-void SVGTextChunkBuilder::processTextAnchorCorrection(bool isVerticalText, float textAnchorShift, Vector<SVGTextFragment>& fragments)
-{
- unsigned fragmentCount = fragments.size();
- for (unsigned i = 0; i < fragmentCount; ++i) {
- SVGTextFragment& fragment = fragments[i];
-
- if (isVerticalText)
- fragment.y += textAnchorShift;
- else
- fragment.x += textAnchorShift;
- }
+ if (first != limit)
+ m_textChunks.append(SVGTextChunk(lineLayoutBoxes, first, limit));
}
-void SVGTextChunkBuilder::buildSpacingAndGlyphsTransform(bool isVerticalText, float scale, const SVGTextFragment& fragment, AffineTransform& spacingAndGlyphsTransform)
+void SVGTextChunkBuilder::layoutTextChunks(const Vector<SVGInlineTextBox*>& lineLayoutBoxes)
{
- spacingAndGlyphsTransform.translate(fragment.x, fragment.y);
+ buildTextChunks(lineLayoutBoxes);
+ if (m_textChunks.isEmpty())
+ return;
- if (isVerticalText)
- spacingAndGlyphsTransform.scaleNonUniform(1, scale);
- else
- spacingAndGlyphsTransform.scaleNonUniform(scale, 1);
+ for (const auto& chunk : m_textChunks)
+ chunk.layout(m_textBoxTransformations);
- spacingAndGlyphsTransform.translate(-fragment.x, -fragment.y);
+ m_textChunks.clear();
}
}
-
-#endif // ENABLE(SVG)