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) | 332 static void updateGraphicsContext(GraphicsContext* context, const Color& fillCol or, const Color& strokeColor, float strokeThickness, const ShadowList* textShado w = 0, bool horizontal = true) |
333 { | 333 { |
334 TextDrawingModeFlags mode = context->textDrawingMode(); | 334 TextDrawingModeFlags mode = context->textDrawingMode(); |
335 if (strokeThickness > 0) { | 335 if (strokeThickness > 0) { |
336 TextDrawingModeFlags newMode = mode | TextModeStroke; | 336 TextDrawingModeFlags newMode = mode | TextModeStroke; |
337 if (mode != newMode) { | 337 if (mode != newMode) { |
338 context->setTextDrawingMode(newMode); | 338 context->setTextDrawingMode(newMode); |
339 mode = newMode; | 339 mode = newMode; |
340 } | 340 } |
341 } | 341 } |
342 | 342 |
343 if (mode & TextModeFill && fillColor != context->fillColor()) | 343 if (mode & TextModeFill && fillColor != context->fillColor()) |
344 context->setFillColor(fillColor); | 344 context->setFillColor(fillColor); |
345 | 345 |
346 if (mode & TextModeStroke) { | 346 if (mode & TextModeStroke) { |
347 if (strokeColor != context->strokeColor()) | 347 if (strokeColor != context->strokeColor()) |
348 context->setStrokeColor(strokeColor); | 348 context->setStrokeColor(strokeColor); |
349 if (strokeThickness != context->strokeThickness()) | 349 if (strokeThickness != context->strokeThickness()) |
350 context->setStrokeThickness(strokeThickness); | 350 context->setStrokeThickness(strokeThickness); |
351 } | 351 } |
352 | |
353 // Text shadows are disabled when printing. http://crbug.com/258321 | |
354 if (textShadow && !context->printing()) | |
355 context->setDrawLooper(textShadow->createDrawLooper(DrawLooperBuilder::S hadowIgnoresAlpha, horizontal)); | |
356 else | |
357 context->clearDrawLooper(); | |
f(malita)
2014/08/15 02:01:06
Is clearing required here? I don't think we were d
jbroman
2014/08/19 18:00:43
It's a little finicky. I've refactored to just use
| |
352 } | 358 } |
353 | 359 |
354 bool InlineTextBox::isLineBreak() const | 360 bool InlineTextBox::isLineBreak() const |
355 { | 361 { |
356 return renderer().isBR() || (renderer().style()->preserveNewline() && len() == 1 && (*renderer().text().impl())[start()] == '\n'); | 362 return renderer().isBR() || (renderer().style()->preserveNewline() && len() == 1 && (*renderer().text().impl())[start()] == '\n'); |
357 } | 363 } |
358 | 364 |
359 bool InlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re sult, const HitTestLocation& locationInContainer, const LayoutPoint& accumulated Offset, LayoutUnit /* lineTop */, LayoutUnit /*lineBottom*/) | 365 bool InlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re sult, const HitTestLocation& locationInContainer, const LayoutPoint& accumulated Offset, LayoutUnit /* lineTop */, LayoutUnit /*lineBottom*/) |
360 { | 366 { |
361 if (isLineBreak()) | 367 if (isLineBreak()) |
362 return false; | 368 return false; |
363 | 369 |
364 FloatPoint boxOrigin = locationIncludingFlipping(); | 370 FloatPoint boxOrigin = locationIncludingFlipping(); |
365 boxOrigin.moveBy(accumulatedOffset); | 371 boxOrigin.moveBy(accumulatedOffset); |
366 FloatRect rect(boxOrigin, size()); | 372 FloatRect rect(boxOrigin, size()); |
367 if (m_truncation != cFullTruncation && visibleToHitTestRequest(request) && l ocationInContainer.intersects(rect)) { | 373 if (m_truncation != cFullTruncation && visibleToHitTestRequest(request) && l ocationInContainer.intersects(rect)) { |
368 renderer().updateHitTestResult(result, flipForWritingMode(locationInCont ainer.point() - toLayoutSize(accumulatedOffset))); | 374 renderer().updateHitTestResult(result, flipForWritingMode(locationInCont ainer.point() - toLayoutSize(accumulatedOffset))); |
369 if (!result.addNodeToRectBasedTestResult(renderer().node(), request, loc ationInContainer, rect)) | 375 if (!result.addNodeToRectBasedTestResult(renderer().node(), request, loc ationInContainer, rect)) |
370 return true; | 376 return true; |
371 } | 377 } |
372 return false; | 378 return false; |
373 } | 379 } |
374 | 380 |
375 static void paintTextWithShadows(GraphicsContext* context, | 381 static void paintText(GraphicsContext* context, |
376 const Font& font, const TextRun& textRun, | 382 const Font& font, const TextRun& textRun, |
377 const AtomicString& emphasisMark, int emphasisMarkOffset, | 383 const AtomicString& emphasisMark, int emphasisMarkOffset, |
378 int startOffset, int endOffset, int truncationPoint, | 384 int startOffset, int endOffset, int truncationPoint, |
379 const FloatPoint& textOrigin, const FloatRect& boxRect, | 385 const FloatPoint& textOrigin, const FloatRect& boxRect) |
380 const ShadowList* shadowList, bool horizontal) | |
381 { | 386 { |
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); | 387 TextRunPaintInfo textRunPaintInfo(textRun); |
388 textRunPaintInfo.bounds = boxRect; | 388 textRunPaintInfo.bounds = boxRect; |
389 if (startOffset <= endOffset) { | 389 if (startOffset <= endOffset) { |
390 textRunPaintInfo.from = startOffset; | 390 textRunPaintInfo.from = startOffset; |
391 textRunPaintInfo.to = endOffset; | 391 textRunPaintInfo.to = endOffset; |
392 if (emphasisMark.isEmpty()) | 392 if (emphasisMark.isEmpty()) |
393 context->drawText(font, textRunPaintInfo, textOrigin); | 393 context->drawText(font, textRunPaintInfo, textOrigin); |
394 else | 394 else |
395 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisMark, tex tOrigin + IntSize(0, emphasisMarkOffset)); | 395 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisMark, tex tOrigin + IntSize(0, emphasisMarkOffset)); |
396 } else { | 396 } else { |
397 if (endOffset > 0) { | 397 if (endOffset > 0) { |
398 textRunPaintInfo.from = 0; | 398 textRunPaintInfo.from = 0; |
399 textRunPaintInfo.to = endOffset; | 399 textRunPaintInfo.to = endOffset; |
400 if (emphasisMark.isEmpty()) | 400 if (emphasisMark.isEmpty()) |
401 context->drawText(font, textRunPaintInfo, textOrigin); | 401 context->drawText(font, textRunPaintInfo, textOrigin); |
402 else | 402 else |
403 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisMark, textOrigin + IntSize(0, emphasisMarkOffset)); | 403 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisMark, textOrigin + IntSize(0, emphasisMarkOffset)); |
404 } | 404 } |
405 if (startOffset < truncationPoint) { | 405 if (startOffset < truncationPoint) { |
406 textRunPaintInfo.from = startOffset; | 406 textRunPaintInfo.from = startOffset; |
407 textRunPaintInfo.to = truncationPoint; | 407 textRunPaintInfo.to = truncationPoint; |
408 if (emphasisMark.isEmpty()) | 408 if (emphasisMark.isEmpty()) |
409 context->drawText(font, textRunPaintInfo, textOrigin); | 409 context->drawText(font, textRunPaintInfo, textOrigin); |
410 else | 410 else |
411 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisMark, textOrigin + IntSize(0, emphasisMarkOffset)); | 411 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisMark, textOrigin + IntSize(0, emphasisMarkOffset)); |
412 } | 412 } |
413 } | 413 } |
414 | |
415 if (hasShadow) | |
416 context->clearDrawLooper(); | |
417 } | 414 } |
418 | 415 |
419 static void paintEmphasisMark(GraphicsContext* context, | 416 static void paintEmphasisMark(GraphicsContext* context, |
420 const AtomicString& emphasisMark, int emphasisMarkOffset, | 417 const AtomicString& emphasisMark, int emphasisMarkOffset, |
421 int startOffset, int endOffset, int paintRunLength, | 418 int startOffset, int endOffset, int paintRunLength, |
422 const Font& font, Color emphasisMarkColor, Color textStrokeColor, float text StrokeWidth, const ShadowList* textShadow, | 419 const Font& font, Color emphasisMarkColor, Color textStrokeColor, float text StrokeWidth, const ShadowList* textShadow, |
423 RenderCombineText* combinedText, const TextRun& textRun, | 420 RenderCombineText* combinedText, const TextRun& textRun, |
424 const FloatPoint& textOrigin, const FloatRect& boxRect, bool horizontal) | 421 const FloatPoint& textOrigin, const FloatRect& boxRect, bool horizontal) |
425 { | 422 { |
426 ASSERT(!emphasisMark.isEmpty()); | 423 ASSERT(!emphasisMark.isEmpty()); |
427 updateGraphicsContext(context, emphasisMarkColor, textStrokeColor, textStrok eWidth); | 424 updateGraphicsContext(context, emphasisMarkColor, textStrokeColor, textStrok eWidth, textShadow, horizontal); |
428 | 425 |
429 if (combinedText) { | 426 if (combinedText) { |
430 DEFINE_STATIC_LOCAL(TextRun, objectReplacementCharacterTextRun, (&object ReplacementCharacter, 1)); | 427 DEFINE_STATIC_LOCAL(TextRun, objectReplacementCharacterTextRun, (&object ReplacementCharacter, 1)); |
431 FloatPoint emphasisMarkTextOrigin(boxRect.x() + boxRect.width() / 2, box Rect.y() + font.fontMetrics().ascent()); | 428 FloatPoint emphasisMarkTextOrigin(boxRect.x() + boxRect.width() / 2, box Rect.y() + font.fontMetrics().ascent()); |
432 context->concatCTM(InlineTextBox::rotation(boxRect, InlineTextBox::Clock wise)); | 429 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); | 430 paintText(context, combinedText->originalFont(), objectReplacementCharac terTextRun, emphasisMark, emphasisMarkOffset, 0, 1, 1, emphasisMarkTextOrigin, b oxRect); |
434 context->concatCTM(InlineTextBox::rotation(boxRect, InlineTextBox::Count erclockwise)); | 431 context->concatCTM(InlineTextBox::rotation(boxRect, InlineTextBox::Count erclockwise)); |
435 } else { | 432 } else { |
436 paintTextWithShadows(context, font, textRun, emphasisMark, emphasisMarkO ffset, startOffset, endOffset, paintRunLength, textOrigin, boxRect, textShadow, horizontal); | 433 paintText(context, font, textRun, emphasisMark, emphasisMarkOffset, star tOffset, endOffset, paintRunLength, textOrigin, boxRect); |
437 } | 434 } |
435 | |
436 context->clearShadow(); | |
f(malita)
2014/08/15 02:01:06
Also, is it correct to do this unconditionally (ca
f(malita)
2014/08/15 02:01:06
This feels unbalanced: we're setting up shadows in
jbroman
2014/08/19 18:00:43
We'd have a number of issues were this possible. I
jbroman
2014/08/19 18:00:43
I tried to move this, but it's logic common to pai
| |
438 } | 437 } |
439 | 438 |
440 bool InlineTextBox::getEmphasisMarkPosition(RenderStyle* style, TextEmphasisPosi tion& emphasisPosition) const | 439 bool InlineTextBox::getEmphasisMarkPosition(RenderStyle* style, TextEmphasisPosi tion& emphasisPosition) const |
441 { | 440 { |
442 // This function returns true if there are text emphasis marks and they are suppressed by ruby text. | 441 // This function returns true if there are text emphasis marks and they are suppressed by ruby text. |
443 if (style->textEmphasisMark() == TextEmphasisMarkNone) | 442 if (style->textEmphasisMark() == TextEmphasisMarkNone) |
444 return false; | 443 return false; |
445 | 444 |
446 emphasisPosition = style->textEmphasisPosition(); | 445 emphasisPosition = style->textEmphasisPosition(); |
447 if (emphasisPosition == TextEmphasisPositionUnder) | 446 if (emphasisPosition == TextEmphasisPositionUnder) |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
685 int endOffset = length; | 684 int endOffset = length; |
686 if (paintSelectedTextSeparately && ePos > sPos) { | 685 if (paintSelectedTextSeparately && ePos > sPos) { |
687 startOffset = ePos; | 686 startOffset = ePos; |
688 endOffset = sPos; | 687 endOffset = sPos; |
689 } | 688 } |
690 | 689 |
691 // For stroked painting, we have to change the text drawing mode. It's probably dangerous to leave that mutated as a side | 690 // 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. | 691 // effect, so only when we know we're stroking, do a save/restore. |
693 GraphicsContextStateSaver stateSaver(*context, textStyle.strokeWidth > 0 ); | 692 GraphicsContextStateSaver stateSaver(*context, textStyle.strokeWidth > 0 ); |
694 | 693 |
695 updateGraphicsContext(context, textStyle.fillColor, textStyle.strokeColo r, textStyle.strokeWidth); | 694 updateGraphicsContext(context, textStyle.fillColor, textStyle.strokeColo r, textStyle.strokeWidth, textStyle.shadow, isHorizontal()); |
696 paintTextWithShadows(context, font, textRun, nullAtom, 0, startOffset, e ndOffset, length, textOrigin, boxRect, textStyle.shadow, isHorizontal()); | 695 paintText(context, font, textRun, nullAtom, 0, startOffset, endOffset, l ength, textOrigin, boxRect); |
697 | 696 |
698 if (!emphasisMark.isEmpty()) | 697 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()); | 698 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 } | 699 } |
701 | 700 |
702 if ((paintSelectedTextOnly || paintSelectedTextSeparately) && sPos < ePos) { | 701 if ((paintSelectedTextOnly || paintSelectedTextSeparately) && sPos < ePos) { |
703 // paint only the text that is selected | 702 // paint only the text that is selected |
704 GraphicsContextStateSaver stateSaver(*context, selectionStyle.strokeWidt h > 0); | 703 GraphicsContextStateSaver stateSaver(*context, selectionStyle.strokeWidt h > 0); |
705 | 704 |
706 updateGraphicsContext(context, selectionStyle.fillColor, selectionStyle. strokeColor, selectionStyle.strokeWidth); | 705 updateGraphicsContext(context, selectionStyle.fillColor, selectionStyle. strokeColor, selectionStyle.strokeWidth, selectionStyle.shadow, isHorizontal()); |
707 paintTextWithShadows(context, font, textRun, nullAtom, 0, sPos, ePos, le ngth, textOrigin, boxRect, selectionStyle.shadow, isHorizontal()); | 706 paintText(context, font, textRun, nullAtom, 0, sPos, ePos, length, textO rigin, boxRect); |
708 | 707 |
709 if (!emphasisMark.isEmpty()) | 708 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()); | 709 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 && paintInfo.phase != PaintPhaseSe lection) { |
716 updateGraphicsContext(context, textStyle.fillColor, textStyle.strokeColo r, textStyle.strokeWidth); | 715 updateGraphicsContext(context, textStyle.fillColor, textStyle.strokeColo r, textStyle.strokeWidth, textStyle.shadow, isHorizontal()); |
717 if (combinedText) | 716 if (combinedText) |
718 context->concatCTM(rotation(boxRect, Clockwise)); | 717 context->concatCTM(rotation(boxRect, Clockwise)); |
719 paintDecoration(context, boxOrigin, textDecorations, textStyle.shadow); | 718 paintDecoration(context, boxOrigin, textDecorations, textStyle.shadow); |
720 if (combinedText) | 719 if (combinedText) |
721 context->concatCTM(rotation(boxRect, Counterclockwise)); | 720 context->concatCTM(rotation(boxRect, Counterclockwise)); |
722 } | 721 } |
723 | 722 |
723 // Text and decoration painting may have used shadows. | |
724 // It might be cleaner to use a GraphicsContextStateSaver. | |
f(malita)
2014/08/15 02:01:06
If shadows require nesting semantics we should def
jbroman
2014/08/19 18:00:43
I don't think they do. There's certainly no layout
| |
725 context->clearDrawLooper(); | |
f(malita)
2014/08/15 02:01:06
This may need to happen before paint decorations a
jbroman
2014/08/19 18:00:43
We couldn't, only because of the explicit clear in
| |
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) { |
732 if (it->color == Color::transparent) | 735 if (it->color == Color::transparent) |
733 continue; | 736 continue; |
(...skipping 792 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1526 printedCharacters = fprintf(stderr, "\t%s %p", obj.renderName(), &obj); | 1529 printedCharacters = fprintf(stderr, "\t%s %p", obj.renderName(), &obj); |
1527 const int rendererCharacterOffset = 24; | 1530 const int rendererCharacterOffset = 24; |
1528 for (; printedCharacters < rendererCharacterOffset; printedCharacters++) | 1531 for (; printedCharacters < rendererCharacterOffset; printedCharacters++) |
1529 fputc(' ', stderr); | 1532 fputc(' ', stderr); |
1530 fprintf(stderr, "(%d,%d) \"%s\"\n", start(), start() + len(), value.utf8().d ata()); | 1533 fprintf(stderr, "(%d,%d) \"%s\"\n", start(), start() + len(), value.utf8().d ata()); |
1531 } | 1534 } |
1532 | 1535 |
1533 #endif | 1536 #endif |
1534 | 1537 |
1535 } // namespace blink | 1538 } // namespace blink |
OLD | NEW |