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 |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 m_visualMetricsIterator = SVGInlineTextMetricsIterator(); | 269 m_visualMetricsIterator = SVGInlineTextMetricsIterator(); |
270 | 270 |
271 // After all text fragments are stored in their correpsonding SVGInlineTextB
oxes, we can layout individual text chunks. | 271 // After all text fragments are stored in their correpsonding SVGInlineTextB
oxes, we can layout individual text chunks. |
272 // Chunk layouting is only performed for line layout boxes, not for path lay
out, where it has already been done. | 272 // Chunk layouting is only performed for line layout boxes, not for path lay
out, where it has already been done. |
273 SVGTextChunkBuilder chunkLayoutBuilder; | 273 SVGTextChunkBuilder chunkLayoutBuilder; |
274 chunkLayoutBuilder.processTextChunks(m_lineLayoutBoxes); | 274 chunkLayoutBuilder.processTextChunks(m_lineLayoutBoxes); |
275 | 275 |
276 m_lineLayoutBoxes.clear(); | 276 m_lineLayoutBoxes.clear(); |
277 } | 277 } |
278 | 278 |
279 bool SVGTextLayoutEngine::currentLogicalCharacterAttributes(SVGTextLayoutAttribu
tes*& logicalAttributes) | 279 const SVGTextLayoutAttributes* SVGTextLayoutEngine::nextLogicalAttributes() |
280 { | 280 { |
281 if (m_layoutAttributesPosition == m_layoutAttributes.size()) | 281 ASSERT(m_layoutAttributesPosition < m_layoutAttributes.size()); |
282 return false; | |
283 | |
284 logicalAttributes = m_layoutAttributes[m_layoutAttributesPosition]; | |
285 ASSERT(logicalAttributes); | |
286 | |
287 if (m_logicalCharacterOffset != logicalAttributes->context()->textLength()) | |
288 return true; | |
289 | |
290 ++m_layoutAttributesPosition; | 282 ++m_layoutAttributesPosition; |
291 if (m_layoutAttributesPosition == m_layoutAttributes.size()) | 283 if (m_layoutAttributesPosition == m_layoutAttributes.size()) |
292 return false; | 284 return nullptr; |
293 | 285 |
294 logicalAttributes = m_layoutAttributes[m_layoutAttributesPosition]; | |
295 m_logicalMetricsListOffset = 0; | 286 m_logicalMetricsListOffset = 0; |
296 m_logicalCharacterOffset = 0; | 287 m_logicalCharacterOffset = 0; |
297 return true; | 288 return m_layoutAttributes[m_layoutAttributesPosition]; |
298 } | 289 } |
299 | 290 |
300 bool SVGTextLayoutEngine::currentLogicalCharacterMetrics(SVGTextLayoutAttributes
*& logicalAttributes, SVGTextMetrics& logicalMetrics) | 291 const SVGTextLayoutAttributes* SVGTextLayoutEngine::currentLogicalCharacterMetri
cs(SVGTextMetrics& logicalMetrics) |
301 { | 292 { |
| 293 // If we're consumed all layout attributes, there can be no more metrics. |
| 294 if (m_layoutAttributesPosition == m_layoutAttributes.size()) |
| 295 return nullptr; |
| 296 |
| 297 const SVGTextLayoutAttributes* logicalAttributes = m_layoutAttributes[m_layo
utAttributesPosition]; |
| 298 // If we reached the end of the text node associated with the current set |
| 299 // of layout attributes, try to move to the next text node/set of layout |
| 300 // attributes. |
| 301 ASSERT(m_logicalCharacterOffset <= logicalAttributes->context()->textLength(
)); |
| 302 if (m_logicalCharacterOffset == logicalAttributes->context()->textLength())
{ |
| 303 logicalAttributes = nextLogicalAttributes(); |
| 304 if (!logicalAttributes) |
| 305 return nullptr; |
| 306 } |
| 307 |
| 308 // We have set of layout attributes. Find the first non-collapsed text |
| 309 // metrics cell. |
302 const Vector<SVGTextMetrics>* metricsList = &logicalAttributes->context()->m
etricsList(); | 310 const Vector<SVGTextMetrics>* metricsList = &logicalAttributes->context()->m
etricsList(); |
303 unsigned metricsListSize = metricsList->size(); | 311 unsigned metricsListSize = metricsList->size(); |
304 while (true) { | 312 while (true) { |
| 313 // If we run out of metrics, move to the next set of layout attributes. |
305 if (m_logicalMetricsListOffset == metricsListSize) { | 314 if (m_logicalMetricsListOffset == metricsListSize) { |
306 if (!currentLogicalCharacterAttributes(logicalAttributes)) | 315 logicalAttributes = nextLogicalAttributes(); |
307 return false; | 316 if (!logicalAttributes) |
| 317 return nullptr; |
308 | 318 |
309 metricsList = &logicalAttributes->context()->metricsList(); | 319 metricsList = &logicalAttributes->context()->metricsList(); |
310 metricsListSize = metricsList->size(); | 320 metricsListSize = metricsList->size(); |
311 continue; | 321 continue; |
312 } | 322 } |
313 | 323 |
314 ASSERT(metricsListSize); | 324 ASSERT(metricsListSize); |
315 ASSERT(m_logicalMetricsListOffset < metricsListSize); | 325 ASSERT(m_logicalMetricsListOffset < metricsListSize); |
316 logicalMetrics = metricsList->at(m_logicalMetricsListOffset); | 326 logicalMetrics = metricsList->at(m_logicalMetricsListOffset); |
317 if (logicalMetrics.isEmpty() || (!logicalMetrics.width() && !logicalMetr
ics.height())) { | 327 if (logicalMetrics.isEmpty() || (!logicalMetrics.width() && !logicalMetr
ics.height())) { |
318 advanceToNextLogicalCharacter(logicalMetrics); | 328 advanceToNextLogicalCharacter(logicalMetrics); |
319 continue; | 329 continue; |
320 } | 330 } |
321 | 331 |
322 // Stop if we found the next valid logical text metrics object. | 332 // Stop if we found the next valid logical text metrics object. |
323 return true; | 333 return logicalAttributes; |
324 } | 334 } |
325 | 335 |
326 ASSERT_NOT_REACHED(); | 336 ASSERT_NOT_REACHED(); |
327 return true; | 337 return nullptr; |
328 } | 338 } |
329 | 339 |
330 void SVGTextLayoutEngine::advanceToNextLogicalCharacter(const SVGTextMetrics& lo
gicalMetrics) | 340 void SVGTextLayoutEngine::advanceToNextLogicalCharacter(const SVGTextMetrics& lo
gicalMetrics) |
331 { | 341 { |
332 ++m_logicalMetricsListOffset; | 342 ++m_logicalMetricsListOffset; |
333 m_logicalCharacterOffset += logicalMetrics.length(); | 343 m_logicalCharacterOffset += logicalMetrics.length(); |
334 } | 344 } |
335 | 345 |
336 void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, Line
LayoutSVGInlineText textLineLayout, const ComputedStyle& style) | 346 void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, Line
LayoutSVGInlineText textLineLayout, const ComputedStyle& style) |
337 { | 347 { |
(...skipping 23 matching lines...) Expand all Loading... |
361 | 371 |
362 // Main layout algorithm. | 372 // Main layout algorithm. |
363 const unsigned boxEndOffset = textBox->start() + textBox->len(); | 373 const unsigned boxEndOffset = textBox->start() + textBox->len(); |
364 while (!m_visualMetricsIterator.isAtEnd() && m_visualMetricsIterator.charact
erOffset() < boxEndOffset) { | 374 while (!m_visualMetricsIterator.isAtEnd() && m_visualMetricsIterator.charact
erOffset() < boxEndOffset) { |
365 const SVGTextMetrics& visualMetrics = m_visualMetricsIterator.metrics(); | 375 const SVGTextMetrics& visualMetrics = m_visualMetricsIterator.metrics(); |
366 if (visualMetrics.isEmpty()) { | 376 if (visualMetrics.isEmpty()) { |
367 m_visualMetricsIterator.next(); | 377 m_visualMetricsIterator.next(); |
368 continue; | 378 continue; |
369 } | 379 } |
370 | 380 |
371 SVGTextLayoutAttributes* logicalAttributes = nullptr; | 381 SVGTextMetrics logicalMetrics(SVGTextMetrics::SkippedSpaceMetrics); |
372 if (!currentLogicalCharacterAttributes(logicalAttributes)) | 382 const SVGTextLayoutAttributes* logicalAttributes = currentLogicalCharact
erMetrics(logicalMetrics); |
| 383 if (!logicalAttributes) |
373 break; | 384 break; |
374 | 385 |
375 ASSERT(logicalAttributes); | 386 const SVGCharacterDataMap& characterDataMap = logicalAttributes->charact
erDataMap(); |
376 SVGTextMetrics logicalMetrics(SVGTextMetrics::SkippedSpaceMetrics); | |
377 if (!currentLogicalCharacterMetrics(logicalAttributes, logicalMetrics)) | |
378 break; | |
379 | |
380 SVGCharacterDataMap& characterDataMap = logicalAttributes->characterData
Map(); | |
381 SVGCharacterData data; | 387 SVGCharacterData data; |
382 SVGCharacterDataMap::iterator it = characterDataMap.find(m_logicalCharac
terOffset + 1); | 388 SVGCharacterDataMap::const_iterator it = characterDataMap.find(m_logical
CharacterOffset + 1); |
383 if (it != characterDataMap.end()) | 389 if (it != characterDataMap.end()) |
384 data = it->value; | 390 data = it->value; |
385 | 391 |
386 // TODO(fs): Use the return value to eliminate the additional | 392 // TODO(fs): Use the return value to eliminate the additional |
387 // hash-lookup below when determining if this text box should be tagged | 393 // hash-lookup below when determining if this text box should be tagged |
388 // as starting a new text chunk. | 394 // as starting a new text chunk. |
389 setCurrentTextPosition(data); | 395 setCurrentTextPosition(data); |
390 | 396 |
391 // When we've advanced to the box start offset, determine using the orig
inal x/y values, | 397 // When we've advanced to the box start offset, determine using the orig
inal x/y values, |
392 // whether this character starts a new text chunk, before doing any furt
her processing. | 398 // whether this character starts a new text chunk, before doing any furt
her processing. |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
504 } | 510 } |
505 | 511 |
506 if (!didStartTextFragment) | 512 if (!didStartTextFragment) |
507 return; | 513 return; |
508 | 514 |
509 // Close last open fragment, if needed. | 515 // Close last open fragment, if needed. |
510 recordTextFragment(textBox); | 516 recordTextFragment(textBox); |
511 } | 517 } |
512 | 518 |
513 } // namespace blink | 519 } // namespace blink |
OLD | NEW |