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

Side by Side Diff: third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp

Issue 2392443009: reflow comments in core/paint (Closed)
Patch Set: Created 4 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 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/paint/InlineTextBoxPainter.h" 5 #include "core/paint/InlineTextBoxPainter.h"
6 6
7 #include "core/editing/CompositionUnderline.h" 7 #include "core/editing/CompositionUnderline.h"
8 #include "core/editing/Editor.h" 8 #include "core/editing/Editor.h"
9 #include "core/editing/markers/DocumentMarkerController.h" 9 #include "core/editing/markers/DocumentMarkerController.h"
10 #include "core/frame/LocalFrame.h" 10 #include "core/frame/LocalFrame.h"
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 bool isPrinting = paintInfo.isPrinting(); 89 bool isPrinting = paintInfo.isPrinting();
90 90
91 // Determine whether or not we're selected. 91 // Determine whether or not we're selected.
92 bool haveSelection = !isPrinting && paintInfo.phase != PaintPhaseTextClip && 92 bool haveSelection = !isPrinting && paintInfo.phase != PaintPhaseTextClip &&
93 m_inlineTextBox.getSelectionState() != SelectionNone; 93 m_inlineTextBox.getSelectionState() != SelectionNone;
94 if (!haveSelection && paintInfo.phase == PaintPhaseSelection) { 94 if (!haveSelection && paintInfo.phase == PaintPhaseSelection) {
95 // When only painting the selection, don't bother to paint if there is none. 95 // When only painting the selection, don't bother to paint if there is none.
96 return; 96 return;
97 } 97 }
98 98
99 // The text clip phase already has a LayoutObjectDrawingRecorder. Text clips a re initiated only in BoxPainter::paintFillLayer, 99 // The text clip phase already has a LayoutObjectDrawingRecorder. Text clips
100 // which is already within a LayoutObjectDrawingRecorder. 100 // are initiated only in BoxPainter::paintFillLayer, which is already within a
101 // LayoutObjectDrawingRecorder.
101 Optional<DrawingRecorder> drawingRecorder; 102 Optional<DrawingRecorder> drawingRecorder;
102 if (paintInfo.phase != PaintPhaseTextClip) { 103 if (paintInfo.phase != PaintPhaseTextClip) {
103 if (DrawingRecorder::useCachedDrawingIfPossible( 104 if (DrawingRecorder::useCachedDrawingIfPossible(
104 paintInfo.context, m_inlineTextBox, 105 paintInfo.context, m_inlineTextBox,
105 DisplayItem::paintPhaseToDrawingType(paintInfo.phase))) 106 DisplayItem::paintPhaseToDrawingType(paintInfo.phase)))
106 return; 107 return;
107 LayoutRect paintRect(logicalVisualOverflow); 108 LayoutRect paintRect(logicalVisualOverflow);
108 m_inlineTextBox.logicalRectToPhysicalRect(paintRect); 109 m_inlineTextBox.logicalRectToPhysicalRect(paintRect);
109 if (paintInfo.phase != PaintPhaseSelection && 110 if (paintInfo.phase != PaintPhaseSelection &&
110 (haveSelection || paintsMarkerHighlights(inlineLayoutObject()))) 111 (haveSelection || paintsMarkerHighlights(inlineLayoutObject())))
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 bool paintSelectedTextOnly = (paintInfo.phase == PaintPhaseSelection); 182 bool paintSelectedTextOnly = (paintInfo.phase == PaintPhaseSelection);
182 bool paintSelectedTextSeparately = 183 bool paintSelectedTextSeparately =
183 !paintSelectedTextOnly && textStyle != selectionStyle; 184 !paintSelectedTextOnly && textStyle != selectionStyle;
184 185
185 // Set our font. 186 // Set our font.
186 const Font& font = styleToUse.font(); 187 const Font& font = styleToUse.font();
187 188
188 LayoutPoint textOrigin(boxOrigin.x(), 189 LayoutPoint textOrigin(boxOrigin.x(),
189 boxOrigin.y() + font.getFontMetrics().ascent()); 190 boxOrigin.y() + font.getFontMetrics().ascent());
190 191
191 // 1. Paint backgrounds behind text if needed. Examples of such backgrounds in clude selection 192 // 1. Paint backgrounds behind text if needed. Examples of such backgrounds
192 // and composition highlights. 193 // include selection and composition highlights.
193 if (paintInfo.phase != PaintPhaseSelection && 194 if (paintInfo.phase != PaintPhaseSelection &&
194 paintInfo.phase != PaintPhaseTextClip && !isPrinting) { 195 paintInfo.phase != PaintPhaseTextClip && !isPrinting) {
195 paintDocumentMarkers(paintInfo, boxOrigin, styleToUse, font, 196 paintDocumentMarkers(paintInfo, boxOrigin, styleToUse, font,
196 DocumentMarkerPaintPhase::Background); 197 DocumentMarkerPaintPhase::Background);
197 198
198 const LayoutObject& textBoxLayoutObject = inlineLayoutObject(); 199 const LayoutObject& textBoxLayoutObject = inlineLayoutObject();
199 if (haveSelection && !paintsCompositionMarkers(textBoxLayoutObject)) { 200 if (haveSelection && !paintsCompositionMarkers(textBoxLayoutObject)) {
200 if (combinedText) 201 if (combinedText)
201 paintSelection<InlineTextBoxPainter::PaintOptions::CombinedText>( 202 paintSelection<InlineTextBoxPainter::PaintOptions::CombinedText>(
202 context, boxRect, styleToUse, font, selectionStyle.fillColor, 203 context, boxRect, styleToUse, font, selectionStyle.fillColor,
203 combinedText); 204 combinedText);
204 else 205 else
205 paintSelection<InlineTextBoxPainter::PaintOptions::Normal>( 206 paintSelection<InlineTextBoxPainter::PaintOptions::Normal>(
206 context, boxRect, styleToUse, font, selectionStyle.fillColor); 207 context, boxRect, styleToUse, font, selectionStyle.fillColor);
207 } 208 }
208 } 209 }
209 210
210 // 2. Now paint the foreground, including text and decorations like underline/ overline (in quirks mode only). 211 // 2. Now paint the foreground, including text and decorations like
212 // underline/overline (in quirks mode only).
211 int selectionStart = 0; 213 int selectionStart = 0;
212 int selectionEnd = 0; 214 int selectionEnd = 0;
213 if (paintSelectedTextOnly || paintSelectedTextSeparately) 215 if (paintSelectedTextOnly || paintSelectedTextSeparately)
214 m_inlineTextBox.selectionStartEnd(selectionStart, selectionEnd); 216 m_inlineTextBox.selectionStartEnd(selectionStart, selectionEnd);
215 217
216 bool respectHyphen = 218 bool respectHyphen =
217 selectionEnd == static_cast<int>(m_inlineTextBox.len()) && 219 selectionEnd == static_cast<int>(m_inlineTextBox.len()) &&
218 m_inlineTextBox.hasHyphen(); 220 m_inlineTextBox.hasHyphen();
219 if (respectHyphen) 221 if (respectHyphen)
220 selectionEnd = textRun.length(); 222 selectionEnd = textRun.length();
(...skipping 16 matching lines...) Expand all
237 if (combinedText) 239 if (combinedText)
238 textPainter.setCombinedText(combinedText); 240 textPainter.setCombinedText(combinedText);
239 241
240 if (!paintSelectedTextOnly) { 242 if (!paintSelectedTextOnly) {
241 int startOffset = 0; 243 int startOffset = 0;
242 int endOffset = length; 244 int endOffset = length;
243 if (paintSelectedTextSeparately && selectionStart < selectionEnd) { 245 if (paintSelectedTextSeparately && selectionStart < selectionEnd) {
244 startOffset = selectionEnd; 246 startOffset = selectionEnd;
245 endOffset = selectionStart; 247 endOffset = selectionStart;
246 } 248 }
247 // Where the text and its flow have opposite directions then our offset into the text given by |truncation| is at 249 // Where the text and its flow have opposite directions then our offset into
248 // the start of the part that will be visible. 250 // the text given by |truncation| is at the start of the part that will be
251 // visible.
249 if (m_inlineTextBox.truncation() != cNoTruncation && 252 if (m_inlineTextBox.truncation() != cNoTruncation &&
250 m_inlineTextBox.getLineLayoutItem() 253 m_inlineTextBox.getLineLayoutItem()
251 .containingBlock() 254 .containingBlock()
252 .style() 255 .style()
253 ->isLeftToRightDirection() != 256 ->isLeftToRightDirection() !=
254 m_inlineTextBox.isLeftToRightDirection()) { 257 m_inlineTextBox.isLeftToRightDirection()) {
255 startOffset = m_inlineTextBox.truncation(); 258 startOffset = m_inlineTextBox.truncation();
256 endOffset = textRun.length(); 259 endOffset = textRun.length();
257 } 260 }
258 261
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 return; 398 return;
396 399
397 DCHECK(m_inlineTextBox.truncation() != cFullTruncation); 400 DCHECK(m_inlineTextBox.truncation() != cFullTruncation);
398 DCHECK(m_inlineTextBox.len()); 401 DCHECK(m_inlineTextBox.len());
399 402
400 DocumentMarkerVector markers = 403 DocumentMarkerVector markers =
401 m_inlineTextBox.getLineLayoutItem().document().markers().markersFor( 404 m_inlineTextBox.getLineLayoutItem().document().markers().markersFor(
402 m_inlineTextBox.getLineLayoutItem().node()); 405 m_inlineTextBox.getLineLayoutItem().node());
403 DocumentMarkerVector::const_iterator markerIt = markers.begin(); 406 DocumentMarkerVector::const_iterator markerIt = markers.begin();
404 407
405 // Give any document markers that touch this run a chance to draw before the t ext has been drawn. 408 // Give any document markers that touch this run a chance to draw before the
406 // Note end() points at the last char, not one past it like endOffset and rang es do. 409 // text has been drawn. Note end() points at the last char, not one past it
410 // like endOffset and ranges do.
407 for (; markerIt != markers.end(); ++markerIt) { 411 for (; markerIt != markers.end(); ++markerIt) {
408 DocumentMarker* marker = *markerIt; 412 DocumentMarker* marker = *markerIt;
409 413
410 // Paint either the background markers or the foreground markers, but not bo th 414 // Paint either the background markers or the foreground markers, but not
415 // both.
411 switch (marker->type()) { 416 switch (marker->type()) {
412 case DocumentMarker::Grammar: 417 case DocumentMarker::Grammar:
413 case DocumentMarker::Spelling: 418 case DocumentMarker::Spelling:
414 if (markerPaintPhase == DocumentMarkerPaintPhase::Background) 419 if (markerPaintPhase == DocumentMarkerPaintPhase::Background)
415 continue; 420 continue;
416 break; 421 break;
417 case DocumentMarker::TextMatch: 422 case DocumentMarker::TextMatch:
418 case DocumentMarker::Composition: 423 case DocumentMarker::Composition:
419 break; 424 break;
420 default: 425 default:
421 continue; 426 continue;
422 } 427 }
423 428
424 if (marker->endOffset() <= m_inlineTextBox.start()) { 429 if (marker->endOffset() <= m_inlineTextBox.start()) {
425 // marker is completely before this run. This might be a marker that sits before the 430 // marker is completely before this run. This might be a marker that sits
426 // first run we draw, or markers that were within runs we skipped due to t runcation. 431 // before the first run we draw, or markers that were within runs we
432 // skipped due to truncation.
427 continue; 433 continue;
428 } 434 }
429 if (marker->startOffset() > m_inlineTextBox.end()) { 435 if (marker->startOffset() > m_inlineTextBox.end()) {
430 // marker is completely after this run, bail. A later run will paint it. 436 // marker is completely after this run, bail. A later run will paint it.
431 break; 437 break;
432 } 438 }
433 439
434 // marker intersects this run. Paint it. 440 // marker intersects this run. Paint it.
435 switch (marker->type()) { 441 switch (marker->type()) {
436 case DocumentMarker::Spelling: 442 case DocumentMarker::Spelling:
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 LayoutPoint startPoint(boxOrigin.x(), boxOrigin.y() - deltaY); 536 LayoutPoint startPoint(boxOrigin.x(), boxOrigin.y() - deltaY);
531 TextRun run = m_inlineTextBox.constructTextRun(style); 537 TextRun run = m_inlineTextBox.constructTextRun(style);
532 538
533 // FIXME: Convert the document markers to float rects. 539 // FIXME: Convert the document markers to float rects.
534 IntRect markerRect = enclosingIntRect(font.selectionRectForText( 540 IntRect markerRect = enclosingIntRect(font.selectionRectForText(
535 run, FloatPoint(startPoint), selHeight, startPosition, endPosition)); 541 run, FloatPoint(startPoint), selHeight, startPosition, endPosition));
536 start = markerRect.x() - startPoint.x(); 542 start = markerRect.x() - startPoint.x();
537 width = LayoutUnit(markerRect.width()); 543 width = LayoutUnit(markerRect.width());
538 } 544 }
539 545
540 // IMPORTANT: The misspelling underline is not considered when calculating the text bounds, so we have to 546 // IMPORTANT: The misspelling underline is not considered when calculating the
541 // make sure to fit within those bounds. This means the top pixel(s) of the u nderline will overlap the 547 // text bounds, so we have to make sure to fit within those bounds. This
542 // bottom pixel(s) of the glyphs in smaller font sizes. The alternatives are to increase the line spacing (bad!!) 548 // means the top pixel(s) of the underline will overlap the bottom pixel(s) of
543 // or decrease the underline thickness. The overlap is actually the most usef ul, and matches what AppKit does. 549 // the glyphs in smaller font sizes. The alternatives are to increase the
544 // So, we generally place the underline at the bottom of the text, but in larg er fonts that's not so good so 550 // line spacing (bad!!) or decrease the underline thickness. The overlap is
545 // we pin to two pixels under the baseline. 551 // actually the most useful, and matches what AppKit does. So, we generally
552 // place the underline at the bottom of the text, but in larger fonts that's
553 // not so good so we pin to two pixels under the baseline.
546 int lineThickness = misspellingLineThickness; 554 int lineThickness = misspellingLineThickness;
547 int baseline = m_inlineTextBox.getLineLayoutItem() 555 int baseline = m_inlineTextBox.getLineLayoutItem()
548 .style(m_inlineTextBox.isFirstLineStyle()) 556 .style(m_inlineTextBox.isFirstLineStyle())
549 ->getFontMetrics() 557 ->getFontMetrics()
550 .ascent(); 558 .ascent();
551 int descent = (m_inlineTextBox.logicalHeight() - baseline).toInt(); 559 int descent = (m_inlineTextBox.logicalHeight() - baseline).toInt();
552 int underlineOffset; 560 int underlineOffset;
553 if (descent <= (lineThickness + 2)) { 561 if (descent <= (lineThickness + 2)) {
554 // Place the underline at the very bottom of the text in small/medium fonts. 562 // Place the underline at the very bottom of the text in small/medium fonts.
555 underlineOffset = (m_inlineTextBox.logicalHeight() - lineThickness).toInt(); 563 underlineOffset = (m_inlineTextBox.logicalHeight() - lineThickness).toInt();
556 } else { 564 } else {
557 // In larger fonts, though, place the underline up near the baseline to prev ent a big gap. 565 // In larger fonts, though, place the underline up near the baseline to
566 // prevent a big gap.
558 underlineOffset = baseline + 2; 567 underlineOffset = baseline + 2;
559 } 568 }
560 context.drawLineForDocumentMarker( 569 context.drawLineForDocumentMarker(
561 FloatPoint((boxOrigin.x() + start).toFloat(), 570 FloatPoint((boxOrigin.x() + start).toFloat(),
562 (boxOrigin.y() + underlineOffset).toFloat()), 571 (boxOrigin.y() + underlineOffset).toFloat()),
563 width.toFloat(), lineStyleForMarkerType(marker->type())); 572 width.toFloat(), lineStyleForMarkerType(marker->type()));
564 } 573 }
565 574
566 template <InlineTextBoxPainter::PaintOptions options> 575 template <InlineTextBoxPainter::PaintOptions options>
567 void InlineTextBoxPainter::paintSelection(GraphicsContext& context, 576 void InlineTextBoxPainter::paintSelection(GraphicsContext& context,
568 const LayoutRect& boxRect, 577 const LayoutRect& boxRect,
569 const ComputedStyle& style, 578 const ComputedStyle& style,
570 const Font& font, 579 const Font& font,
571 Color textColor, 580 Color textColor,
572 LayoutTextCombine* combinedText) { 581 LayoutTextCombine* combinedText) {
573 // See if we have a selection to paint at all. 582 // See if we have a selection to paint at all.
574 int sPos, ePos; 583 int sPos, ePos;
575 m_inlineTextBox.selectionStartEnd(sPos, ePos); 584 m_inlineTextBox.selectionStartEnd(sPos, ePos);
576 if (sPos >= ePos) 585 if (sPos >= ePos)
577 return; 586 return;
578 587
579 Color c = m_inlineTextBox.getLineLayoutItem().selectionBackgroundColor(); 588 Color c = m_inlineTextBox.getLineLayoutItem().selectionBackgroundColor();
580 if (!c.alpha()) 589 if (!c.alpha())
581 return; 590 return;
582 591
583 // If the text color ends up being the same as the selection background, inver t the selection 592 // If the text color ends up being the same as the selection background,
584 // background. 593 // invert the selection background.
585 if (textColor == c) 594 if (textColor == c)
586 c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue()); 595 c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue());
587 596
588 // If the text is truncated, let the thing being painted in the truncation 597 // If the text is truncated, let the thing being painted in the truncation
589 // draw its own highlight. 598 // draw its own highlight.
590 unsigned start = m_inlineTextBox.start(); 599 unsigned start = m_inlineTextBox.start();
591 int length = m_inlineTextBox.len(); 600 int length = m_inlineTextBox.len();
592 bool ltr = m_inlineTextBox.isLeftToRightDirection(); 601 bool ltr = m_inlineTextBox.isLeftToRightDirection();
593 bool flowIsLTR = 602 bool flowIsLTR =
594 m_inlineTextBox.getLineLayoutItem().style()->isLeftToRightDirection(); 603 m_inlineTextBox.getLineLayoutItem().style()->isLeftToRightDirection();
(...skipping 13 matching lines...) Expand all
608 style, string, m_inlineTextBox.getLineLayoutItem().textLength() - 617 style, string, m_inlineTextBox.getLineLayoutItem().textLength() -
609 m_inlineTextBox.start(), 618 m_inlineTextBox.start(),
610 respectHyphen ? &charactersWithHyphen : 0); 619 respectHyphen ? &charactersWithHyphen : 0);
611 if (respectHyphen) 620 if (respectHyphen)
612 ePos = textRun.length(); 621 ePos = textRun.length();
613 622
614 GraphicsContextStateSaver stateSaver(context); 623 GraphicsContextStateSaver stateSaver(context);
615 624
616 if (options == InlineTextBoxPainter::PaintOptions::CombinedText) { 625 if (options == InlineTextBoxPainter::PaintOptions::CombinedText) {
617 ASSERT(combinedText); 626 ASSERT(combinedText);
618 // We can't use the height of m_inlineTextBox because LayoutTextCombine's in lineTextBox is horizontal within vertical flow 627 // We can't use the height of m_inlineTextBox because LayoutTextCombine's
628 // inlineTextBox is horizontal within vertical flow
619 combinedText->transformToInlineCoordinates(context, boxRect, true); 629 combinedText->transformToInlineCoordinates(context, boxRect, true);
620 context.drawHighlightForText(font, textRun, FloatPoint(boxRect.location()), 630 context.drawHighlightForText(font, textRun, FloatPoint(boxRect.location()),
621 boxRect.height().toInt(), c, sPos, ePos); 631 boxRect.height().toInt(), c, sPos, ePos);
622 return; 632 return;
623 } 633 }
624 634
625 LayoutUnit selectionBottom = m_inlineTextBox.root().selectionBottom(); 635 LayoutUnit selectionBottom = m_inlineTextBox.root().selectionBottom();
626 LayoutUnit selectionTop = m_inlineTextBox.root().selectionTop(); 636 LayoutUnit selectionTop = m_inlineTextBox.root().selectionTop();
627 637
628 int deltaY = roundToInt( 638 int deltaY = roundToInt(
629 m_inlineTextBox.getLineLayoutItem().style()->isFlippedLinesWritingMode() 639 m_inlineTextBox.getLineLayoutItem().style()->isFlippedLinesWritingMode()
630 ? selectionBottom - m_inlineTextBox.logicalBottom() 640 ? selectionBottom - m_inlineTextBox.logicalBottom()
631 : m_inlineTextBox.logicalTop() - selectionTop); 641 : m_inlineTextBox.logicalTop() - selectionTop);
632 int selHeight = std::max(0, roundToInt(selectionBottom - selectionTop)); 642 int selHeight = std::max(0, roundToInt(selectionBottom - selectionTop));
633 643
634 FloatPoint localOrigin(boxRect.x().toFloat(), 644 FloatPoint localOrigin(boxRect.x().toFloat(),
635 (boxRect.y() - deltaY).toFloat()); 645 (boxRect.y() - deltaY).toFloat());
636 LayoutRect selectionRect = LayoutRect( 646 LayoutRect selectionRect = LayoutRect(
637 font.selectionRectForText(textRun, localOrigin, selHeight, sPos, ePos)); 647 font.selectionRectForText(textRun, localOrigin, selHeight, sPos, ePos));
638 if (m_inlineTextBox.hasWrappedSelectionNewline() 648 if (m_inlineTextBox.hasWrappedSelectionNewline()
639 // For line breaks, just painting a selection where the line break itself is rendered is sufficient. 649 // For line breaks, just painting a selection where the line break itself
650 // is rendered is sufficient.
640 && !m_inlineTextBox.isLineBreak()) 651 && !m_inlineTextBox.isLineBreak())
641 expandToIncludeNewlineForSelection(selectionRect); 652 expandToIncludeNewlineForSelection(selectionRect);
642 653
643 // Line breaks report themselves as having zero width for layout purposes, 654 // Line breaks report themselves as having zero width for layout purposes,
644 // and so will end up positioned at (0, 0), even though we paint their 655 // and so will end up positioned at (0, 0), even though we paint their
645 // selection highlight with character width. For RTL then, we have to 656 // selection highlight with character width. For RTL then, we have to
646 // explicitly shift the selection rect over to paint in the right location. 657 // explicitly shift the selection rect over to paint in the right location.
647 if (!m_inlineTextBox.isLeftToRightDirection() && 658 if (!m_inlineTextBox.isLeftToRightDirection() &&
648 m_inlineTextBox.isLineBreak()) 659 m_inlineTextBox.isLineBreak())
649 selectionRect.move(-selectionRect.width(), LayoutUnit()); 660 selectionRect.move(-selectionRect.width(), LayoutUnit());
(...skipping 19 matching lines...) Expand all
669 const FontMetrics& fontMetrics, 680 const FontMetrics& fontMetrics,
670 const InlineTextBox* inlineTextBox, 681 const InlineTextBox* inlineTextBox,
671 const float textDecorationThickness) { 682 const float textDecorationThickness) {
672 // Compute the gap between the font and the underline. Use at least one 683 // Compute the gap between the font and the underline. Use at least one
673 // pixel gap, if underline is thick then use a bigger gap. 684 // pixel gap, if underline is thick then use a bigger gap.
674 int gap = 0; 685 int gap = 0;
675 686
676 // Underline position of zero means draw underline on Baseline Position, 687 // Underline position of zero means draw underline on Baseline Position,
677 // in Blink we need at least 1-pixel gap to adding following check. 688 // in Blink we need at least 1-pixel gap to adding following check.
678 // Positive underline Position means underline should be drawn above baselin e 689 // Positive underline Position means underline should be drawn above baselin e
679 // and negative value means drawing below baseline, negating the value as in B link 690 // and negative value means drawing below baseline, negating the value as in
680 // downward Y-increases. 691 // Blink downward Y-increases.
681 692
682 if (fontMetrics.underlinePosition()) 693 if (fontMetrics.underlinePosition())
683 gap = -fontMetrics.underlinePosition(); 694 gap = -fontMetrics.underlinePosition();
684 else 695 else
685 gap = std::max<int>(1, ceilf(textDecorationThickness / 2.f)); 696 gap = std::max<int>(1, ceilf(textDecorationThickness / 2.f));
686 697
687 // FIXME: We support only horizontal text for now. 698 // FIXME: We support only horizontal text for now.
688 switch (underlinePosition) { 699 switch (underlinePosition) {
689 case TextUnderlinePositionAuto: 700 case TextUnderlinePositionAuto:
690 return fontMetrics.ascent() + 701 return fontMetrics.ascent() +
691 gap; // Position underline near the alphabetic baseline. 702 gap; // Position underline near the alphabetic baseline.
692 case TextUnderlinePositionUnder: { 703 case TextUnderlinePositionUnder: {
693 // Position underline relative to the under edge of the lowest element's c ontent box. 704 // Position underline relative to the under edge of the lowest element's
705 // content box.
694 const LayoutUnit offset = 706 const LayoutUnit offset =
695 inlineTextBox->root().maxLogicalTop() - inlineTextBox->logicalTop(); 707 inlineTextBox->root().maxLogicalTop() - inlineTextBox->logicalTop();
696 if (offset > 0) 708 if (offset > 0)
697 return (inlineTextBox->logicalHeight() + gap + offset).toInt(); 709 return (inlineTextBox->logicalHeight() + gap + offset).toInt();
698 return (inlineTextBox->logicalHeight() + gap).toInt(); 710 return (inlineTextBox->logicalHeight() + gap).toInt();
699 } 711 }
700 } 712 }
701 713
702 ASSERT_NOT_REACHED(); 714 ASSERT_NOT_REACHED();
703 return fontMetrics.ascent() + gap; 715 return fontMetrics.ascent() + gap;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
753 // Each Bezier curve starts at the same pixel that the previous one 765 // Each Bezier curve starts at the same pixel that the previous one
754 // ended. We need to subtract (stepCount - 1) pixels when calculating the 766 // ended. We need to subtract (stepCount - 1) pixels when calculating the
755 // length covered to account for that. 767 // length covered to account for that.
756 float uncoveredLength = length - (stepCount * step - (stepCount - 1)); 768 float uncoveredLength = length - (stepCount * step - (stepCount - 1));
757 float adjustment = uncoveredLength / stepCount; 769 float adjustment = uncoveredLength / stepCount;
758 step += adjustment; 770 step += adjustment;
759 controlPointDistance += adjustment; 771 controlPointDistance += adjustment;
760 } 772 }
761 773
762 /* 774 /*
763 * Draw one cubic Bezier curve and repeat the same pattern long the the decorati on's axis. 775 * Draw one cubic Bezier curve and repeat the same pattern long the the
764 * The start point (p1), controlPoint1, controlPoint2 and end point (p2) of the Bezier curve 776 * decoration's axis. The start point (p1), controlPoint1, controlPoint2 and
765 * form a diamond shape: 777 * end point (p2) of the Bezier curve form a diamond shape:
766 * 778 *
767 * step 779 * step
768 * |-----------| 780 * |-----------|
769 * 781 *
770 * controlPoint1 782 * controlPoint1
771 * + 783 * +
772 * 784 *
773 * 785 *
774 * . . 786 * . .
775 * . . 787 * . .
(...skipping 14 matching lines...) Expand all
790 FloatPoint p1, 802 FloatPoint p1,
791 FloatPoint p2, 803 FloatPoint p2,
792 float strokeThickness) { 804 float strokeThickness) {
793 context.adjustLineToPixelBoundaries(p1, p2, strokeThickness, 805 context.adjustLineToPixelBoundaries(p1, p2, strokeThickness,
794 context.getStrokeStyle()); 806 context.getStrokeStyle());
795 807
796 Path path; 808 Path path;
797 path.moveTo(p1); 809 path.moveTo(p1);
798 810
799 // Distance between decoration's axis and Bezier curve's control points. 811 // Distance between decoration's axis and Bezier curve's control points.
800 // The height of the curve is based on this distance. Use a minimum of 6 pixel s distance since 812 // The height of the curve is based on this distance. Use a minimum of 6
801 // the actual curve passes approximately at half of that distance, that is 3 p ixels. 813 // pixels distance since the actual curve passes approximately at half of that
802 // The minimum height of the curve is also approximately 3 pixels. Increases t he curve's height 814 // distance, that is 3 pixels. The minimum height of the curve is also
815 // approximately 3 pixels. Increases the curve's height
803 // as strockThickness increases to make the curve looks better. 816 // as strockThickness increases to make the curve looks better.
804 float controlPointDistance = 3 * std::max<float>(2, strokeThickness); 817 float controlPointDistance = 3 * std::max<float>(2, strokeThickness);
805 818
806 // Increment used to form the diamond shape between start point (p1), control 819 // Increment used to form the diamond shape between start point (p1), control
807 // points and end point (p2) along the axis of the decoration. Makes the 820 // points and end point (p2) along the axis of the decoration. Makes the
808 // curve wider as strockThickness increases to make the curve looks better. 821 // curve wider as strockThickness increases to make the curve looks better.
809 float step = 2 * std::max<float>(2, strokeThickness); 822 float step = 2 * std::max<float>(2, strokeThickness);
810 823
811 bool isVerticalLine = (p1.x() == p2.x()); 824 bool isVerticalLine = (p1.x() == p2.x());
812 825
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
935 textBoxLayoutObject.getTextDecorations(deco, underline, overline, 948 textBoxLayoutObject.getTextDecorations(deco, underline, overline,
936 linethrough, true, true); 949 linethrough, true, true);
937 950
938 // Use a special function for underlines to get the positioning exactly right. 951 // Use a special function for underlines to get the positioning exactly right.
939 bool isPrinting = paintInfo.isPrinting(); 952 bool isPrinting = paintInfo.isPrinting();
940 953
941 const ComputedStyle& styleToUse = 954 const ComputedStyle& styleToUse =
942 textBoxLayoutObject.styleRef(m_inlineTextBox.isFirstLineStyle()); 955 textBoxLayoutObject.styleRef(m_inlineTextBox.isFirstLineStyle());
943 float baseline = styleToUse.getFontMetrics().ascent(); 956 float baseline = styleToUse.getFontMetrics().ascent();
944 957
945 // Set the thick of the line to be 10% (or something else ?)of the computed fo nt size and not less than 1px. 958 // Set the thick of the line to be 10% (or something else ?)of the computed
946 // Using computedFontSize should take care of zoom as well. 959 // font size and not less than 1px. Using computedFontSize should take care
960 // of zoom as well.
947 961
948 // Update Underline thickness, in case we have Faulty Font Metrics calculating underline thickness by old method. 962 // Update Underline thickness, in case we have Faulty Font Metrics calculating
963 // underline thickness by old method.
949 float textDecorationThickness = 964 float textDecorationThickness =
950 styleToUse.getFontMetrics().underlineThickness(); 965 styleToUse.getFontMetrics().underlineThickness();
951 int fontHeightInt = (int)(styleToUse.getFontMetrics().floatHeight() + 0.5); 966 int fontHeightInt = (int)(styleToUse.getFontMetrics().floatHeight() + 0.5);
952 if ((textDecorationThickness == 0.f) || 967 if ((textDecorationThickness == 0.f) ||
953 (textDecorationThickness >= (fontHeightInt >> 1))) 968 (textDecorationThickness >= (fontHeightInt >> 1)))
954 textDecorationThickness = 969 textDecorationThickness =
955 std::max(1.f, styleToUse.computedFontSize() / 10.f); 970 std::max(1.f, styleToUse.computedFontSize() / 10.f);
956 971
957 context.setStrokeThickness(textDecorationThickness); 972 context.setStrokeThickness(textDecorationThickness);
958 973
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1019 } else { 1034 } else {
1020 unsigned paintFrom = ltr == flowIsLTR ? paintStart : paintEnd; 1035 unsigned paintFrom = ltr == flowIsLTR ? paintStart : paintEnd;
1021 unsigned paintLength = 1036 unsigned paintLength =
1022 ltr == flowIsLTR 1037 ltr == flowIsLTR
1023 ? paintEnd - paintStart 1038 ? paintEnd - paintStart
1024 : m_inlineTextBox.start() + m_inlineTextBox.len() - paintEnd; 1039 : m_inlineTextBox.start() + m_inlineTextBox.len() - paintEnd;
1025 width = m_inlineTextBox.getLineLayoutItem().width( 1040 width = m_inlineTextBox.getLineLayoutItem().width(
1026 paintFrom, paintLength, LayoutUnit(m_inlineTextBox.textPos() + start), 1041 paintFrom, paintLength, LayoutUnit(m_inlineTextBox.textPos() + start),
1027 flowIsLTR ? LTR : RTL, m_inlineTextBox.isFirstLineStyle()); 1042 flowIsLTR ? LTR : RTL, m_inlineTextBox.isFirstLineStyle());
1028 } 1043 }
1029 // In RTL mode, start and width are computed from the right end of the text bo x: 1044 // In RTL mode, start and width are computed from the right end of the text
1030 // starting at |logicalWidth| - |start| and continuing left by |width| to 1045 // box: starting at |logicalWidth| - |start| and continuing left by |width| to
1031 // |logicalWidth| - |start| - |width|. We will draw that line, but 1046 // |logicalWidth| - |start| - |width|. We will draw that line, but backwards:
1032 // backwards: |logicalWidth| - |start| - |width| to |logicalWidth| - |start|. 1047 // |logicalWidth| - |start| - |width| to |logicalWidth| - |start|.
1033 if (!flowIsLTR) 1048 if (!flowIsLTR)
1034 start = m_inlineTextBox.logicalWidth().toFloat() - width - start; 1049 start = m_inlineTextBox.logicalWidth().toFloat() - width - start;
1035 1050
1036 // Thick marked text underlines are 2px thick as long as there is room for the 2px line under the baseline. 1051 // Thick marked text underlines are 2px thick as long as there is room for the
1037 // All other marked text underlines are 1px thick. 1052 // 2px line under the baseline. All other marked text underlines are 1px
1038 // If there's not enough space the underline will touch or overlap characters. 1053 // thick. If there's not enough space the underline will touch or overlap
1054 // characters.
1039 int lineThickness = 1; 1055 int lineThickness = 1;
1040 int baseline = m_inlineTextBox.getLineLayoutItem() 1056 int baseline = m_inlineTextBox.getLineLayoutItem()
1041 .style(m_inlineTextBox.isFirstLineStyle()) 1057 .style(m_inlineTextBox.isFirstLineStyle())
1042 ->getFontMetrics() 1058 ->getFontMetrics()
1043 .ascent(); 1059 .ascent();
1044 if (underline.thick() && m_inlineTextBox.logicalHeight() - baseline >= 2) 1060 if (underline.thick() && m_inlineTextBox.logicalHeight() - baseline >= 2)
1045 lineThickness = 2; 1061 lineThickness = 2;
1046 1062
1047 // We need to have some space between underlines of subsequent clauses, becaus e some input methods do not use different underline styles for those. 1063 // We need to have some space between underlines of subsequent clauses,
1048 // We make each line shorter, which has a harmless side effect of shortening t he first and last clauses, too. 1064 // because some input methods do not use different underline styles for those.
1065 // We make each line shorter, which has a harmless side effect of shortening
1066 // the first and last clauses, too.
1049 start += 1; 1067 start += 1;
1050 width -= 2; 1068 width -= 2;
1051 1069
1052 context.setStrokeColor(underline.color()); 1070 context.setStrokeColor(underline.color());
1053 context.setStrokeThickness(lineThickness); 1071 context.setStrokeThickness(lineThickness);
1054 context.drawLineForText( 1072 context.drawLineForText(
1055 FloatPoint( 1073 FloatPoint(
1056 boxOrigin.x() + start, 1074 boxOrigin.x() + start,
1057 (boxOrigin.y() + m_inlineTextBox.logicalHeight() - lineThickness) 1075 (boxOrigin.y() + m_inlineTextBox.logicalHeight() - lineThickness)
1058 .toFloat()), 1076 .toFloat()),
1059 width, m_inlineTextBox.getLineLayoutItem().document().printing()); 1077 width, m_inlineTextBox.getLineLayoutItem().document().printing());
1060 } 1078 }
1061 1079
1062 void InlineTextBoxPainter::paintTextMatchMarkerForeground( 1080 void InlineTextBoxPainter::paintTextMatchMarkerForeground(
1063 const PaintInfo& paintInfo, 1081 const PaintInfo& paintInfo,
1064 const LayoutPoint& boxOrigin, 1082 const LayoutPoint& boxOrigin,
1065 DocumentMarker* marker, 1083 DocumentMarker* marker,
1066 const ComputedStyle& style, 1084 const ComputedStyle& style,
1067 const Font& font) { 1085 const Font& font) {
1068 if (!inlineLayoutObject().frame()->editor().markedTextMatchesAreHighlighted()) 1086 if (!inlineLayoutObject().frame()->editor().markedTextMatchesAreHighlighted())
1069 return; 1087 return;
1070 1088
1071 // TODO(ramya.v): Extract this into a helper function and share many copies of this code. 1089 // TODO(ramya.v): Extract this into a helper function and share many copies of
1090 // this code.
1072 int sPos = 1091 int sPos =
1073 std::max(marker->startOffset() - m_inlineTextBox.start(), (unsigned)0); 1092 std::max(marker->startOffset() - m_inlineTextBox.start(), (unsigned)0);
1074 int ePos = std::min(marker->endOffset() - m_inlineTextBox.start(), 1093 int ePos = std::min(marker->endOffset() - m_inlineTextBox.start(),
1075 m_inlineTextBox.len()); 1094 m_inlineTextBox.len());
1076 TextRun run = m_inlineTextBox.constructTextRun(style); 1095 TextRun run = m_inlineTextBox.constructTextRun(style);
1077 1096
1078 Color textColor = 1097 Color textColor =
1079 LayoutTheme::theme().platformTextSearchColor(marker->activeMatch()); 1098 LayoutTheme::theme().platformTextSearchColor(marker->activeMatch());
1080 if (style.visitedDependentColor(CSSPropertyColor) == textColor) 1099 if (style.visitedDependentColor(CSSPropertyColor) == textColor)
1081 return; 1100 return;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1119 GraphicsContextStateSaver stateSaver(context); 1138 GraphicsContextStateSaver stateSaver(context);
1120 1139
1121 LayoutRect boxRect(boxOrigin, LayoutSize(m_inlineTextBox.logicalWidth(), 1140 LayoutRect boxRect(boxOrigin, LayoutSize(m_inlineTextBox.logicalWidth(),
1122 m_inlineTextBox.logicalHeight())); 1141 m_inlineTextBox.logicalHeight()));
1123 context.clip(FloatRect(boxRect)); 1142 context.clip(FloatRect(boxRect));
1124 context.drawHighlightForText(font, run, FloatPoint(boxOrigin), 1143 context.drawHighlightForText(font, run, FloatPoint(boxOrigin),
1125 boxRect.height().toInt(), color, sPos, ePos); 1144 boxRect.height().toInt(), color, sPos, ePos);
1126 } 1145 }
1127 1146
1128 } // namespace blink 1147 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698