| 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 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 327 { | 327 { |
| 328 ++m_logicalMetricsListOffset; | 328 ++m_logicalMetricsListOffset; |
| 329 m_logicalCharacterOffset += logicalMetrics.length(); | 329 m_logicalCharacterOffset += logicalMetrics.length(); |
| 330 } | 330 } |
| 331 | 331 |
| 332 void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, cons
t LayoutSVGInlineText& text, const ComputedStyle& style) | 332 void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, cons
t LayoutSVGInlineText& text, const ComputedStyle& style) |
| 333 { | 333 { |
| 334 if (m_inPathLayout && !m_textPathCalculator) | 334 if (m_inPathLayout && !m_textPathCalculator) |
| 335 return; | 335 return; |
| 336 | 336 |
| 337 const SVGComputedStyle& svgStyle = style.svgStyle(); | |
| 338 | |
| 339 // Find the start of the current text box in the metrics list. | 337 // Find the start of the current text box in the metrics list. |
| 340 m_visualMetricsIterator.advanceToTextStart(&text, textBox->start()); | 338 m_visualMetricsIterator.advanceToTextStart(&text, textBox->start()); |
| 341 | 339 |
| 342 const Font& font = style.font(); | 340 const Font& font = style.font(); |
| 343 | 341 |
| 344 SVGTextLayoutEngineSpacing spacingLayout(font, style.effectiveZoom()); | 342 SVGTextLayoutEngineSpacing spacingLayout(font, style.effectiveZoom()); |
| 345 SVGTextLayoutEngineBaseline baselineLayout(font, style.effectiveZoom()); | 343 SVGTextLayoutEngineBaseline baselineLayout(font, style.effectiveZoom()); |
| 346 | 344 |
| 347 bool didStartTextFragment = false; | 345 bool didStartTextFragment = false; |
| 348 bool applySpacingToNextCharacter = false; | 346 bool applySpacingToNextCharacter = false; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 379 float y = data.y; | 377 float y = data.y; |
| 380 | 378 |
| 381 // When we've advanced to the box start offset, determine using the orig
inal x/y values, | 379 // When we've advanced to the box start offset, determine using the orig
inal x/y values, |
| 382 // whether this character starts a new text chunk, before doing any furt
her processing. | 380 // whether this character starts a new text chunk, before doing any furt
her processing. |
| 383 if (m_visualMetricsIterator.characterOffset() == textBox->start()) | 381 if (m_visualMetricsIterator.characterOffset() == textBox->start()) |
| 384 textBox->setStartsNewTextChunk(logicalAttributes->context()->charact
erStartsNewTextChunk(m_logicalCharacterOffset)); | 382 textBox->setStartsNewTextChunk(logicalAttributes->context()->charact
erStartsNewTextChunk(m_logicalCharacterOffset)); |
| 385 | 383 |
| 386 float angle = SVGTextLayoutAttributes::isEmptyValue(data.rotate) ? 0 : d
ata.rotate; | 384 float angle = SVGTextLayoutAttributes::isEmptyValue(data.rotate) ? 0 : d
ata.rotate; |
| 387 | 385 |
| 388 // Calculate glyph orientation angle. | 386 // Calculate glyph orientation angle. |
| 387 // Font::width() calculates the resolved FontOrientation for each charac
ter, |
| 388 // but is not exposed today to avoid the API complexity. |
| 389 UChar32 currentCharacter = text.codepointAt(m_visualMetricsIterator.char
acterOffset()); | 389 UChar32 currentCharacter = text.codepointAt(m_visualMetricsIterator.char
acterOffset()); |
| 390 float orientationAngle = baselineLayout.calculateGlyphOrientationAngle(m
_isVerticalText, svgStyle, currentCharacter); | 390 FontOrientation fontOrientation = font.fontDescription().orientation(); |
| 391 fontOrientation = adjustOrientationForCharacterInMixedVertical(fontOrien
tation, currentCharacter); |
| 391 | 392 |
| 392 // Calculate glyph advance & x/y orientation shifts. | 393 // Calculate glyph advance. |
| 393 float xOrientationShift = 0; | 394 // Shaping engine takes care of x/y orientation shifts for different fon
tOrientation values. |
| 394 float yOrientationShift = 0; | 395 float glyphAdvance = visualMetrics.advance(fontOrientation); |
| 395 float glyphAdvance = baselineLayout.calculateGlyphAdvanceAndOrientation(
m_isVerticalText, visualMetrics, orientationAngle, xOrientationShift, yOrientati
onShift); | |
| 396 | 396 |
| 397 // Assign current text position to x/y values, if needed. | 397 // Assign current text position to x/y values, if needed. |
| 398 updateCharacterPositionIfNeeded(x, y); | 398 updateCharacterPositionIfNeeded(x, y); |
| 399 | 399 |
| 400 // Apply dx/dy value adjustments to current text position, if needed. | 400 // Apply dx/dy value adjustments to current text position, if needed. |
| 401 updateRelativePositionAdjustmentsIfNeeded(data.dx, data.dy); | 401 updateRelativePositionAdjustmentsIfNeeded(data.dx, data.dy); |
| 402 | 402 |
| 403 // Calculate CSS 'letter-spacing' and 'word-spacing' for next character,
if needed. | 403 // Calculate CSS 'letter-spacing' and 'word-spacing' for next character,
if needed. |
| 404 float spacing = spacingLayout.calculateCSSSpacing(currentCharacter); | 404 float spacing = spacingLayout.calculateCSSSpacing(currentCharacter); |
| 405 | 405 |
| 406 float textPathOffset = 0; | 406 float textPathOffset = 0; |
| 407 float textPathShiftX = 0; |
| 408 float textPathShiftY = 0; |
| 407 if (m_inPathLayout) { | 409 if (m_inPathLayout) { |
| 408 float scaledGlyphAdvance = glyphAdvance * m_textPathScaling; | 410 float scaledGlyphAdvance = glyphAdvance * m_textPathScaling; |
| 409 if (m_isVerticalText) { | 411 if (m_isVerticalText) { |
| 410 // If there's an absolute y position available, it marks the beg
inning of a new position along the path. | 412 // If there's an absolute y position available, it marks the beg
inning of a new position along the path. |
| 411 if (!SVGTextLayoutAttributes::isEmptyValue(y)) | 413 if (!SVGTextLayoutAttributes::isEmptyValue(y)) |
| 412 m_textPathCurrentOffset = y + m_textPathStartOffset; | 414 m_textPathCurrentOffset = y + m_textPathStartOffset; |
| 413 | 415 |
| 414 m_textPathCurrentOffset += m_dy; | 416 m_textPathCurrentOffset += m_dy; |
| 415 m_dy = 0; | 417 m_dy = 0; |
| 416 | 418 |
| 417 // Apply dx/dy correction and setup translations that move to th
e glyph midpoint. | 419 // Apply dx/dy correction and setup translations that move to th
e glyph midpoint. |
| 418 xOrientationShift += m_dx + baselineShift; | 420 textPathShiftX += m_dx + baselineShift; |
| 419 yOrientationShift -= scaledGlyphAdvance / 2; | 421 textPathShiftY -= scaledGlyphAdvance / 2; |
| 420 } else { | 422 } else { |
| 421 // If there's an absolute x position available, it marks the beg
inning of a new position along the path. | 423 // If there's an absolute x position available, it marks the beg
inning of a new position along the path. |
| 422 if (!SVGTextLayoutAttributes::isEmptyValue(x)) | 424 if (!SVGTextLayoutAttributes::isEmptyValue(x)) |
| 423 m_textPathCurrentOffset = x + m_textPathStartOffset; | 425 m_textPathCurrentOffset = x + m_textPathStartOffset; |
| 424 | 426 |
| 425 m_textPathCurrentOffset += m_dx; | 427 m_textPathCurrentOffset += m_dx; |
| 426 m_dx = 0; | 428 m_dx = 0; |
| 427 | 429 |
| 428 // Apply dx/dy correction and setup translations that move to th
e glyph midpoint. | 430 // Apply dx/dy correction and setup translations that move to th
e glyph midpoint. |
| 429 xOrientationShift -= scaledGlyphAdvance / 2; | 431 textPathShiftX -= scaledGlyphAdvance / 2; |
| 430 yOrientationShift += m_dy - baselineShift; | 432 textPathShiftY += m_dy - baselineShift; |
| 431 } | 433 } |
| 432 | 434 |
| 433 // Calculate current offset along path. | 435 // Calculate current offset along path. |
| 434 textPathOffset = m_textPathCurrentOffset + scaledGlyphAdvance / 2; | 436 textPathOffset = m_textPathCurrentOffset + scaledGlyphAdvance / 2; |
| 435 | 437 |
| 436 // Move to next character. | 438 // Move to next character. |
| 437 m_textPathCurrentOffset += scaledGlyphAdvance + m_textPathSpacing +
spacing * m_textPathScaling; | 439 m_textPathCurrentOffset += scaledGlyphAdvance + m_textPathSpacing +
spacing * m_textPathScaling; |
| 438 | 440 |
| 439 // Skip character, if we're before the path. | 441 // Skip character, if we're before the path. |
| 440 if (textPathOffset < 0) { | 442 if (textPathOffset < 0) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 462 x += baselineShift; | 464 x += baselineShift; |
| 463 else | 465 else |
| 464 y -= baselineShift; | 466 y -= baselineShift; |
| 465 | 467 |
| 466 x += m_dx; | 468 x += m_dx; |
| 467 y += m_dy; | 469 y += m_dy; |
| 468 } | 470 } |
| 469 | 471 |
| 470 // Determine whether we have to start a new fragment. | 472 // Determine whether we have to start a new fragment. |
| 471 bool shouldStartNewFragment = m_dx || m_dy || m_isVerticalText || m_inPa
thLayout || angle || angle != lastAngle | 473 bool shouldStartNewFragment = m_dx || m_dy || m_isVerticalText || m_inPa
thLayout || angle || angle != lastAngle |
| 472 || orientationAngle || applySpacingToNextCharacter || m_textLengthSp
acingInEffect; | 474 || applySpacingToNextCharacter || m_textLengthSpacingInEffect; |
| 473 | 475 |
| 474 // If we already started a fragment, close it now. | 476 // If we already started a fragment, close it now. |
| 475 if (didStartTextFragment && shouldStartNewFragment) { | 477 if (didStartTextFragment && shouldStartNewFragment) { |
| 476 applySpacingToNextCharacter = false; | 478 applySpacingToNextCharacter = false; |
| 477 recordTextFragment(textBox); | 479 recordTextFragment(textBox); |
| 478 } | 480 } |
| 479 | 481 |
| 480 // Eventually start a new fragment, if not yet done. | 482 // Eventually start a new fragment, if not yet done. |
| 481 if (!didStartTextFragment || shouldStartNewFragment) { | 483 if (!didStartTextFragment || shouldStartNewFragment) { |
| 482 ASSERT(!m_currentTextFragment.characterOffset); | 484 ASSERT(!m_currentTextFragment.characterOffset); |
| 483 ASSERT(!m_currentTextFragment.length); | 485 ASSERT(!m_currentTextFragment.length); |
| 484 | 486 |
| 485 didStartTextFragment = true; | 487 didStartTextFragment = true; |
| 486 m_currentTextFragment.characterOffset = m_visualMetricsIterator.char
acterOffset(); | 488 m_currentTextFragment.characterOffset = m_visualMetricsIterator.char
acterOffset(); |
| 487 m_currentTextFragment.metricsListOffset = m_visualMetricsIterator.me
tricsListOffset(); | 489 m_currentTextFragment.metricsListOffset = m_visualMetricsIterator.me
tricsListOffset(); |
| 488 m_currentTextFragment.x = x; | 490 m_currentTextFragment.x = x; |
| 489 m_currentTextFragment.y = y; | 491 m_currentTextFragment.y = y; |
| 490 | 492 |
| 491 // Build fragment transformation. | 493 // Build fragment transformation. |
| 492 if (angle) | 494 if (angle) |
| 493 m_currentTextFragment.transform.rotate(angle); | 495 m_currentTextFragment.transform.rotate(angle); |
| 494 | 496 |
| 495 if (xOrientationShift || yOrientationShift) | 497 if (textPathShiftX || textPathShiftY) |
| 496 m_currentTextFragment.transform.translate(xOrientationShift, yOr
ientationShift); | 498 m_currentTextFragment.transform.translate(textPathShiftX, textPa
thShiftY); |
| 497 | 499 |
| 498 if (orientationAngle) | 500 // In vertical text, always rotate by 90 degrees regardless of fontO
rientation. |
| 499 m_currentTextFragment.transform.rotate(orientationAngle); | 501 // Shaping engine takes care of the necessary orientation. |
| 502 if (m_isVerticalText) |
| 503 m_currentTextFragment.transform.rotate(90); |
| 500 | 504 |
| 501 m_currentTextFragment.isTextOnPath = m_inPathLayout && m_textPathSca
ling != 1; | 505 m_currentTextFragment.isTextOnPath = m_inPathLayout && m_textPathSca
ling != 1; |
| 502 if (m_currentTextFragment.isTextOnPath) { | 506 if (m_currentTextFragment.isTextOnPath) { |
| 503 if (m_isVerticalText) | 507 if (m_isVerticalText) |
| 504 m_currentTextFragment.lengthAdjustTransform.scaleNonUniform(
1, m_textPathScaling); | 508 m_currentTextFragment.lengthAdjustTransform.scaleNonUniform(
1, m_textPathScaling); |
| 505 else | 509 else |
| 506 m_currentTextFragment.lengthAdjustTransform.scaleNonUniform(
m_textPathScaling, 1); | 510 m_currentTextFragment.lengthAdjustTransform.scaleNonUniform(
m_textPathScaling, 1); |
| 507 } | 511 } |
| 508 } | 512 } |
| 509 | 513 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 532 } | 536 } |
| 533 | 537 |
| 534 if (!didStartTextFragment) | 538 if (!didStartTextFragment) |
| 535 return; | 539 return; |
| 536 | 540 |
| 537 // Close last open fragment, if needed. | 541 // Close last open fragment, if needed. |
| 538 recordTextFragment(textBox); | 542 recordTextFragment(textBox); |
| 539 } | 543 } |
| 540 | 544 |
| 541 } | 545 } |
| OLD | NEW |