| Index: Source/core/rendering/svg/SVGTextMetricsBuilder.cpp
|
| diff --git a/Source/core/rendering/svg/SVGTextMetricsBuilder.cpp b/Source/core/rendering/svg/SVGTextMetricsBuilder.cpp
|
| index 5bac22f285e59b086e211f7a27742a375222fe96..fa70571456701d52e89f2c895e47aba83c4597aa 100644
|
| --- a/Source/core/rendering/svg/SVGTextMetricsBuilder.cpp
|
| +++ b/Source/core/rendering/svg/SVGTextMetricsBuilder.cpp
|
| @@ -25,8 +25,12 @@
|
| #include "core/rendering/svg/RenderSVGText.h"
|
| #include "core/rendering/svg/SVGTextMetrics.h"
|
| #include "platform/fonts/WidthIterator.h"
|
| +#include "platform/text/BidiCharacterRun.h"
|
| +#include "platform/text/BidiResolver.h"
|
| +#include "platform/text/TextDirection.h"
|
| #include "platform/text/TextPath.h"
|
| #include "platform/text/TextRun.h"
|
| +#include "platform/text/TextRunIterator.h"
|
| #include "wtf/Vector.h"
|
|
|
| namespace WebCore {
|
| @@ -34,6 +38,7 @@ namespace WebCore {
|
| class SVGTextMetricsCalculator {
|
| public:
|
| SVGTextMetricsCalculator(RenderSVGInlineText*);
|
| + ~SVGTextMetricsCalculator();
|
|
|
| SVGTextMetrics computeMetricsForCharacter(unsigned textPosition);
|
| unsigned textLength() const { return static_cast<unsigned>(m_run.charactersLength()); }
|
| @@ -48,13 +53,17 @@ public:
|
| }
|
|
|
| private:
|
| + void setupBidiRuns();
|
| SVGTextMetrics computeMetricsForCharacterSimple(unsigned textPosition);
|
| SVGTextMetrics computeMetricsForCharacterComplex(unsigned textPosition);
|
|
|
| RenderSVGInlineText* m_text;
|
| + BidiCharacterRun* m_bidiRun;
|
| TextRun m_run;
|
| + BidiResolver<TextRunIterator, BidiCharacterRun> m_bidiResolver;
|
| bool m_isComplexText;
|
| float m_totalWidth;
|
| + TextDirection m_textDirection;
|
|
|
| // Simple text only.
|
| OwnPtr<WidthIterator> m_simpleWidthIterator;
|
| @@ -62,6 +71,7 @@ private:
|
|
|
| SVGTextMetricsCalculator::SVGTextMetricsCalculator(RenderSVGInlineText* text)
|
| : m_text(text)
|
| + , m_bidiRun(0)
|
| , m_run(SVGTextMetrics::constructTextRun(text, 0, text->textLength()))
|
| , m_isComplexText(false)
|
| , m_totalWidth(0)
|
| @@ -73,6 +83,32 @@ SVGTextMetricsCalculator::SVGTextMetricsCalculator(RenderSVGInlineText* text)
|
|
|
| if (!m_isComplexText)
|
| m_simpleWidthIterator = adoptPtr(new WidthIterator(&scaledFont, m_run));
|
| + else
|
| + setupBidiRuns();
|
| +}
|
| +
|
| +SVGTextMetricsCalculator::~SVGTextMetricsCalculator()
|
| +{
|
| + if (m_bidiRun)
|
| + m_bidiResolver.runs().deleteRuns();
|
| +}
|
| +
|
| +void SVGTextMetricsCalculator::setupBidiRuns()
|
| +{
|
| + RenderStyle* style = m_text->style();
|
| + m_textDirection = style->direction();
|
| + if (isOverride(style->unicodeBidi()))
|
| + return;
|
| +
|
| + BidiStatus status(LTR, false);
|
| + status.last = status.lastStrong = WTF::Unicode::OtherNeutral;
|
| + m_bidiResolver.setStatus(status);
|
| + m_bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&m_run, 0));
|
| + const bool hardLineBreak = false;
|
| + const bool reorderRuns = false;
|
| + m_bidiResolver.createBidiRunsForLine(TextRunIterator(&m_run, m_run.length()), NoVisualOverride, hardLineBreak, reorderRuns);
|
| + BidiRunList<BidiCharacterRun>& bidiRuns = m_bidiResolver.runs();
|
| + m_bidiRun = bidiRuns.firstRun();
|
| }
|
|
|
| SVGTextMetrics SVGTextMetricsCalculator::computeMetricsForCharacterSimple(unsigned textPosition)
|
| @@ -92,10 +128,12 @@ SVGTextMetrics SVGTextMetricsCalculator::computeMetricsForCharacterSimple(unsign
|
| SVGTextMetrics SVGTextMetricsCalculator::computeMetricsForCharacterComplex(unsigned textPosition)
|
| {
|
| unsigned metricsLength = characterStartsSurrogatePair(textPosition) ? 2 : 1;
|
| - SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(m_text, textPosition, metricsLength);
|
| + SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(m_text, textPosition, metricsLength, m_textDirection);
|
| ASSERT(metrics.length() == metricsLength);
|
|
|
| - SVGTextMetrics complexStartToCurrentMetrics = SVGTextMetrics::measureCharacterRange(m_text, 0, textPosition + metricsLength);
|
| + unsigned startPosition = m_bidiRun ? m_bidiRun->start() : 0;
|
| + ASSERT(startPosition <= textPosition);
|
| + SVGTextMetrics complexStartToCurrentMetrics = SVGTextMetrics::measureCharacterRange(m_text, startPosition, textPosition - startPosition + metricsLength, m_textDirection);
|
| // Frequent case for Arabic text: when measuring a single character the arabic isolated form is taken
|
| // when rendering the glyph "in context" (with it's surrounding characters) it changes due to shaping.
|
| // So whenever currentWidth != currentMetrics.width(), we are processing a text run whose length is
|
| @@ -110,6 +148,17 @@ SVGTextMetrics SVGTextMetricsCalculator::computeMetricsForCharacterComplex(unsig
|
|
|
| SVGTextMetrics SVGTextMetricsCalculator::computeMetricsForCharacter(unsigned textPosition)
|
| {
|
| + if (m_bidiRun) {
|
| + if (textPosition >= static_cast<unsigned>(m_bidiRun->stop())) {
|
| + m_bidiRun = m_bidiRun->next();
|
| + // New BiDi run means new reference position for measurements, so reset |m_totalWidth|.
|
| + m_totalWidth = 0;
|
| + }
|
| + ASSERT(m_bidiRun);
|
| + ASSERT(static_cast<int>(textPosition) < m_bidiRun->stop());
|
| + m_textDirection = m_bidiRun->direction();
|
| + }
|
| +
|
| if (m_isComplexText)
|
| return computeMetricsForCharacterComplex(textPosition);
|
|
|
|
|