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

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

Issue 1404853003: Add SVG Text to support the CSS 'text-orientation' property (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: drott review Created 5 years, 2 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
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
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698