| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved. | 2 * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved. |
| 3 * | 3 * |
| 4 * This library is free software; you can redistribute it and/or | 4 * This library is free software; you can redistribute it and/or |
| 5 * modify it under the terms of the GNU Library General Public | 5 * modify it under the terms of the GNU Library General Public |
| 6 * License as published by the Free Software Foundation; either | 6 * License as published by the Free Software Foundation; either |
| 7 * version 2 of the License, or (at your option) any later version. | 7 * version 2 of the License, or (at your option) any later version. |
| 8 * | 8 * |
| 9 * This library is distributed in the hope that it will be useful, | 9 * This library is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 12 * Library General Public License for more details. | 12 * Library General Public License for more details. |
| 13 * | 13 * |
| 14 * You should have received a copy of the GNU Library General Public License | 14 * You should have received a copy of the GNU Library General Public License |
| 15 * along with this library; see the file COPYING.LIB. If not, write to | 15 * along with this library; see the file COPYING.LIB. If not, write to |
| 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| 17 * Boston, MA 02110-1301, USA. | 17 * Boston, MA 02110-1301, USA. |
| 18 */ | 18 */ |
| 19 | 19 |
| 20 #include "config.h" | 20 #include "config.h" |
| 21 | 21 |
| 22 #include "core/rendering/svg/SVGTextMetricsBuilder.h" | 22 #include "core/rendering/svg/SVGTextMetricsBuilder.h" |
| 23 | 23 |
| 24 #include "core/rendering/svg/RenderSVGInlineText.h" | 24 #include "core/rendering/svg/RenderSVGInlineText.h" |
| 25 #include "core/rendering/svg/RenderSVGText.h" | 25 #include "core/rendering/svg/RenderSVGText.h" |
| 26 #include "core/rendering/svg/SVGTextMetrics.h" | 26 #include "core/rendering/svg/SVGTextMetrics.h" |
| 27 #include "platform/fonts/WidthIterator.h" | 27 #include "platform/fonts/WidthIterator.h" |
| 28 #include "platform/text/BidiCharacterRun.h" |
| 29 #include "platform/text/BidiResolver.h" |
| 30 #include "platform/text/TextDirection.h" |
| 28 #include "platform/text/TextPath.h" | 31 #include "platform/text/TextPath.h" |
| 29 #include "platform/text/TextRun.h" | 32 #include "platform/text/TextRun.h" |
| 33 #include "platform/text/TextRunIterator.h" |
| 30 #include "wtf/Vector.h" | 34 #include "wtf/Vector.h" |
| 31 | 35 |
| 32 namespace WebCore { | 36 namespace WebCore { |
| 33 | 37 |
| 34 class SVGTextMetricsCalculator { | 38 class SVGTextMetricsCalculator { |
| 35 public: | 39 public: |
| 36 SVGTextMetricsCalculator(RenderSVGInlineText*); | 40 SVGTextMetricsCalculator(RenderSVGInlineText*); |
| 41 ~SVGTextMetricsCalculator(); |
| 37 | 42 |
| 38 SVGTextMetrics computeMetricsForCharacter(unsigned textPosition); | 43 SVGTextMetrics computeMetricsForCharacter(unsigned textPosition); |
| 39 unsigned textLength() const { return static_cast<unsigned>(m_run.charactersL
ength()); } | 44 unsigned textLength() const { return static_cast<unsigned>(m_run.charactersL
ength()); } |
| 40 | 45 |
| 41 bool characterStartsSurrogatePair(unsigned textPosition) const | 46 bool characterStartsSurrogatePair(unsigned textPosition) const |
| 42 { | 47 { |
| 43 return U16_IS_LEAD(m_run[textPosition]) && textPosition + 1 < textLength
() && U16_IS_TRAIL(m_run[textPosition + 1]); | 48 return U16_IS_LEAD(m_run[textPosition]) && textPosition + 1 < textLength
() && U16_IS_TRAIL(m_run[textPosition + 1]); |
| 44 } | 49 } |
| 45 bool characterIsWhiteSpace(unsigned textPosition) const | 50 bool characterIsWhiteSpace(unsigned textPosition) const |
| 46 { | 51 { |
| 47 return m_run[textPosition] == ' '; | 52 return m_run[textPosition] == ' '; |
| 48 } | 53 } |
| 49 | 54 |
| 50 private: | 55 private: |
| 56 void setupBidiRuns(); |
| 51 SVGTextMetrics computeMetricsForCharacterSimple(unsigned textPosition); | 57 SVGTextMetrics computeMetricsForCharacterSimple(unsigned textPosition); |
| 52 SVGTextMetrics computeMetricsForCharacterComplex(unsigned textPosition); | 58 SVGTextMetrics computeMetricsForCharacterComplex(unsigned textPosition); |
| 53 | 59 |
| 54 RenderSVGInlineText* m_text; | 60 RenderSVGInlineText* m_text; |
| 61 BidiCharacterRun* m_bidiRun; |
| 55 TextRun m_run; | 62 TextRun m_run; |
| 63 BidiResolver<TextRunIterator, BidiCharacterRun> m_bidiResolver; |
| 56 bool m_isComplexText; | 64 bool m_isComplexText; |
| 57 float m_totalWidth; | 65 float m_totalWidth; |
| 66 TextDirection m_textDirection; |
| 58 | 67 |
| 59 // Simple text only. | 68 // Simple text only. |
| 60 OwnPtr<WidthIterator> m_simpleWidthIterator; | 69 OwnPtr<WidthIterator> m_simpleWidthIterator; |
| 61 }; | 70 }; |
| 62 | 71 |
| 63 SVGTextMetricsCalculator::SVGTextMetricsCalculator(RenderSVGInlineText* text) | 72 SVGTextMetricsCalculator::SVGTextMetricsCalculator(RenderSVGInlineText* text) |
| 64 : m_text(text) | 73 : m_text(text) |
| 74 , m_bidiRun(0) |
| 65 , m_run(SVGTextMetrics::constructTextRun(text, 0, text->textLength())) | 75 , m_run(SVGTextMetrics::constructTextRun(text, 0, text->textLength())) |
| 66 , m_isComplexText(false) | 76 , m_isComplexText(false) |
| 67 , m_totalWidth(0) | 77 , m_totalWidth(0) |
| 68 { | 78 { |
| 69 const Font& scaledFont = text->scaledFont(); | 79 const Font& scaledFont = text->scaledFont(); |
| 70 CodePath codePath = scaledFont.codePath(m_run); | 80 CodePath codePath = scaledFont.codePath(m_run); |
| 71 m_isComplexText = codePath == ComplexPath; | 81 m_isComplexText = codePath == ComplexPath; |
| 72 m_run.setCharacterScanForCodePath(!m_isComplexText); | 82 m_run.setCharacterScanForCodePath(!m_isComplexText); |
| 73 | 83 |
| 74 if (!m_isComplexText) | 84 if (!m_isComplexText) |
| 75 m_simpleWidthIterator = adoptPtr(new WidthIterator(&scaledFont, m_run)); | 85 m_simpleWidthIterator = adoptPtr(new WidthIterator(&scaledFont, m_run)); |
| 86 else |
| 87 setupBidiRuns(); |
| 88 } |
| 89 |
| 90 SVGTextMetricsCalculator::~SVGTextMetricsCalculator() |
| 91 { |
| 92 if (m_bidiRun) |
| 93 m_bidiResolver.runs().deleteRuns(); |
| 94 } |
| 95 |
| 96 void SVGTextMetricsCalculator::setupBidiRuns() |
| 97 { |
| 98 RenderStyle* style = m_text->style(); |
| 99 m_textDirection = style->direction(); |
| 100 if (isOverride(style->unicodeBidi())) |
| 101 return; |
| 102 |
| 103 BidiStatus status(LTR, false); |
| 104 status.last = status.lastStrong = WTF::Unicode::OtherNeutral; |
| 105 m_bidiResolver.setStatus(status); |
| 106 m_bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&m_run, 0))
; |
| 107 const bool hardLineBreak = false; |
| 108 const bool reorderRuns = false; |
| 109 m_bidiResolver.createBidiRunsForLine(TextRunIterator(&m_run, m_run.length())
, NoVisualOverride, hardLineBreak, reorderRuns); |
| 110 BidiRunList<BidiCharacterRun>& bidiRuns = m_bidiResolver.runs(); |
| 111 m_bidiRun = bidiRuns.firstRun(); |
| 76 } | 112 } |
| 77 | 113 |
| 78 SVGTextMetrics SVGTextMetricsCalculator::computeMetricsForCharacterSimple(unsign
ed textPosition) | 114 SVGTextMetrics SVGTextMetricsCalculator::computeMetricsForCharacterSimple(unsign
ed textPosition) |
| 79 { | 115 { |
| 80 GlyphBuffer glyphBuffer; | 116 GlyphBuffer glyphBuffer; |
| 81 unsigned metricsLength = m_simpleWidthIterator->advance(textPosition + 1, &g
lyphBuffer); | 117 unsigned metricsLength = m_simpleWidthIterator->advance(textPosition + 1, &g
lyphBuffer); |
| 82 if (!metricsLength) | 118 if (!metricsLength) |
| 83 return SVGTextMetrics(); | 119 return SVGTextMetrics(); |
| 84 | 120 |
| 85 float currentWidth = m_simpleWidthIterator->runWidthSoFar() - m_totalWidth; | 121 float currentWidth = m_simpleWidthIterator->runWidthSoFar() - m_totalWidth; |
| 86 m_totalWidth = m_simpleWidthIterator->runWidthSoFar(); | 122 m_totalWidth = m_simpleWidthIterator->runWidthSoFar(); |
| 87 | 123 |
| 88 Glyph glyphId = glyphBuffer.glyphAt(0); | 124 Glyph glyphId = glyphBuffer.glyphAt(0); |
| 89 return SVGTextMetrics(m_text, textPosition, metricsLength, currentWidth, gly
phId); | 125 return SVGTextMetrics(m_text, textPosition, metricsLength, currentWidth, gly
phId); |
| 90 } | 126 } |
| 91 | 127 |
| 92 SVGTextMetrics SVGTextMetricsCalculator::computeMetricsForCharacterComplex(unsig
ned textPosition) | 128 SVGTextMetrics SVGTextMetricsCalculator::computeMetricsForCharacterComplex(unsig
ned textPosition) |
| 93 { | 129 { |
| 94 unsigned metricsLength = characterStartsSurrogatePair(textPosition) ? 2 : 1; | 130 unsigned metricsLength = characterStartsSurrogatePair(textPosition) ? 2 : 1; |
| 95 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(m_text, textP
osition, metricsLength); | 131 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(m_text, textP
osition, metricsLength, m_textDirection); |
| 96 ASSERT(metrics.length() == metricsLength); | 132 ASSERT(metrics.length() == metricsLength); |
| 97 | 133 |
| 98 SVGTextMetrics complexStartToCurrentMetrics = SVGTextMetrics::measureCharact
erRange(m_text, 0, textPosition + metricsLength); | 134 unsigned startPosition = m_bidiRun ? m_bidiRun->start() : 0; |
| 135 ASSERT(startPosition <= textPosition); |
| 136 SVGTextMetrics complexStartToCurrentMetrics = SVGTextMetrics::measureCharact
erRange(m_text, startPosition, textPosition - startPosition + metricsLength, m_t
extDirection); |
| 99 // Frequent case for Arabic text: when measuring a single character the arab
ic isolated form is taken | 137 // Frequent case for Arabic text: when measuring a single character the arab
ic isolated form is taken |
| 100 // when rendering the glyph "in context" (with it's surrounding characters)
it changes due to shaping. | 138 // when rendering the glyph "in context" (with it's surrounding characters)
it changes due to shaping. |
| 101 // So whenever currentWidth != currentMetrics.width(), we are processing a t
ext run whose length is | 139 // So whenever currentWidth != currentMetrics.width(), we are processing a t
ext run whose length is |
| 102 // not equal to the sum of the individual lengths of the glyphs, when measur
ing them isolated. | 140 // not equal to the sum of the individual lengths of the glyphs, when measur
ing them isolated. |
| 103 float currentWidth = complexStartToCurrentMetrics.width() - m_totalWidth; | 141 float currentWidth = complexStartToCurrentMetrics.width() - m_totalWidth; |
| 104 if (currentWidth != metrics.width()) | 142 if (currentWidth != metrics.width()) |
| 105 metrics.setWidth(currentWidth); | 143 metrics.setWidth(currentWidth); |
| 106 | 144 |
| 107 m_totalWidth = complexStartToCurrentMetrics.width(); | 145 m_totalWidth = complexStartToCurrentMetrics.width(); |
| 108 return metrics; | 146 return metrics; |
| 109 } | 147 } |
| 110 | 148 |
| 111 SVGTextMetrics SVGTextMetricsCalculator::computeMetricsForCharacter(unsigned tex
tPosition) | 149 SVGTextMetrics SVGTextMetricsCalculator::computeMetricsForCharacter(unsigned tex
tPosition) |
| 112 { | 150 { |
| 151 if (m_bidiRun) { |
| 152 if (textPosition >= static_cast<unsigned>(m_bidiRun->stop())) { |
| 153 m_bidiRun = m_bidiRun->next(); |
| 154 // New BiDi run means new reference position for measurements, so re
set |m_totalWidth|. |
| 155 m_totalWidth = 0; |
| 156 } |
| 157 ASSERT(m_bidiRun); |
| 158 ASSERT(static_cast<int>(textPosition) < m_bidiRun->stop()); |
| 159 m_textDirection = m_bidiRun->direction(); |
| 160 } |
| 161 |
| 113 if (m_isComplexText) | 162 if (m_isComplexText) |
| 114 return computeMetricsForCharacterComplex(textPosition); | 163 return computeMetricsForCharacterComplex(textPosition); |
| 115 | 164 |
| 116 return computeMetricsForCharacterSimple(textPosition); | 165 return computeMetricsForCharacterSimple(textPosition); |
| 117 } | 166 } |
| 118 | 167 |
| 119 struct MeasureTextData { | 168 struct MeasureTextData { |
| 120 MeasureTextData(SVGCharacterDataMap* characterDataMap) | 169 MeasureTextData(SVGCharacterDataMap* characterDataMap) |
| 121 : allCharactersMap(characterDataMap) | 170 : allCharactersMap(characterDataMap) |
| 122 , lastCharacterWasWhiteSpace(true) | 171 , lastCharacterWasWhiteSpace(true) |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 218 } | 267 } |
| 219 | 268 |
| 220 void SVGTextMetricsBuilder::buildMetricsAndLayoutAttributes(RenderSVGText* textR
oot, RenderSVGInlineText* stopAtLeaf, SVGCharacterDataMap& allCharactersMap) | 269 void SVGTextMetricsBuilder::buildMetricsAndLayoutAttributes(RenderSVGText* textR
oot, RenderSVGInlineText* stopAtLeaf, SVGCharacterDataMap& allCharactersMap) |
| 221 { | 270 { |
| 222 ASSERT(textRoot); | 271 ASSERT(textRoot); |
| 223 MeasureTextData data(&allCharactersMap); | 272 MeasureTextData data(&allCharactersMap); |
| 224 walkTree(textRoot, stopAtLeaf, &data); | 273 walkTree(textRoot, stopAtLeaf, &data); |
| 225 } | 274 } |
| 226 | 275 |
| 227 } | 276 } |
| OLD | NEW |