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

Side by Side Diff: Source/core/layout/svg/SVGTextLayoutEngine.cpp

Issue 1158033006: Track if textLength spacing is in effect while walking the line box tree (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 6 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 #include "core/layout/svg/SVGTextLayoutEngine.h" 21 #include "core/layout/svg/SVGTextLayoutEngine.h"
22 22
23 #include "core/layout/svg/LayoutSVGInlineText.h" 23 #include "core/layout/svg/LayoutSVGInlineText.h"
24 #include "core/layout/svg/LayoutSVGTextPath.h" 24 #include "core/layout/svg/LayoutSVGTextPath.h"
25 #include "core/layout/svg/SVGTextChunkBuilder.h" 25 #include "core/layout/svg/SVGTextChunkBuilder.h"
26 #include "core/layout/svg/SVGTextLayoutEngineBaseline.h" 26 #include "core/layout/svg/SVGTextLayoutEngineBaseline.h"
27 #include "core/layout/svg/SVGTextLayoutEngineSpacing.h" 27 #include "core/layout/svg/SVGTextLayoutEngineSpacing.h"
28 #include "core/layout/svg/line/SVGInlineFlowBox.h"
28 #include "core/layout/svg/line/SVGInlineTextBox.h" 29 #include "core/layout/svg/line/SVGInlineTextBox.h"
29 #include "core/svg/SVGElement.h" 30 #include "core/svg/SVGElement.h"
30 #include "core/svg/SVGLengthContext.h" 31 #include "core/svg/SVGLengthContext.h"
31 #include "core/svg/SVGTextContentElement.h" 32 #include "core/svg/SVGTextContentElement.h"
32 33
33 namespace blink { 34 namespace blink {
34 35
35 SVGTextLayoutEngine::SVGTextLayoutEngine(Vector<SVGTextLayoutAttributes*>& layou tAttributes) 36 SVGTextLayoutEngine::SVGTextLayoutEngine(Vector<SVGTextLayoutAttributes*>& layou tAttributes)
36 : m_layoutAttributes(layoutAttributes) 37 : m_layoutAttributes(layoutAttributes)
37 , m_layoutAttributesPosition(0) 38 , m_layoutAttributesPosition(0)
38 , m_logicalCharacterOffset(0) 39 , m_logicalCharacterOffset(0)
39 , m_logicalMetricsListOffset(0) 40 , m_logicalMetricsListOffset(0)
40 , m_x(0) 41 , m_x(0)
41 , m_y(0) 42 , m_y(0)
42 , m_dx(0) 43 , m_dx(0)
43 , m_dy(0) 44 , m_dy(0)
44 , m_isVerticalText(false) 45 , m_isVerticalText(false)
45 , m_inPathLayout(false) 46 , m_inPathLayout(false)
47 , m_textLengthSpacingInEffect(false)
46 , m_textPathCalculator(0) 48 , m_textPathCalculator(0)
47 , m_textPathLength(0) 49 , m_textPathLength(0)
48 , m_textPathCurrentOffset(0) 50 , m_textPathCurrentOffset(0)
49 , m_textPathSpacing(0) 51 , m_textPathSpacing(0)
50 , m_textPathScaling(1) 52 , m_textPathScaling(1)
51 { 53 {
52 ASSERT(!m_layoutAttributes.isEmpty()); 54 ASSERT(!m_layoutAttributes.isEmpty());
53 } 55 }
54 56
55 void SVGTextLayoutEngine::updateCharacterPositionIfNeeded(float& x, float& y) 57 void SVGTextLayoutEngine::updateCharacterPositionIfNeeded(float& x, float& y)
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 for (unsigned i = m_currentTextFragment.metricsListOffset; i < visua lMetricsListOffset; ++i) 135 for (unsigned i = m_currentTextFragment.metricsListOffset; i < visua lMetricsListOffset; ++i)
134 length += textMetricsValues.at(i).width(); 136 length += textMetricsValues.at(i).width();
135 m_currentTextFragment.width = length; 137 m_currentTextFragment.width = length;
136 } 138 }
137 } 139 }
138 140
139 textBox->textFragments().append(m_currentTextFragment); 141 textBox->textFragments().append(m_currentTextFragment);
140 m_currentTextFragment = SVGTextFragment(); 142 m_currentTextFragment = SVGTextFragment();
141 } 143 }
142 144
143 bool SVGTextLayoutEngine::parentDefinesTextLength(LayoutObject* parent) const 145 void SVGTextLayoutEngine::beginTextPathLayout(SVGInlineFlowBox* flowBox)
144 { 146 {
145 LayoutObject* currentParent = parent; 147 // Build text chunks for all <textPath> children, using the line layout algo rithm.
146 while (currentParent) { 148 // This is needeed as text-anchor is just an additional startOffset for text paths.
147 if (SVGTextContentElement* textContentElement = SVGTextContentElement::e lementFromLayoutObject(currentParent)) { 149 SVGTextLayoutEngine lineLayout(m_layoutAttributes);
148 SVGLengthContext lengthContext(textContentElement); 150 lineLayout.m_textLengthSpacingInEffect = m_textLengthSpacingInEffect;
149 if (textContentElement->lengthAdjust()->currentValue()->enumValue() == SVGLengthAdjustSpacing && textContentElement->textLengthIsSpecifiedByUser()) 151 lineLayout.layoutCharactersInTextBoxes(flowBox);
150 return true;
151 }
152
153 if (currentParent->isSVGText())
154 return false;
155
156 currentParent = currentParent->parent();
157 }
158
159 ASSERT_NOT_REACHED();
160 return false;
161 }
162
163 void SVGTextLayoutEngine::beginTextPathLayout(LayoutObject* object, SVGTextLayou tEngine& lineLayout)
164 {
165 ASSERT(object);
166 152
167 m_inPathLayout = true; 153 m_inPathLayout = true;
168 LayoutSVGTextPath* textPath = toLayoutSVGTextPath(object); 154 LayoutSVGTextPath* textPath = &toLayoutSVGTextPath(flowBox->layoutObject());
169 155
170 Path path = textPath->layoutPath(); 156 Path path = textPath->layoutPath();
171 if (path.isEmpty()) 157 if (path.isEmpty())
172 return; 158 return;
173 m_textPathCalculator = new Path::PositionCalculator(path); 159 m_textPathCalculator = new Path::PositionCalculator(path);
174 m_textPathStartOffset = textPath->startOffset(); 160 m_textPathStartOffset = textPath->startOffset();
175 m_textPathLength = path.length(); 161 m_textPathLength = path.length();
176 if (m_textPathStartOffset > 0 && m_textPathStartOffset <= 1) 162 if (m_textPathStartOffset > 0 && m_textPathStartOffset <= 1)
177 m_textPathStartOffset *= m_textPathLength; 163 m_textPathStartOffset *= m_textPathLength;
178 164
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 textBox->clearTextFragments(); 217 textBox->clearTextFragments();
232 m_isVerticalText = style.svgStyle().isVerticalWritingMode(); 218 m_isVerticalText = style.svgStyle().isVerticalWritingMode();
233 layoutTextOnLineOrPath(textBox, text, style); 219 layoutTextOnLineOrPath(textBox, text, style);
234 220
235 if (m_inPathLayout) 221 if (m_inPathLayout)
236 return; 222 return;
237 223
238 m_lineLayoutBoxes.append(textBox); 224 m_lineLayoutBoxes.append(textBox);
239 } 225 }
240 226
227 static bool definesTextLengthWithSpacing(const InlineFlowBox* start)
228 {
229 SVGTextContentElement* textContentElement = SVGTextContentElement::elementFr omLayoutObject(&start->layoutObject());
230 return textContentElement
231 && textContentElement->lengthAdjust()->currentValue()->enumValue() == SV GLengthAdjustSpacing
232 && textContentElement->textLengthIsSpecifiedByUser();
233 }
234
235 void SVGTextLayoutEngine::layoutCharactersInTextBoxes(InlineFlowBox* start)
236 {
237 bool textLengthSpacingInEffect = m_textLengthSpacingInEffect || definesTextL engthWithSpacing(start);
238 TemporaryChange<bool> textLengthSpacingScope(m_textLengthSpacingInEffect, te xtLengthSpacingInEffect);
239
240 for (InlineBox* child = start->firstChild(); child; child = child->nextOnLin e()) {
241 if (child->isSVGInlineTextBox()) {
242 ASSERT(child->layoutObject().isSVGInlineText());
243 layoutInlineTextBox(toSVGInlineTextBox(child));
244 } else {
245 // Skip generated content.
246 Node* node = child->layoutObject().node();
247 if (!node)
248 continue;
249
250 SVGInlineFlowBox* flowBox = toSVGInlineFlowBox(child);
251 bool isTextPath = isSVGTextPathElement(*node);
252 if (isTextPath)
253 beginTextPathLayout(flowBox);
254
255 layoutCharactersInTextBoxes(flowBox);
256
257 if (isTextPath)
258 endTextPathLayout();
259 }
260 }
261 }
262
241 void SVGTextLayoutEngine::finishLayout() 263 void SVGTextLayoutEngine::finishLayout()
242 { 264 {
243 m_visualMetricsIterator = SVGInlineTextMetricsIterator(); 265 m_visualMetricsIterator = SVGInlineTextMetricsIterator();
244 266
245 // After all text fragments are stored in their correpsonding SVGInlineTextB oxes, we can layout individual text chunks. 267 // After all text fragments are stored in their correpsonding SVGInlineTextB oxes, we can layout individual text chunks.
246 // Chunk layouting is only performed for line layout boxes, not for path lay out, where it has already been done. 268 // Chunk layouting is only performed for line layout boxes, not for path lay out, where it has already been done.
247 SVGTextChunkBuilder chunkLayoutBuilder; 269 SVGTextChunkBuilder chunkLayoutBuilder;
248 chunkLayoutBuilder.processTextChunks(m_lineLayoutBoxes); 270 chunkLayoutBuilder.processTextChunks(m_lineLayoutBoxes);
249 271
250 // Finalize transform matrices, after the chunk layout corrections have been applied, and all fragment x/y positions are finalized. 272 // Finalize transform matrices, after the chunk layout corrections have been applied, and all fragment x/y positions are finalized.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 { 331 {
310 ++m_logicalMetricsListOffset; 332 ++m_logicalMetricsListOffset;
311 m_logicalCharacterOffset += logicalMetrics.length(); 333 m_logicalCharacterOffset += logicalMetrics.length();
312 } 334 }
313 335
314 void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, cons t LayoutSVGInlineText& text, const ComputedStyle& style) 336 void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, cons t LayoutSVGInlineText& text, const ComputedStyle& style)
315 { 337 {
316 if (m_inPathLayout && !m_textPathCalculator) 338 if (m_inPathLayout && !m_textPathCalculator)
317 return; 339 return;
318 340
319 LayoutObject* textParent = text.parent();
320 bool definesTextLength = textParent ? parentDefinesTextLength(textParent) : false;
321
322 const SVGComputedStyle& svgStyle = style.svgStyle(); 341 const SVGComputedStyle& svgStyle = style.svgStyle();
323 342
324 // Find the start of the current text box in the metrics list. 343 // Find the start of the current text box in the metrics list.
325 m_visualMetricsIterator.advanceToTextStart(&text, textBox->start()); 344 m_visualMetricsIterator.advanceToTextStart(&text, textBox->start());
326 345
327 const Font& font = style.font(); 346 const Font& font = style.font();
328 347
329 SVGTextLayoutEngineSpacing spacingLayout(font, style.effectiveZoom()); 348 SVGTextLayoutEngineSpacing spacingLayout(font, style.effectiveZoom());
330 SVGTextLayoutEngineBaseline baselineLayout(font, style.effectiveZoom()); 349 SVGTextLayoutEngineBaseline baselineLayout(font, style.effectiveZoom());
331 350
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 x += baselineShift; 466 x += baselineShift;
448 else 467 else
449 y -= baselineShift; 468 y -= baselineShift;
450 469
451 x += m_dx; 470 x += m_dx;
452 y += m_dy; 471 y += m_dy;
453 } 472 }
454 473
455 // Determine whether we have to start a new fragment. 474 // Determine whether we have to start a new fragment.
456 bool shouldStartNewFragment = m_dx || m_dy || m_isVerticalText || m_inPa thLayout || angle || angle != lastAngle 475 bool shouldStartNewFragment = m_dx || m_dy || m_isVerticalText || m_inPa thLayout || angle || angle != lastAngle
457 || orientationAngle || applySpacingToNextCharacter || definesTextLen gth; 476 || orientationAngle || applySpacingToNextCharacter || m_textLengthSp acingInEffect;
458 477
459 // If we already started a fragment, close it now. 478 // If we already started a fragment, close it now.
460 if (didStartTextFragment && shouldStartNewFragment) { 479 if (didStartTextFragment && shouldStartNewFragment) {
461 applySpacingToNextCharacter = false; 480 applySpacingToNextCharacter = false;
462 recordTextFragment(textBox); 481 recordTextFragment(textBox);
463 } 482 }
464 483
465 // Eventually start a new fragment, if not yet done. 484 // Eventually start a new fragment, if not yet done.
466 if (!didStartTextFragment || shouldStartNewFragment) { 485 if (!didStartTextFragment || shouldStartNewFragment) {
467 ASSERT(!m_currentTextFragment.characterOffset); 486 ASSERT(!m_currentTextFragment.characterOffset);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 } 536 }
518 537
519 if (!didStartTextFragment) 538 if (!didStartTextFragment)
520 return; 539 return;
521 540
522 // Close last open fragment, if needed. 541 // Close last open fragment, if needed.
523 recordTextFragment(textBox); 542 recordTextFragment(textBox);
524 } 543 }
525 544
526 } 545 }
OLDNEW
« no previous file with comments | « Source/core/layout/svg/SVGTextLayoutEngine.h ('k') | Source/core/layout/svg/line/SVGRootInlineBox.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698