diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp')
-rw-r--r-- | Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp | 241 |
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) |