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

Side by Side Diff: Source/core/rendering/InlineTextBox.cpp

Issue 472083002: Move the shadows out of paintTextWithShadows. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: GraphicsContextStateSaver& Created 6 years, 4 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
« no previous file with comments | « Source/core/rendering/InlineTextBox.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * (C) 1999 Lars Knoll (knoll@kde.org) 2 * (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 2000 Dirk Mueller (mueller@kde.org) 3 * (C) 2000 Dirk Mueller (mueller@kde.org)
4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r ights reserved. 4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r ights reserved.
5 * 5 *
6 * This library is free software; you can redistribute it and/or 6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public 7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either 8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version. 9 * version 2 of the License, or (at your option) any later version.
10 * 10 *
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 return -1; 322 return -1;
323 } 323 }
324 324
325 static Color textColorForWhiteBackground(Color textColor) 325 static Color textColorForWhiteBackground(Color textColor)
326 { 326 {
327 int distanceFromWhite = differenceSquared(textColor, Color::white); 327 int distanceFromWhite = differenceSquared(textColor, Color::white);
328 // semi-arbitrarily chose 65025 (255^2) value here after a few tests; 328 // semi-arbitrarily chose 65025 (255^2) value here after a few tests;
329 return distanceFromWhite > 65025 ? textColor : textColor.dark(); 329 return distanceFromWhite > 65025 ? textColor : textColor.dark();
330 } 330 }
331 331
332 static void updateGraphicsContext(GraphicsContext* context, const Color& fillCol or, const Color& strokeColor, float strokeThickness)
333 {
334 TextDrawingModeFlags mode = context->textDrawingMode();
335 if (strokeThickness > 0) {
336 TextDrawingModeFlags newMode = mode | TextModeStroke;
337 if (mode != newMode) {
338 context->setTextDrawingMode(newMode);
339 mode = newMode;
340 }
341 }
342
343 if (mode & TextModeFill && fillColor != context->fillColor())
344 context->setFillColor(fillColor);
345
346 if (mode & TextModeStroke) {
347 if (strokeColor != context->strokeColor())
348 context->setStrokeColor(strokeColor);
349 if (strokeThickness != context->strokeThickness())
350 context->setStrokeThickness(strokeThickness);
351 }
352 }
353
354 bool InlineTextBox::isLineBreak() const 332 bool InlineTextBox::isLineBreak() const
355 { 333 {
356 return renderer().isBR() || (renderer().style()->preserveNewline() && len() == 1 && (*renderer().text().impl())[start()] == '\n'); 334 return renderer().isBR() || (renderer().style()->preserveNewline() && len() == 1 && (*renderer().text().impl())[start()] == '\n');
357 } 335 }
358 336
359 bool InlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re sult, const HitTestLocation& locationInContainer, const LayoutPoint& accumulated Offset, LayoutUnit /* lineTop */, LayoutUnit /*lineBottom*/) 337 bool InlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re sult, const HitTestLocation& locationInContainer, const LayoutPoint& accumulated Offset, LayoutUnit /* lineTop */, LayoutUnit /*lineBottom*/)
360 { 338 {
361 if (isLineBreak()) 339 if (isLineBreak())
362 return false; 340 return false;
363 341
364 FloatPoint boxOrigin = locationIncludingFlipping(); 342 FloatPoint boxOrigin = locationIncludingFlipping();
365 boxOrigin.moveBy(accumulatedOffset); 343 boxOrigin.moveBy(accumulatedOffset);
366 FloatRect rect(boxOrigin, size()); 344 FloatRect rect(boxOrigin, size());
367 if (m_truncation != cFullTruncation && visibleToHitTestRequest(request) && l ocationInContainer.intersects(rect)) { 345 if (m_truncation != cFullTruncation && visibleToHitTestRequest(request) && l ocationInContainer.intersects(rect)) {
368 renderer().updateHitTestResult(result, flipForWritingMode(locationInCont ainer.point() - toLayoutSize(accumulatedOffset))); 346 renderer().updateHitTestResult(result, flipForWritingMode(locationInCont ainer.point() - toLayoutSize(accumulatedOffset)));
369 if (!result.addNodeToRectBasedTestResult(renderer().node(), request, loc ationInContainer, rect)) 347 if (!result.addNodeToRectBasedTestResult(renderer().node(), request, loc ationInContainer, rect))
370 return true; 348 return true;
371 } 349 }
372 return false; 350 return false;
373 } 351 }
374 352
375 static void paintTextWithShadows(GraphicsContext* context,
376 const Font& font, const TextRun& textRun,
377 const AtomicString& emphasisMark, int emphasisMarkOffset,
378 int startOffset, int endOffset, int truncationPoint,
379 const FloatPoint& textOrigin, const FloatRect& boxRect,
380 const ShadowList* shadowList, bool horizontal)
381 {
382 // Text shadows are disabled when printing. http://crbug.com/258321
383 bool hasShadow = shadowList && !context->printing();
384 if (hasShadow)
385 context->setDrawLooper(shadowList->createDrawLooper(DrawLooperBuilder::S hadowIgnoresAlpha, horizontal));
386
387 TextRunPaintInfo textRunPaintInfo(textRun);
388 textRunPaintInfo.bounds = boxRect;
389 if (startOffset <= endOffset) {
390 textRunPaintInfo.from = startOffset;
391 textRunPaintInfo.to = endOffset;
392 if (emphasisMark.isEmpty())
393 context->drawText(font, textRunPaintInfo, textOrigin);
394 else
395 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisMark, tex tOrigin + IntSize(0, emphasisMarkOffset));
396 } else {
397 if (endOffset > 0) {
398 textRunPaintInfo.from = 0;
399 textRunPaintInfo.to = endOffset;
400 if (emphasisMark.isEmpty())
401 context->drawText(font, textRunPaintInfo, textOrigin);
402 else
403 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisMark, textOrigin + IntSize(0, emphasisMarkOffset));
404 }
405 if (startOffset < truncationPoint) {
406 textRunPaintInfo.from = startOffset;
407 textRunPaintInfo.to = truncationPoint;
408 if (emphasisMark.isEmpty())
409 context->drawText(font, textRunPaintInfo, textOrigin);
410 else
411 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisMark, textOrigin + IntSize(0, emphasisMarkOffset));
412 }
413 }
414
415 if (hasShadow)
416 context->clearDrawLooper();
417 }
418
419 static void paintEmphasisMark(GraphicsContext* context,
420 const AtomicString& emphasisMark, int emphasisMarkOffset,
421 int startOffset, int endOffset, int paintRunLength,
422 const Font& font, Color emphasisMarkColor, Color textStrokeColor, float text StrokeWidth, const ShadowList* textShadow,
423 RenderCombineText* combinedText, const TextRun& textRun,
424 const FloatPoint& textOrigin, const FloatRect& boxRect, bool horizontal)
425 {
426 ASSERT(!emphasisMark.isEmpty());
427 updateGraphicsContext(context, emphasisMarkColor, textStrokeColor, textStrok eWidth);
428
429 if (combinedText) {
430 DEFINE_STATIC_LOCAL(TextRun, objectReplacementCharacterTextRun, (&object ReplacementCharacter, 1));
431 FloatPoint emphasisMarkTextOrigin(boxRect.x() + boxRect.width() / 2, box Rect.y() + font.fontMetrics().ascent());
432 context->concatCTM(InlineTextBox::rotation(boxRect, InlineTextBox::Clock wise));
433 paintTextWithShadows(context, combinedText->originalFont(), objectReplac ementCharacterTextRun, emphasisMark, emphasisMarkOffset, 0, 1, 1, emphasisMarkTe xtOrigin, boxRect, textShadow, horizontal);
434 context->concatCTM(InlineTextBox::rotation(boxRect, InlineTextBox::Count erclockwise));
435 } else {
436 paintTextWithShadows(context, font, textRun, emphasisMark, emphasisMarkO ffset, startOffset, endOffset, paintRunLength, textOrigin, boxRect, textShadow, horizontal);
437 }
438 }
439
440 bool InlineTextBox::getEmphasisMarkPosition(RenderStyle* style, TextEmphasisPosi tion& emphasisPosition) const 353 bool InlineTextBox::getEmphasisMarkPosition(RenderStyle* style, TextEmphasisPosi tion& emphasisPosition) const
441 { 354 {
442 // This function returns true if there are text emphasis marks and they are suppressed by ruby text. 355 // This function returns true if there are text emphasis marks and they are suppressed by ruby text.
443 if (style->textEmphasisMark() == TextEmphasisMarkNone) 356 if (style->textEmphasisMark() == TextEmphasisMarkNone)
444 return false; 357 return false;
445 358
446 emphasisPosition = style->textEmphasisPosition(); 359 emphasisPosition = style->textEmphasisPosition();
447 if (emphasisPosition == TextEmphasisPositionUnder) 360 if (emphasisPosition == TextEmphasisPositionUnder)
448 return true; // Ruby text is always over, so it cannot suppress emphasis marks under. 361 return true; // Ruby text is always over, so it cannot suppress emphasis marks under.
449 362
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 } 449 }
537 450
538 // Text shadows are disabled when printing. http://crbug.com/258321 451 // Text shadows are disabled when printing. http://crbug.com/258321
539 if (isPrinting) 452 if (isPrinting)
540 selectionStyle.shadow = 0; 453 selectionStyle.shadow = 0;
541 } 454 }
542 455
543 return selectionStyle; 456 return selectionStyle;
544 } 457 }
545 458
459 void updateGraphicsContext(GraphicsContext* context, const TextPaintingStyle& te xtStyle, bool horizontal, GraphicsContextStateSaver& stateSaver)
460 {
461 TextDrawingModeFlags mode = context->textDrawingMode();
462 if (textStyle.strokeWidth > 0) {
463 TextDrawingModeFlags newMode = mode | TextModeStroke;
464 if (mode != newMode) {
465 if (!stateSaver.saved())
466 stateSaver.save();
467 context->setTextDrawingMode(newMode);
468 mode = newMode;
469 }
470 }
471
472 if (mode & TextModeFill && textStyle.fillColor != context->fillColor())
473 context->setFillColor(textStyle.fillColor);
474
475 if (mode & TextModeStroke) {
476 if (textStyle.strokeColor != context->strokeColor())
477 context->setStrokeColor(textStyle.strokeColor);
478 if (textStyle.strokeWidth != context->strokeThickness())
479 context->setStrokeThickness(textStyle.strokeWidth);
480 }
481
482 // Text shadows are disabled when printing. http://crbug.com/258321
483 if (textStyle.shadow && !context->printing()) {
484 if (!stateSaver.saved())
485 stateSaver.save();
486 context->setDrawLooper(textStyle.shadow->createDrawLooper(DrawLooperBuil der::ShadowIgnoresAlpha, horizontal));
487 }
488 }
489
490 void paintText(GraphicsContext* context,
491 const Font& font, const TextRun& textRun,
492 const AtomicString& emphasisMark, int emphasisMarkOffset,
493 int startOffset, int endOffset, int truncationPoint,
494 const FloatPoint& textOrigin, const FloatRect& boxRect)
495 {
496 TextRunPaintInfo textRunPaintInfo(textRun);
497 textRunPaintInfo.bounds = boxRect;
498 if (startOffset <= endOffset) {
499 textRunPaintInfo.from = startOffset;
500 textRunPaintInfo.to = endOffset;
501 if (emphasisMark.isEmpty())
502 context->drawText(font, textRunPaintInfo, textOrigin);
503 else
504 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisMark, tex tOrigin + IntSize(0, emphasisMarkOffset));
505 } else {
506 if (endOffset > 0) {
507 textRunPaintInfo.from = 0;
508 textRunPaintInfo.to = endOffset;
509 if (emphasisMark.isEmpty())
510 context->drawText(font, textRunPaintInfo, textOrigin);
511 else
512 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisMark, textOrigin + IntSize(0, emphasisMarkOffset));
513 }
514 if (startOffset < truncationPoint) {
515 textRunPaintInfo.from = startOffset;
516 textRunPaintInfo.to = truncationPoint;
517 if (emphasisMark.isEmpty())
518 context->drawText(font, textRunPaintInfo, textOrigin);
519 else
520 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisMark, textOrigin + IntSize(0, emphasisMarkOffset));
521 }
522 }
523 }
524
525 inline void paintEmphasisMark(GraphicsContext* context,
526 const AtomicString& emphasisMark, int emphasisMarkOffset,
527 int startOffset, int endOffset, int paintRunLength,
528 const Font& font, RenderCombineText* combinedText, const TextRun& textRun,
529 const FloatPoint& textOrigin, const FloatRect& boxRect)
530 {
531 ASSERT(!emphasisMark.isEmpty());
532
533 if (combinedText) {
534 DEFINE_STATIC_LOCAL(TextRun, objectReplacementCharacterTextRun, (&object ReplacementCharacter, 1));
535 FloatPoint emphasisMarkTextOrigin(boxRect.x() + boxRect.width() / 2, box Rect.y() + font.fontMetrics().ascent());
536 context->concatCTM(InlineTextBox::rotation(boxRect, InlineTextBox::Clock wise));
537 paintText(context, combinedText->originalFont(), objectReplacementCharac terTextRun, emphasisMark, emphasisMarkOffset, 0, 1, 1, emphasisMarkTextOrigin, b oxRect);
538 context->concatCTM(InlineTextBox::rotation(boxRect, InlineTextBox::Count erclockwise));
539 } else {
540 paintText(context, font, textRun, emphasisMark, emphasisMarkOffset, star tOffset, endOffset, paintRunLength, textOrigin, boxRect);
541 }
542 }
543
544 void paintTextWithEmphasisMark(
545 GraphicsContext* context, const Font& font, const TextPaintingStyle& textSty le, const TextRun& textRun,
546 const AtomicString& emphasisMark, int emphasisMarkOffset, int startOffset, i nt endOffset, int length,
547 RenderCombineText* combinedText, const FloatPoint& textOrigin, const FloatRe ct& boxRect, bool horizontal)
548 {
549 GraphicsContextStateSaver stateSaver(*context, false);
550 updateGraphicsContext(context, textStyle, horizontal, stateSaver);
551 paintText(context, font, textRun, nullAtom, 0, startOffset, endOffset, lengt h, textOrigin, boxRect);
552
553 if (!emphasisMark.isEmpty()) {
554 if (textStyle.emphasisMarkColor != textStyle.fillColor)
555 context->setFillColor(textStyle.emphasisMarkColor);
556 paintEmphasisMark(context, emphasisMark, emphasisMarkOffset, startOffset , endOffset, length, font, combinedText, textRun, textOrigin, boxRect);
557 }
558 }
559
546 } // namespace 560 } // namespace
547 561
548 void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit /*lineTop*/, LayoutUnit /*lineBottom*/) 562 void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit /*lineTop*/, LayoutUnit /*lineBottom*/)
549 { 563 {
550 if (isLineBreak() || !paintInfo.shouldPaintWithinRoot(&renderer()) || render er().style()->visibility() != VISIBLE 564 if (isLineBreak() || !paintInfo.shouldPaintWithinRoot(&renderer()) || render er().style()->visibility() != VISIBLE
551 || m_truncation == cFullTruncation || paintInfo.phase == PaintPhaseOutli ne || !m_len) 565 || m_truncation == cFullTruncation || paintInfo.phase == PaintPhaseOutli ne || !m_len)
552 return; 566 return;
553 567
554 ASSERT(paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintP haseChildOutlines); 568 ASSERT(paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintP haseChildOutlines);
555 569
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
680 emphasisMarkOffset = emphasisMarkPosition == TextEmphasisPositionOver ? -font.fontMetrics().ascent() - font.emphasisMarkDescent(emphasisMark) : font.fon tMetrics().descent() + font.emphasisMarkAscent(emphasisMark); 694 emphasisMarkOffset = emphasisMarkPosition == TextEmphasisPositionOver ? -font.fontMetrics().ascent() - font.emphasisMarkDescent(emphasisMark) : font.fon tMetrics().descent() + font.emphasisMarkAscent(emphasisMark);
681 695
682 if (!paintSelectedTextOnly) { 696 if (!paintSelectedTextOnly) {
683 // FIXME: Truncate right-to-left text correctly. 697 // FIXME: Truncate right-to-left text correctly.
684 int startOffset = 0; 698 int startOffset = 0;
685 int endOffset = length; 699 int endOffset = length;
686 if (paintSelectedTextSeparately && ePos > sPos) { 700 if (paintSelectedTextSeparately && ePos > sPos) {
687 startOffset = ePos; 701 startOffset = ePos;
688 endOffset = sPos; 702 endOffset = sPos;
689 } 703 }
690 704 paintTextWithEmphasisMark(context, font, textStyle, textRun, emphasisMar k, emphasisMarkOffset, startOffset, endOffset, length, combinedText, textOrigin, boxRect, isHorizontal());
691 // For stroked painting, we have to change the text drawing mode. It's probably dangerous to leave that mutated as a side
692 // effect, so only when we know we're stroking, do a save/restore.
693 GraphicsContextStateSaver stateSaver(*context, textStyle.strokeWidth > 0 );
694
695 updateGraphicsContext(context, textStyle.fillColor, textStyle.strokeColo r, textStyle.strokeWidth);
696 paintTextWithShadows(context, font, textRun, nullAtom, 0, startOffset, e ndOffset, length, textOrigin, boxRect, textStyle.shadow, isHorizontal());
697
698 if (!emphasisMark.isEmpty())
699 paintEmphasisMark(context, emphasisMark, emphasisMarkOffset, startOf fset, endOffset, length, font, textStyle.emphasisMarkColor, textStyle.strokeColo r, textStyle.strokeWidth, textStyle.shadow, combinedText, textRun, textOrigin, b oxRect, isHorizontal());
700 } 705 }
701 706
702 if ((paintSelectedTextOnly || paintSelectedTextSeparately) && sPos < ePos) { 707 if ((paintSelectedTextOnly || paintSelectedTextSeparately) && sPos < ePos) {
703 // paint only the text that is selected 708 // paint only the text that is selected
704 GraphicsContextStateSaver stateSaver(*context, selectionStyle.strokeWidt h > 0); 709 paintTextWithEmphasisMark(context, font, selectionStyle, textRun, emphas isMark, emphasisMarkOffset, sPos, ePos, length, combinedText, textOrigin, boxRec t, isHorizontal());
705
706 updateGraphicsContext(context, selectionStyle.fillColor, selectionStyle. strokeColor, selectionStyle.strokeWidth);
707 paintTextWithShadows(context, font, textRun, nullAtom, 0, sPos, ePos, le ngth, textOrigin, boxRect, selectionStyle.shadow, isHorizontal());
708
709 if (!emphasisMark.isEmpty())
710 paintEmphasisMark(context, emphasisMark, emphasisMarkOffset, sPos, e Pos, length, font, selectionStyle.emphasisMarkColor, selectionStyle.strokeColor, textStyle.strokeWidth, selectionStyle.shadow, combinedText, textRun, textOrigin , boxRect, isHorizontal());
711 } 710 }
712 711
713 // Paint decorations 712 // Paint decorations
714 TextDecoration textDecorations = styleToUse->textDecorationsInEffect(); 713 TextDecoration textDecorations = styleToUse->textDecorationsInEffect();
715 if (textDecorations != TextDecorationNone && paintInfo.phase != PaintPhaseSe lection) { 714 if (textDecorations != TextDecorationNone && !paintSelectedTextOnly) {
716 updateGraphicsContext(context, textStyle.fillColor, textStyle.strokeColo r, textStyle.strokeWidth); 715 GraphicsContextStateSaver stateSaver(*context, false);
716 updateGraphicsContext(context, textStyle, isHorizontal(), stateSaver);
717 if (combinedText) 717 if (combinedText)
718 context->concatCTM(rotation(boxRect, Clockwise)); 718 context->concatCTM(rotation(boxRect, Clockwise));
719 paintDecoration(context, boxOrigin, textDecorations, textStyle.shadow); 719 paintDecoration(context, boxOrigin, textDecorations);
720 if (combinedText) 720 if (combinedText)
721 context->concatCTM(rotation(boxRect, Counterclockwise)); 721 context->concatCTM(rotation(boxRect, Counterclockwise));
722 } 722 }
723 723
724 if (paintInfo.phase == PaintPhaseForeground) { 724 if (paintInfo.phase == PaintPhaseForeground) {
725 paintDocumentMarkers(context, boxOrigin, styleToUse, font, false); 725 paintDocumentMarkers(context, boxOrigin, styleToUse, font, false);
726 726
727 // Paint custom underlines for compositions. 727 // Paint custom underlines for compositions.
728 if (useCustomUnderlines) { 728 if (useCustomUnderlines) {
729 const Vector<CompositionUnderline>& underlines = renderer().frame()- >inputMethodController().customCompositionUnderlines(); 729 const Vector<CompositionUnderline>& underlines = renderer().frame()- >inputMethodController().customCompositionUnderlines();
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
768 768
769 Color c = renderer().selectionBackgroundColor(); 769 Color c = renderer().selectionBackgroundColor();
770 if (!c.alpha()) 770 if (!c.alpha())
771 return; 771 return;
772 772
773 // If the text color ends up being the same as the selection background, inv ert the selection 773 // If the text color ends up being the same as the selection background, inv ert the selection
774 // background. 774 // background.
775 if (textColor == c) 775 if (textColor == c)
776 c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue()); 776 c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue());
777 777
778
779 // If the text is truncated, let the thing being painted in the truncation 778 // If the text is truncated, let the thing being painted in the truncation
780 // draw its own highlight. 779 // draw its own highlight.
781 int length = m_truncation != cNoTruncation ? m_truncation : m_len; 780 int length = m_truncation != cNoTruncation ? m_truncation : m_len;
782 StringView string = renderer().text().createView(); 781 StringView string = renderer().text().createView();
783 782
784 if (string.length() != static_cast<unsigned>(length) || m_start) 783 if (string.length() != static_cast<unsigned>(length) || m_start)
785 string.narrow(m_start, length); 784 string.narrow(m_start, length);
786 785
787 StringBuilder charactersWithHyphen; 786 StringBuilder charactersWithHyphen;
788 bool respectHyphen = ePos == length && hasHyphen(); 787 bool respectHyphen = ePos == length && hasHyphen();
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
1035 context->setShouldAntialias(antialiasDecoration); 1034 context->setShouldAntialias(antialiasDecoration);
1036 // Fall through 1035 // Fall through
1037 default: 1036 default:
1038 context->drawLineForText(start, width, isPrinting); 1037 context->drawLineForText(start, width, isPrinting);
1039 1038
1040 if (decoration.style == TextDecorationStyleDouble) 1039 if (decoration.style == TextDecorationStyleDouble)
1041 context->drawLineForText(start + FloatPoint(0, doubleOffset), width, isPrinting); 1040 context->drawLineForText(start + FloatPoint(0, doubleOffset), width, isPrinting);
1042 } 1041 }
1043 } 1042 }
1044 1043
1045 void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint& boxOrigin, TextDecoration deco, const ShadowList* shadowList) 1044 void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint& boxOrigin, TextDecoration deco)
1046 { 1045 {
1047 GraphicsContextStateSaver stateSaver(*context); 1046 GraphicsContextStateSaver stateSaver(*context);
1048 1047
1049 if (m_truncation == cFullTruncation) 1048 if (m_truncation == cFullTruncation)
1050 return; 1049 return;
1051 1050
1052 FloatPoint localOrigin = boxOrigin; 1051 FloatPoint localOrigin = boxOrigin;
1053 1052
1054 float width = m_logicalWidth; 1053 float width = m_logicalWidth;
1055 if (m_truncation != cNoTruncation) { 1054 if (m_truncation != cNoTruncation) {
1056 width = renderer().width(m_start, m_truncation, textPos(), isLeftToRight Direction() ? LTR : RTL, isFirstLineStyle()); 1055 width = renderer().width(m_start, m_truncation, textPos(), isLeftToRight Direction() ? LTR : RTL, isFirstLineStyle());
1057 if (!isLeftToRightDirection()) 1056 if (!isLeftToRightDirection())
1058 localOrigin.move(m_logicalWidth - width, 0); 1057 localOrigin.move(m_logicalWidth - width, 0);
1059 } 1058 }
1060 1059
1061 // Get the text decoration colors. 1060 // Get the text decoration colors.
1062 RenderObject::AppliedTextDecoration underline, overline, linethrough; 1061 RenderObject::AppliedTextDecoration underline, overline, linethrough;
1063
1064 renderer().getTextDecorations(deco, underline, overline, linethrough, true); 1062 renderer().getTextDecorations(deco, underline, overline, linethrough, true);
1065 if (isFirstLineStyle()) 1063 if (isFirstLineStyle())
1066 renderer().getTextDecorations(deco, underline, overline, linethrough, tr ue, true); 1064 renderer().getTextDecorations(deco, underline, overline, linethrough, tr ue, true);
1067 1065
1068 // Use a special function for underlines to get the positioning exactly righ t. 1066 // Use a special function for underlines to get the positioning exactly righ t.
1069 bool isPrinting = renderer().document().printing(); 1067 bool isPrinting = renderer().document().printing();
1070 1068
1071 bool linesAreOpaque = !isPrinting && (!(deco & TextDecorationUnderline) || u nderline.color.alpha() == 255) && (!(deco & TextDecorationOverline) || overline. color.alpha() == 255) && (!(deco & TextDecorationLineThrough) || linethrough.col or.alpha() == 255);
1072
1073 RenderStyle* styleToUse = renderer().style(isFirstLineStyle()); 1069 RenderStyle* styleToUse = renderer().style(isFirstLineStyle());
1074 int baseline = styleToUse->fontMetrics().ascent(); 1070 int baseline = styleToUse->fontMetrics().ascent();
1075 1071
1076 size_t shadowCount = shadowList ? shadowList->shadows().size() : 0;
1077 // Set the thick of the line to be 10% (or something else ?)of the computed font size and not less than 1px. 1072 // Set the thick of the line to be 10% (or something else ?)of the computed font size and not less than 1px.
1078 // Using computedFontSize should take care of zoom as well. 1073 // Using computedFontSize should take care of zoom as well.
1079 1074
1080 // Update Underline thickness, in case we have Faulty Font Metrics calculati ng underline thickness by old method. 1075 // Update Underline thickness, in case we have Faulty Font Metrics calculati ng underline thickness by old method.
1081 float textDecorationThickness = styleToUse->fontMetrics().underlineThickness (); 1076 float textDecorationThickness = styleToUse->fontMetrics().underlineThickness ();
1082 int fontHeightInt = (int)(styleToUse->fontMetrics().floatHeight() + 0.5); 1077 int fontHeightInt = (int)(styleToUse->fontMetrics().floatHeight() + 0.5);
1083 if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHei ghtInt >> 1))) 1078 if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHei ghtInt >> 1)))
1084 textDecorationThickness = std::max(1.f, styleToUse->computedFontSize() / 10.f); 1079 textDecorationThickness = std::max(1.f, styleToUse->computedFontSize() / 10.f);
1085 1080
1086 context->setStrokeThickness(textDecorationThickness); 1081 context->setStrokeThickness(textDecorationThickness);
1087 1082
1088 bool antialiasDecoration = shouldSetDecorationAntialias(overline.style, unde rline.style, linethrough.style) 1083 bool antialiasDecoration = shouldSetDecorationAntialias(overline.style, unde rline.style, linethrough.style)
1089 && RenderBoxModelObject::shouldAntialiasLines(context); 1084 && RenderBoxModelObject::shouldAntialiasLines(context);
1090 1085
1091 float extraOffset = 0; 1086 // Offset between lines - always non-zero, so lines never cross each other.
1092 if (!linesAreOpaque && shadowCount > 1) { 1087 float doubleOffset = textDecorationThickness + 1.f;
1093 FloatRect clipRect(localOrigin, FloatSize(width, baseline + 2)); 1088
1094 for (size_t i = shadowCount; i--; ) { 1089 if (deco & TextDecorationUnderline) {
1095 const ShadowData& s = shadowList->shadows()[i]; 1090 const int underlineOffset = computeUnderlineOffset(styleToUse->textUnder linePosition(), styleToUse->fontMetrics(), this, textDecorationThickness);
1096 FloatRect shadowRect(localOrigin, FloatSize(width, baseline + 2)); 1091 paintAppliedDecoration(context, localOrigin + FloatPoint(0, underlineOff set), width, doubleOffset, 1, underline, textDecorationThickness, antialiasDecor ation, isPrinting);
1097 shadowRect.inflate(s.blur());
1098 float shadowX = isHorizontal() ? s.x() : s.y();
1099 float shadowY = isHorizontal() ? s.y() : -s.x();
1100 shadowRect.move(shadowX, shadowY);
1101 clipRect.unite(shadowRect);
1102 extraOffset = std::max(extraOffset, std::max(0.0f, shadowY) + s.blur ());
1103 }
1104 context->clip(clipRect);
1105 extraOffset += baseline + 2;
1106 localOrigin.move(0, extraOffset);
1107 } 1092 }
1108 1093 if (deco & TextDecorationOverline) {
1109 for (size_t i = std::max(static_cast<size_t>(1), shadowCount); i--; ) { 1094 paintAppliedDecoration(context, localOrigin, width, -doubleOffset, 1, ov erline, textDecorationThickness, antialiasDecoration, isPrinting);
1110 // Even if we have no shadows, we still want to run the code below this once. 1095 }
1111 if (i < shadowCount) { 1096 if (deco & TextDecorationLineThrough) {
1112 if (!i) { 1097 const float lineThroughOffset = 2 * baseline / 3;
1113 // The last set of lines paints normally inside the clip. 1098 paintAppliedDecoration(context, localOrigin + FloatPoint(0, lineThroughO ffset), width, doubleOffset, 0, linethrough, textDecorationThickness, antialiasD ecoration, isPrinting);
1114 localOrigin.move(0, -extraOffset);
1115 extraOffset = 0;
1116 }
1117 const ShadowData& shadow = shadowList->shadows()[i];
1118 float shadowX = isHorizontal() ? shadow.x() : shadow.y();
1119 float shadowY = isHorizontal() ? shadow.y() : -shadow.x();
1120 context->setShadow(FloatSize(shadowX, shadowY - extraOffset), shadow .blur(), shadow.color());
1121 }
1122
1123 // Offset between lines - always non-zero, so lines never cross each oth er.
1124 float doubleOffset = textDecorationThickness + 1.f;
1125
1126 if (deco & TextDecorationUnderline) {
1127 const int underlineOffset = computeUnderlineOffset(styleToUse->textU nderlinePosition(), styleToUse->fontMetrics(), this, textDecorationThickness);
1128 paintAppliedDecoration(context, localOrigin + FloatPoint(0, underlin eOffset), width, doubleOffset, 1, underline, textDecorationThickness, antialiasD ecoration, isPrinting);
1129 }
1130 if (deco & TextDecorationOverline) {
1131 paintAppliedDecoration(context, localOrigin, width, -doubleOffset, 1 , overline, textDecorationThickness, antialiasDecoration, isPrinting);
1132 }
1133 if (deco & TextDecorationLineThrough) {
1134 const float lineThroughOffset = 2 * baseline / 3;
1135 paintAppliedDecoration(context, localOrigin + FloatPoint(0, lineThro ughOffset), width, doubleOffset, 0, linethrough, textDecorationThickness, antial iasDecoration, isPrinting);
1136 }
1137 } 1099 }
1138 } 1100 }
1139 1101
1140 static GraphicsContext::DocumentMarkerLineStyle lineStyleForMarkerType(DocumentM arker::MarkerType markerType) 1102 static GraphicsContext::DocumentMarkerLineStyle lineStyleForMarkerType(DocumentM arker::MarkerType markerType)
1141 { 1103 {
1142 switch (markerType) { 1104 switch (markerType) {
1143 case DocumentMarker::Spelling: 1105 case DocumentMarker::Spelling:
1144 return GraphicsContext::DocumentMarkerSpellingLineStyle; 1106 return GraphicsContext::DocumentMarkerSpellingLineStyle;
1145 case DocumentMarker::Grammar: 1107 case DocumentMarker::Grammar:
1146 return GraphicsContext::DocumentMarkerGrammarLineStyle; 1108 return GraphicsContext::DocumentMarkerGrammarLineStyle;
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after
1520 printedCharacters = fprintf(stderr, "\t%s %p", obj.renderName(), &obj); 1482 printedCharacters = fprintf(stderr, "\t%s %p", obj.renderName(), &obj);
1521 const int rendererCharacterOffset = 24; 1483 const int rendererCharacterOffset = 24;
1522 for (; printedCharacters < rendererCharacterOffset; printedCharacters++) 1484 for (; printedCharacters < rendererCharacterOffset; printedCharacters++)
1523 fputc(' ', stderr); 1485 fputc(' ', stderr);
1524 fprintf(stderr, "(%d,%d) \"%s\"\n", start(), start() + len(), value.utf8().d ata()); 1486 fprintf(stderr, "(%d,%d) \"%s\"\n", start(), start() + len(), value.utf8().d ata());
1525 } 1487 }
1526 1488
1527 #endif 1489 #endif
1528 1490
1529 } // namespace blink 1491 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/rendering/InlineTextBox.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698