Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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, | 353 static void paintText(GraphicsContext* context, |
| 376 const Font& font, const TextRun& textRun, | 354 const Font& font, const TextRun& textRun, |
| 377 const AtomicString& emphasisMark, int emphasisMarkOffset, | 355 const AtomicString& emphasisMark, int emphasisMarkOffset, |
| 378 int startOffset, int endOffset, int truncationPoint, | 356 int startOffset, int endOffset, int truncationPoint, |
| 379 const FloatPoint& textOrigin, const FloatRect& boxRect, | 357 const FloatPoint& textOrigin, const FloatRect& boxRect) |
| 380 const ShadowList* shadowList, bool horizontal) | |
| 381 { | 358 { |
| 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); | 359 TextRunPaintInfo textRunPaintInfo(textRun); |
| 388 textRunPaintInfo.bounds = boxRect; | 360 textRunPaintInfo.bounds = boxRect; |
| 389 if (startOffset <= endOffset) { | 361 if (startOffset <= endOffset) { |
| 390 textRunPaintInfo.from = startOffset; | 362 textRunPaintInfo.from = startOffset; |
| 391 textRunPaintInfo.to = endOffset; | 363 textRunPaintInfo.to = endOffset; |
| 392 if (emphasisMark.isEmpty()) | 364 if (emphasisMark.isEmpty()) |
| 393 context->drawText(font, textRunPaintInfo, textOrigin); | 365 context->drawText(font, textRunPaintInfo, textOrigin); |
| 394 else | 366 else |
| 395 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisMark, tex tOrigin + IntSize(0, emphasisMarkOffset)); | 367 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisMark, tex tOrigin + IntSize(0, emphasisMarkOffset)); |
| 396 } else { | 368 } else { |
| 397 if (endOffset > 0) { | 369 if (endOffset > 0) { |
| 398 textRunPaintInfo.from = 0; | 370 textRunPaintInfo.from = 0; |
| 399 textRunPaintInfo.to = endOffset; | 371 textRunPaintInfo.to = endOffset; |
| 400 if (emphasisMark.isEmpty()) | 372 if (emphasisMark.isEmpty()) |
| 401 context->drawText(font, textRunPaintInfo, textOrigin); | 373 context->drawText(font, textRunPaintInfo, textOrigin); |
| 402 else | 374 else |
| 403 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisMark, textOrigin + IntSize(0, emphasisMarkOffset)); | 375 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisMark, textOrigin + IntSize(0, emphasisMarkOffset)); |
| 404 } | 376 } |
| 405 if (startOffset < truncationPoint) { | 377 if (startOffset < truncationPoint) { |
| 406 textRunPaintInfo.from = startOffset; | 378 textRunPaintInfo.from = startOffset; |
| 407 textRunPaintInfo.to = truncationPoint; | 379 textRunPaintInfo.to = truncationPoint; |
| 408 if (emphasisMark.isEmpty()) | 380 if (emphasisMark.isEmpty()) |
| 409 context->drawText(font, textRunPaintInfo, textOrigin); | 381 context->drawText(font, textRunPaintInfo, textOrigin); |
| 410 else | 382 else |
| 411 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisMark, textOrigin + IntSize(0, emphasisMarkOffset)); | 383 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisMark, textOrigin + IntSize(0, emphasisMarkOffset)); |
| 412 } | 384 } |
| 413 } | 385 } |
| 414 | |
| 415 if (hasShadow) | |
| 416 context->clearDrawLooper(); | |
| 417 } | 386 } |
| 418 | 387 |
| 419 static void paintEmphasisMark(GraphicsContext* context, | 388 static void paintEmphasisMark(GraphicsContext* context, |
| 420 const AtomicString& emphasisMark, int emphasisMarkOffset, | 389 const AtomicString& emphasisMark, int emphasisMarkOffset, |
| 421 int startOffset, int endOffset, int paintRunLength, | 390 int startOffset, int endOffset, int paintRunLength, |
| 422 const Font& font, Color emphasisMarkColor, Color textStrokeColor, float text StrokeWidth, const ShadowList* textShadow, | 391 const Font& font, RenderCombineText* combinedText, const TextRun& textRun, |
| 423 RenderCombineText* combinedText, const TextRun& textRun, | 392 const FloatPoint& textOrigin, const FloatRect& boxRect) |
| 424 const FloatPoint& textOrigin, const FloatRect& boxRect, bool horizontal) | |
| 425 { | 393 { |
| 426 ASSERT(!emphasisMark.isEmpty()); | 394 ASSERT(!emphasisMark.isEmpty()); |
| 427 updateGraphicsContext(context, emphasisMarkColor, textStrokeColor, textStrok eWidth); | |
| 428 | 395 |
| 429 if (combinedText) { | 396 if (combinedText) { |
| 430 DEFINE_STATIC_LOCAL(TextRun, objectReplacementCharacterTextRun, (&object ReplacementCharacter, 1)); | 397 DEFINE_STATIC_LOCAL(TextRun, objectReplacementCharacterTextRun, (&object ReplacementCharacter, 1)); |
| 431 FloatPoint emphasisMarkTextOrigin(boxRect.x() + boxRect.width() / 2, box Rect.y() + font.fontMetrics().ascent()); | 398 FloatPoint emphasisMarkTextOrigin(boxRect.x() + boxRect.width() / 2, box Rect.y() + font.fontMetrics().ascent()); |
| 432 context->concatCTM(InlineTextBox::rotation(boxRect, InlineTextBox::Clock wise)); | 399 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); | 400 paintText(context, combinedText->originalFont(), objectReplacementCharac terTextRun, emphasisMark, emphasisMarkOffset, 0, 1, 1, emphasisMarkTextOrigin, b oxRect); |
| 434 context->concatCTM(InlineTextBox::rotation(boxRect, InlineTextBox::Count erclockwise)); | 401 context->concatCTM(InlineTextBox::rotation(boxRect, InlineTextBox::Count erclockwise)); |
| 435 } else { | 402 } else { |
| 436 paintTextWithShadows(context, font, textRun, emphasisMark, emphasisMarkO ffset, startOffset, endOffset, paintRunLength, textOrigin, boxRect, textShadow, horizontal); | 403 paintText(context, font, textRun, emphasisMark, emphasisMarkOffset, star tOffset, endOffset, paintRunLength, textOrigin, boxRect); |
| 437 } | 404 } |
| 438 } | 405 } |
| 439 | 406 |
| 440 bool InlineTextBox::getEmphasisMarkPosition(RenderStyle* style, TextEmphasisPosi tion& emphasisPosition) const | 407 bool InlineTextBox::getEmphasisMarkPosition(RenderStyle* style, TextEmphasisPosi tion& emphasisPosition) const |
| 441 { | 408 { |
| 442 // This function returns true if there are text emphasis marks and they are suppressed by ruby text. | 409 // This function returns true if there are text emphasis marks and they are suppressed by ruby text. |
| 443 if (style->textEmphasisMark() == TextEmphasisMarkNone) | 410 if (style->textEmphasisMark() == TextEmphasisMarkNone) |
| 444 return false; | 411 return false; |
| 445 | 412 |
| 446 emphasisPosition = style->textEmphasisPosition(); | 413 emphasisPosition = style->textEmphasisPosition(); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 538 // Text shadows are disabled when printing. http://crbug.com/258321 | 505 // Text shadows are disabled when printing. http://crbug.com/258321 |
| 539 if (isPrinting) | 506 if (isPrinting) |
| 540 selectionStyle.shadow = 0; | 507 selectionStyle.shadow = 0; |
| 541 } | 508 } |
| 542 | 509 |
| 543 return selectionStyle; | 510 return selectionStyle; |
| 544 } | 511 } |
| 545 | 512 |
| 546 } // namespace | 513 } // namespace |
| 547 | 514 |
| 515 static void updateGraphicsContext(GraphicsContext* context, const TextPaintingSt yle& textStyle, bool horizontal, GraphicsContextStateSaver* stateSaver = 0) | |
|
f(malita)
2014/08/20 18:55:45
Nit: this could live in the anonymous namespace ab
jbroman
2014/08/20 19:32:25
Okay. At this point, I might as well push paintTex
| |
| 516 { | |
| 517 TextDrawingModeFlags mode = context->textDrawingMode(); | |
| 518 if (textStyle.strokeWidth > 0) { | |
| 519 if (stateSaver) { | |
|
f(malita)
2014/08/20 18:55:46
Can we skip this when mode == newMode (move it ins
jbroman
2014/08/20 19:32:25
Done.
| |
| 520 stateSaver->save(); | |
| 521 stateSaver = 0; | |
| 522 } | |
| 523 | |
| 524 TextDrawingModeFlags newMode = mode | TextModeStroke; | |
| 525 if (mode != newMode) { | |
| 526 context->setTextDrawingMode(newMode); | |
| 527 mode = newMode; | |
| 528 } | |
| 529 } | |
| 530 | |
| 531 if (mode & TextModeFill && textStyle.fillColor != context->fillColor()) | |
| 532 context->setFillColor(textStyle.fillColor); | |
| 533 | |
| 534 if (mode & TextModeStroke) { | |
| 535 if (textStyle.strokeColor != context->strokeColor()) | |
| 536 context->setStrokeColor(textStyle.strokeColor); | |
| 537 if (textStyle.strokeWidth != context->strokeThickness()) | |
| 538 context->setStrokeThickness(textStyle.strokeWidth); | |
| 539 } | |
| 540 | |
| 541 // Text shadows are disabled when printing. http://crbug.com/258321 | |
| 542 if (textStyle.shadow && !context->printing()) { | |
| 543 context->setDrawLooper(textStyle.shadow->createDrawLooper(DrawLooperBuil der::ShadowIgnoresAlpha, horizontal)); | |
| 544 if (stateSaver) { | |
| 545 stateSaver->save(); | |
|
f(malita)
2014/08/20 18:55:46
We should save before touching the looper.
jbroman
2014/08/20 19:32:25
Err, yes, of course. Hazard of "p" and "P" being s
| |
| 546 stateSaver = 0; | |
| 547 } | |
| 548 } | |
| 549 } | |
| 550 | |
| 551 static void paintTextWithEmphasisMark( | |
| 552 GraphicsContext* context, const Font& font, const TextPaintingStyle& textSty le, const TextRun& textRun, | |
| 553 const AtomicString& emphasisMark, int emphasisMarkOffset, int startOffset, i nt endOffset, int length, | |
| 554 RenderCombineText* combinedText, const FloatPoint& textOrigin, const FloatRe ct& boxRect, bool horizontal) | |
| 555 { | |
| 556 GraphicsContextStateSaver stateSaver(*context, false); | |
| 557 updateGraphicsContext(context, textStyle, horizontal, &stateSaver); | |
| 558 paintText(context, font, textRun, nullAtom, 0, startOffset, endOffset, lengt h, textOrigin, boxRect); | |
| 559 | |
| 560 if (!emphasisMark.isEmpty()) { | |
| 561 if (textStyle.emphasisMarkColor != textStyle.fillColor) | |
| 562 context->setFillColor(textStyle.emphasisMarkColor); | |
| 563 paintEmphasisMark(context, emphasisMark, emphasisMarkOffset, startOffset , endOffset, length, font, combinedText, textRun, textOrigin, boxRect); | |
| 564 } | |
| 565 } | |
| 566 | |
| 548 void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit /*lineTop*/, LayoutUnit /*lineBottom*/) | 567 void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit /*lineTop*/, LayoutUnit /*lineBottom*/) |
| 549 { | 568 { |
| 550 if (isLineBreak() || !paintInfo.shouldPaintWithinRoot(&renderer()) || render er().style()->visibility() != VISIBLE | 569 if (isLineBreak() || !paintInfo.shouldPaintWithinRoot(&renderer()) || render er().style()->visibility() != VISIBLE |
| 551 || m_truncation == cFullTruncation || paintInfo.phase == PaintPhaseOutli ne || !m_len) | 570 || m_truncation == cFullTruncation || paintInfo.phase == PaintPhaseOutli ne || !m_len) |
| 552 return; | 571 return; |
| 553 | 572 |
| 554 ASSERT(paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintP haseChildOutlines); | 573 ASSERT(paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintP haseChildOutlines); |
| 555 | 574 |
| 556 LayoutRect logicalVisualOverflow = logicalOverflowRect(); | 575 LayoutRect logicalVisualOverflow = logicalOverflowRect(); |
| 557 LayoutUnit logicalStart = logicalVisualOverflow.x() + (isHorizontal() ? pain tOffset.x() : paintOffset.y()); | 576 LayoutUnit logicalStart = logicalVisualOverflow.x() + (isHorizontal() ? pain tOffset.x() : paintOffset.y()); |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 680 emphasisMarkOffset = emphasisMarkPosition == TextEmphasisPositionOver ? -font.fontMetrics().ascent() - font.emphasisMarkDescent(emphasisMark) : font.fon tMetrics().descent() + font.emphasisMarkAscent(emphasisMark); | 699 emphasisMarkOffset = emphasisMarkPosition == TextEmphasisPositionOver ? -font.fontMetrics().ascent() - font.emphasisMarkDescent(emphasisMark) : font.fon tMetrics().descent() + font.emphasisMarkAscent(emphasisMark); |
| 681 | 700 |
| 682 if (!paintSelectedTextOnly) { | 701 if (!paintSelectedTextOnly) { |
| 683 // FIXME: Truncate right-to-left text correctly. | 702 // FIXME: Truncate right-to-left text correctly. |
| 684 int startOffset = 0; | 703 int startOffset = 0; |
| 685 int endOffset = length; | 704 int endOffset = length; |
| 686 if (paintSelectedTextSeparately && ePos > sPos) { | 705 if (paintSelectedTextSeparately && ePos > sPos) { |
| 687 startOffset = ePos; | 706 startOffset = ePos; |
| 688 endOffset = sPos; | 707 endOffset = sPos; |
| 689 } | 708 } |
| 690 | 709 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 } | 710 } |
| 701 | 711 |
| 702 if ((paintSelectedTextOnly || paintSelectedTextSeparately) && sPos < ePos) { | 712 if ((paintSelectedTextOnly || paintSelectedTextSeparately) && sPos < ePos) { |
| 703 // paint only the text that is selected | 713 // paint only the text that is selected |
| 704 GraphicsContextStateSaver stateSaver(*context, selectionStyle.strokeWidt h > 0); | 714 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 } | 715 } |
| 712 | 716 |
| 713 // Paint decorations | 717 // Paint decorations |
| 714 TextDecoration textDecorations = styleToUse->textDecorationsInEffect(); | 718 TextDecoration textDecorations = styleToUse->textDecorationsInEffect(); |
| 715 if (textDecorations != TextDecorationNone && paintInfo.phase != PaintPhaseSe lection) { | 719 if (textDecorations != TextDecorationNone && !paintSelectedTextOnly) { |
| 716 updateGraphicsContext(context, textStyle.fillColor, textStyle.strokeColo r, textStyle.strokeWidth); | 720 GraphicsContextStateSaver stateSaver(*context); |
|
f(malita)
2014/08/20 18:55:45
Can't this save be deferred also? Why weren't we s
jbroman
2014/08/20 19:32:24
In the combinedText case, there's also the CTM rot
| |
| 721 updateGraphicsContext(context, textStyle, isHorizontal()); | |
| 717 if (combinedText) | 722 if (combinedText) |
| 718 context->concatCTM(rotation(boxRect, Clockwise)); | 723 context->concatCTM(rotation(boxRect, Clockwise)); |
| 719 paintDecoration(context, boxOrigin, textDecorations, textStyle.shadow); | 724 paintDecoration(context, boxOrigin, textDecorations); |
| 720 if (combinedText) | |
| 721 context->concatCTM(rotation(boxRect, Counterclockwise)); | |
| 722 } | 725 } |
| 723 | 726 |
| 724 if (paintInfo.phase == PaintPhaseForeground) { | 727 if (paintInfo.phase == PaintPhaseForeground) { |
| 725 paintDocumentMarkers(context, boxOrigin, styleToUse, font, false); | 728 paintDocumentMarkers(context, boxOrigin, styleToUse, font, false); |
| 726 | 729 |
| 727 // Paint custom underlines for compositions. | 730 // Paint custom underlines for compositions. |
| 728 if (useCustomUnderlines) { | 731 if (useCustomUnderlines) { |
| 729 const Vector<CompositionUnderline>& underlines = renderer().frame()- >inputMethodController().customCompositionUnderlines(); | 732 const Vector<CompositionUnderline>& underlines = renderer().frame()- >inputMethodController().customCompositionUnderlines(); |
| 730 CompositionUnderlineRangeFilter filter(underlines, start(), end()); | 733 CompositionUnderlineRangeFilter filter(underlines, start(), end()); |
| 731 for (CompositionUnderlineRangeFilter::ConstIterator it = filter.begi n(); it != filter.end(); ++it) { | 734 for (CompositionUnderlineRangeFilter::ConstIterator it = filter.begi n(); it != filter.end(); ++it) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 768 | 771 |
| 769 Color c = renderer().selectionBackgroundColor(); | 772 Color c = renderer().selectionBackgroundColor(); |
| 770 if (!c.alpha()) | 773 if (!c.alpha()) |
| 771 return; | 774 return; |
| 772 | 775 |
| 773 // If the text color ends up being the same as the selection background, inv ert the selection | 776 // If the text color ends up being the same as the selection background, inv ert the selection |
| 774 // background. | 777 // background. |
| 775 if (textColor == c) | 778 if (textColor == c) |
| 776 c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue()); | 779 c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue()); |
| 777 | 780 |
| 778 | |
| 779 // If the text is truncated, let the thing being painted in the truncation | 781 // If the text is truncated, let the thing being painted in the truncation |
| 780 // draw its own highlight. | 782 // draw its own highlight. |
| 781 int length = m_truncation != cNoTruncation ? m_truncation : m_len; | 783 int length = m_truncation != cNoTruncation ? m_truncation : m_len; |
| 782 StringView string = renderer().text().createView(); | 784 StringView string = renderer().text().createView(); |
| 783 | 785 |
| 784 if (string.length() != static_cast<unsigned>(length) || m_start) | 786 if (string.length() != static_cast<unsigned>(length) || m_start) |
| 785 string.narrow(m_start, length); | 787 string.narrow(m_start, length); |
| 786 | 788 |
| 787 StringBuilder charactersWithHyphen; | 789 StringBuilder charactersWithHyphen; |
| 788 bool respectHyphen = ePos == length && hasHyphen(); | 790 bool respectHyphen = ePos == length && hasHyphen(); |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1035 context->setShouldAntialias(antialiasDecoration); | 1037 context->setShouldAntialias(antialiasDecoration); |
| 1036 // Fall through | 1038 // Fall through |
| 1037 default: | 1039 default: |
| 1038 context->drawLineForText(start, width, isPrinting); | 1040 context->drawLineForText(start, width, isPrinting); |
| 1039 | 1041 |
| 1040 if (decoration.style == TextDecorationStyleDouble) | 1042 if (decoration.style == TextDecorationStyleDouble) |
| 1041 context->drawLineForText(start + FloatPoint(0, doubleOffset), width, isPrinting); | 1043 context->drawLineForText(start + FloatPoint(0, doubleOffset), width, isPrinting); |
| 1042 } | 1044 } |
| 1043 } | 1045 } |
| 1044 | 1046 |
| 1045 void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint& boxOrigin, TextDecoration deco, const ShadowList* shadowList) | 1047 void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint& boxOrigin, TextDecoration deco) |
| 1046 { | 1048 { |
| 1047 GraphicsContextStateSaver stateSaver(*context); | 1049 GraphicsContextStateSaver stateSaver(*context); |
| 1048 | 1050 |
| 1049 if (m_truncation == cFullTruncation) | 1051 if (m_truncation == cFullTruncation) |
| 1050 return; | 1052 return; |
| 1051 | 1053 |
| 1052 FloatPoint localOrigin = boxOrigin; | 1054 FloatPoint localOrigin = boxOrigin; |
| 1053 | 1055 |
| 1054 float width = m_logicalWidth; | 1056 float width = m_logicalWidth; |
| 1055 if (m_truncation != cNoTruncation) { | 1057 if (m_truncation != cNoTruncation) { |
| 1056 width = renderer().width(m_start, m_truncation, textPos(), isLeftToRight Direction() ? LTR : RTL, isFirstLineStyle()); | 1058 width = renderer().width(m_start, m_truncation, textPos(), isLeftToRight Direction() ? LTR : RTL, isFirstLineStyle()); |
| 1057 if (!isLeftToRightDirection()) | 1059 if (!isLeftToRightDirection()) |
| 1058 localOrigin.move(m_logicalWidth - width, 0); | 1060 localOrigin.move(m_logicalWidth - width, 0); |
| 1059 } | 1061 } |
| 1060 | 1062 |
| 1061 // Get the text decoration colors. | 1063 // Get the text decoration colors. |
| 1062 RenderObject::AppliedTextDecoration underline, overline, linethrough; | 1064 RenderObject::AppliedTextDecoration underline, overline, linethrough; |
| 1063 | |
| 1064 renderer().getTextDecorations(deco, underline, overline, linethrough, true); | 1065 renderer().getTextDecorations(deco, underline, overline, linethrough, true); |
| 1065 if (isFirstLineStyle()) | 1066 if (isFirstLineStyle()) |
| 1066 renderer().getTextDecorations(deco, underline, overline, linethrough, tr ue, true); | 1067 renderer().getTextDecorations(deco, underline, overline, linethrough, tr ue, true); |
| 1067 | 1068 |
| 1068 // Use a special function for underlines to get the positioning exactly righ t. | 1069 // Use a special function for underlines to get the positioning exactly righ t. |
| 1069 bool isPrinting = renderer().document().printing(); | 1070 bool isPrinting = renderer().document().printing(); |
| 1070 | 1071 |
| 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()); | 1072 RenderStyle* styleToUse = renderer().style(isFirstLineStyle()); |
| 1074 int baseline = styleToUse->fontMetrics().ascent(); | 1073 int baseline = styleToUse->fontMetrics().ascent(); |
| 1075 | 1074 |
| 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. | 1075 // 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. | 1076 // Using computedFontSize should take care of zoom as well. |
| 1079 | 1077 |
| 1080 // Update Underline thickness, in case we have Faulty Font Metrics calculati ng underline thickness by old method. | 1078 // Update Underline thickness, in case we have Faulty Font Metrics calculati ng underline thickness by old method. |
| 1081 float textDecorationThickness = styleToUse->fontMetrics().underlineThickness (); | 1079 float textDecorationThickness = styleToUse->fontMetrics().underlineThickness (); |
| 1082 int fontHeightInt = (int)(styleToUse->fontMetrics().floatHeight() + 0.5); | 1080 int fontHeightInt = (int)(styleToUse->fontMetrics().floatHeight() + 0.5); |
| 1083 if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHei ghtInt >> 1))) | 1081 if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHei ghtInt >> 1))) |
| 1084 textDecorationThickness = std::max(1.f, styleToUse->computedFontSize() / 10.f); | 1082 textDecorationThickness = std::max(1.f, styleToUse->computedFontSize() / 10.f); |
| 1085 | 1083 |
| 1086 context->setStrokeThickness(textDecorationThickness); | 1084 context->setStrokeThickness(textDecorationThickness); |
| 1087 | 1085 |
| 1088 bool antialiasDecoration = shouldSetDecorationAntialias(overline.style, unde rline.style, linethrough.style) | 1086 bool antialiasDecoration = shouldSetDecorationAntialias(overline.style, unde rline.style, linethrough.style) |
| 1089 && RenderBoxModelObject::shouldAntialiasLines(context); | 1087 && RenderBoxModelObject::shouldAntialiasLines(context); |
| 1090 | 1088 |
| 1091 float extraOffset = 0; | 1089 // Offset between lines - always non-zero, so lines never cross each other. |
| 1092 if (!linesAreOpaque && shadowCount > 1) { | 1090 float doubleOffset = textDecorationThickness + 1.f; |
| 1093 FloatRect clipRect(localOrigin, FloatSize(width, baseline + 2)); | 1091 |
| 1094 for (size_t i = shadowCount; i--; ) { | 1092 if (deco & TextDecorationUnderline) { |
| 1095 const ShadowData& s = shadowList->shadows()[i]; | 1093 const int underlineOffset = computeUnderlineOffset(styleToUse->textUnder linePosition(), styleToUse->fontMetrics(), this, textDecorationThickness); |
| 1096 FloatRect shadowRect(localOrigin, FloatSize(width, baseline + 2)); | 1094 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 } | 1095 } |
| 1108 | 1096 if (deco & TextDecorationOverline) { |
| 1109 for (size_t i = std::max(static_cast<size_t>(1), shadowCount); i--; ) { | 1097 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. | 1098 } |
| 1111 if (i < shadowCount) { | 1099 if (deco & TextDecorationLineThrough) { |
| 1112 if (!i) { | 1100 const float lineThroughOffset = 2 * baseline / 3; |
| 1113 // The last set of lines paints normally inside the clip. | 1101 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 } | 1102 } |
| 1138 } | 1103 } |
| 1139 | 1104 |
| 1140 static GraphicsContext::DocumentMarkerLineStyle lineStyleForMarkerType(DocumentM arker::MarkerType markerType) | 1105 static GraphicsContext::DocumentMarkerLineStyle lineStyleForMarkerType(DocumentM arker::MarkerType markerType) |
| 1141 { | 1106 { |
| 1142 switch (markerType) { | 1107 switch (markerType) { |
| 1143 case DocumentMarker::Spelling: | 1108 case DocumentMarker::Spelling: |
| 1144 return GraphicsContext::DocumentMarkerSpellingLineStyle; | 1109 return GraphicsContext::DocumentMarkerSpellingLineStyle; |
| 1145 case DocumentMarker::Grammar: | 1110 case DocumentMarker::Grammar: |
| 1146 return GraphicsContext::DocumentMarkerGrammarLineStyle; | 1111 return GraphicsContext::DocumentMarkerGrammarLineStyle; |
| (...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1520 printedCharacters = fprintf(stderr, "\t%s %p", obj.renderName(), &obj); | 1485 printedCharacters = fprintf(stderr, "\t%s %p", obj.renderName(), &obj); |
| 1521 const int rendererCharacterOffset = 24; | 1486 const int rendererCharacterOffset = 24; |
| 1522 for (; printedCharacters < rendererCharacterOffset; printedCharacters++) | 1487 for (; printedCharacters < rendererCharacterOffset; printedCharacters++) |
| 1523 fputc(' ', stderr); | 1488 fputc(' ', stderr); |
| 1524 fprintf(stderr, "(%d,%d) \"%s\"\n", start(), start() + len(), value.utf8().d ata()); | 1489 fprintf(stderr, "(%d,%d) \"%s\"\n", start(), start() + len(), value.utf8().d ata()); |
| 1525 } | 1490 } |
| 1526 | 1491 |
| 1527 #endif | 1492 #endif |
| 1528 | 1493 |
| 1529 } // namespace blink | 1494 } // namespace blink |
| OLD | NEW |