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 16 matching lines...) Expand all Loading... |
27 #include "core/dom/DocumentMarkerController.h" | 27 #include "core/dom/DocumentMarkerController.h" |
28 #include "core/dom/RenderedDocumentMarker.h" | 28 #include "core/dom/RenderedDocumentMarker.h" |
29 #include "core/dom/Text.h" | 29 #include "core/dom/Text.h" |
30 #include "core/dom/WebCoreMemoryInstrumentation.h" | 30 #include "core/dom/WebCoreMemoryInstrumentation.h" |
31 #include "core/editing/Editor.h" | 31 #include "core/editing/Editor.h" |
32 #include "core/page/Chrome.h" | 32 #include "core/page/Chrome.h" |
33 #include "core/page/ChromeClient.h" | 33 #include "core/page/ChromeClient.h" |
34 #include "core/page/Frame.h" | 34 #include "core/page/Frame.h" |
35 #include "core/page/Page.h" | 35 #include "core/page/Page.h" |
36 #include "core/page/Settings.h" | 36 #include "core/page/Settings.h" |
| 37 #include "core/platform/graphics/DrawLooper.h" |
37 #include "core/platform/graphics/FontCache.h" | 38 #include "core/platform/graphics/FontCache.h" |
38 #include "core/platform/graphics/GraphicsContextStateSaver.h" | 39 #include "core/platform/graphics/GraphicsContextStateSaver.h" |
39 #include "core/rendering/EllipsisBox.h" | 40 #include "core/rendering/EllipsisBox.h" |
40 #include "core/rendering/HitTestResult.h" | 41 #include "core/rendering/HitTestResult.h" |
41 #include "core/rendering/PaintInfo.h" | 42 #include "core/rendering/PaintInfo.h" |
42 #include "core/rendering/RenderArena.h" | 43 #include "core/rendering/RenderArena.h" |
43 #include "core/rendering/RenderBR.h" | 44 #include "core/rendering/RenderBR.h" |
44 #include "core/rendering/RenderBlock.h" | 45 #include "core/rendering/RenderBlock.h" |
45 #include "core/rendering/RenderCombineText.h" | 46 #include "core/rendering/RenderCombineText.h" |
46 #include "core/rendering/RenderRubyRun.h" | 47 #include "core/rendering/RenderRubyRun.h" |
47 #include "core/rendering/RenderRubyText.h" | 48 #include "core/rendering/RenderRubyText.h" |
48 #include "core/rendering/RenderTheme.h" | 49 #include "core/rendering/RenderTheme.h" |
49 #include "core/rendering/break_lines.h" | 50 #include "core/rendering/break_lines.h" |
| 51 #include "core/rendering/style/ShadowData.h" |
50 #include "core/rendering/svg/SVGTextRunRenderingContext.h" | 52 #include "core/rendering/svg/SVGTextRunRenderingContext.h" |
51 #include <wtf/text/CString.h> | 53 #include "wtf/Vector.h" |
| 54 #include "wtf/text/CString.h" |
52 | 55 |
53 using namespace std; | 56 using namespace std; |
54 | 57 |
55 namespace WebCore { | 58 namespace WebCore { |
56 | 59 |
57 typedef WTF::HashMap<const InlineTextBox*, LayoutRect> InlineTextBoxOverflowMap; | 60 typedef WTF::HashMap<const InlineTextBox*, LayoutRect> InlineTextBoxOverflowMap; |
58 static InlineTextBoxOverflowMap* gTextBoxesWithOverflow; | 61 static InlineTextBoxOverflowMap* gTextBoxesWithOverflow; |
59 | 62 |
60 static const int misspellingLineThickness = 3; | 63 static const int misspellingLineThickness = 3; |
61 | 64 |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 FloatRect shadowRect(textRect); | 405 FloatRect shadowRect(textRect); |
403 shadowRect.inflate(shadowBlur); | 406 shadowRect.inflate(shadowBlur); |
404 shadowRect.move(shadowOffset); | 407 shadowRect.move(shadowOffset); |
405 context->save(); | 408 context->save(); |
406 context->clip(shadowRect); | 409 context->clip(shadowRect); |
407 | 410 |
408 extraOffset = FloatSize(0, 2 * textRect.height() + max(0.0f, shadowOffse
t.height()) + shadowBlur); | 411 extraOffset = FloatSize(0, 2 * textRect.height() + max(0.0f, shadowOffse
t.height()) + shadowBlur); |
409 shadowOffset -= extraOffset; | 412 shadowOffset -= extraOffset; |
410 } | 413 } |
411 | 414 |
412 context->setShadow(shadowOffset, shadowBlur, shadowColor, context->fillColor
Space()); | 415 context->setShadow(shadowOffset, shadowBlur, shadowColor); |
413 return extraOffset; | 416 return extraOffset; |
414 } | 417 } |
415 | 418 |
416 static void paintTextWithShadows(GraphicsContext* context, const Font& font, con
st TextRun& textRun, | 419 static void paintTextWithShadows(GraphicsContext* context, const Font& font, con
st TextRun& textRun, |
417 const AtomicString& emphasisMark, int emphasisM
arkOffset, | 420 const AtomicString& emphasisMark, int emphasisM
arkOffset, |
418 int startOffset, int endOffset, int truncationP
oint, | 421 int startOffset, int endOffset, int truncationP
oint, |
419 const FloatPoint& textOrigin, const FloatRect&
boxRect, | 422 const FloatPoint& textOrigin, const FloatRect&
boxRect, |
420 const ShadowData* shadow, bool stroked, bool ho
rizontal) | 423 const ShadowData* shadow, bool stroked, bool ho
rizontal) |
421 { | 424 { |
| 425 bool hasShadow = !!shadow; |
422 Color fillColor = context->fillColor(); | 426 Color fillColor = context->fillColor(); |
423 ColorSpace fillColorSpace = context->fillColorSpace(); | 427 |
424 bool opaque = fillColor.alpha() == 255; | 428 if (hasShadow) { |
425 if (!opaque) | 429 // FIXME: it would be better if we could get the shadows top-to-bottom f
rom the style. |
426 context->setFillColor(Color::black, fillColorSpace); | 430 Vector<const ShadowData*, 4> shadows; |
| 431 do { |
| 432 shadows.append(shadow); |
| 433 } while (shadow = shadow->next()); |
| 434 |
| 435 DrawLooper drawLooper; |
| 436 drawLooper.addUnmodifiedContent(); |
| 437 for (int i = shadows.size() - 1; i >= 0; i--) { |
| 438 shadow = shadows[i]; |
| 439 int shadowX = horizontal ? shadow->x() : shadow->y(); |
| 440 int shadowY = horizontal ? shadow->y() : -shadow->x(); |
| 441 FloatSize offset(shadowX, shadowY); |
| 442 drawLooper.addShadow(offset, shadow->blur(), shadow->color(), |
| 443 DrawLooper::ShadowRespectsTransforms, DrawLooper::ShadowIgnoresA
lpha); |
| 444 } |
| 445 context->setDrawLooper(drawLooper); |
| 446 } |
427 | 447 |
428 TextRunPaintInfo textRunPaintInfo(textRun); | 448 TextRunPaintInfo textRunPaintInfo(textRun); |
429 textRunPaintInfo.bounds = boxRect; | 449 textRunPaintInfo.bounds = boxRect; |
430 do { | 450 if (startOffset <= endOffset) { |
431 IntSize extraOffset; | 451 textRunPaintInfo.from = startOffset; |
432 if (shadow) | 452 textRunPaintInfo.to = endOffset; |
433 extraOffset = roundedIntSize(InlineTextBox::applyShadowToGraphicsCon
text(context, shadow, boxRect, stroked, opaque, horizontal)); | 453 if (emphasisMark.isEmpty()) |
434 else if (!opaque) | 454 context->drawText(font, textRunPaintInfo, textOrigin); |
435 context->setFillColor(fillColor, fillColorSpace); | 455 else |
436 | 456 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisMark, tex
tOrigin + IntSize(0, emphasisMarkOffset)); |
437 if (startOffset <= endOffset) { | 457 } else { |
438 textRunPaintInfo.from = startOffset; | 458 if (endOffset > 0) { |
| 459 textRunPaintInfo.from = 0; |
439 textRunPaintInfo.to = endOffset; | 460 textRunPaintInfo.to = endOffset; |
440 if (emphasisMark.isEmpty()) | 461 if (emphasisMark.isEmpty()) |
441 context->drawText(font, textRunPaintInfo, textOrigin + extraOffs
et); | 462 context->drawText(font, textRunPaintInfo, textOrigin); |
442 else | 463 else |
443 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisMark,
textOrigin + extraOffset + IntSize(0, emphasisMarkOffset)); | 464 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisMark,
textOrigin + IntSize(0, emphasisMarkOffset)); |
444 } else { | |
445 if (endOffset > 0) { | |
446 textRunPaintInfo.from = 0; | |
447 textRunPaintInfo.to = endOffset; | |
448 if (emphasisMark.isEmpty()) | |
449 context->drawText(font, textRunPaintInfo, textOrigin + extra
Offset); | |
450 else | |
451 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisM
ark, textOrigin + extraOffset + IntSize(0, emphasisMarkOffset)); | |
452 } | |
453 if (startOffset < truncationPoint) { | |
454 textRunPaintInfo.from = startOffset; | |
455 textRunPaintInfo.to = truncationPoint; | |
456 if (emphasisMark.isEmpty()) | |
457 context->drawText(font, textRunPaintInfo, textOrigin + extra
Offset); | |
458 else | |
459 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisM
ark, textOrigin + extraOffset + IntSize(0, emphasisMarkOffset)); | |
460 } | |
461 } | 465 } |
| 466 if (startOffset < truncationPoint) { |
| 467 textRunPaintInfo.from = startOffset; |
| 468 textRunPaintInfo.to = truncationPoint; |
| 469 if (emphasisMark.isEmpty()) |
| 470 context->drawText(font, textRunPaintInfo, textOrigin); |
| 471 else |
| 472 context->drawEmphasisMarks(font, textRunPaintInfo, emphasisMark,
textOrigin + IntSize(0, emphasisMarkOffset)); |
| 473 } |
| 474 } |
462 | 475 |
463 if (!shadow) | 476 if (hasShadow) |
464 break; | 477 context->clearDrawLooper(); |
465 | |
466 if (shadow->next() || stroked || !opaque) | |
467 context->restore(); | |
468 else | |
469 context->clearShadow(); | |
470 | |
471 shadow = shadow->next(); | |
472 } while (shadow || stroked || !opaque); | |
473 } | 478 } |
474 | 479 |
475 bool InlineTextBox::getEmphasisMarkPosition(RenderStyle* style, TextEmphasisPosi
tion& emphasisPosition) const | 480 bool InlineTextBox::getEmphasisMarkPosition(RenderStyle* style, TextEmphasisPosi
tion& emphasisPosition) const |
476 { | 481 { |
477 // This function returns true if there are text emphasis marks and they are
suppressed by ruby text. | 482 // This function returns true if there are text emphasis marks and they are
suppressed by ruby text. |
478 if (style->textEmphasisMark() == TextEmphasisMarkNone) | 483 if (style->textEmphasisMark() == TextEmphasisMarkNone) |
479 return false; | 484 return false; |
480 | 485 |
481 emphasisPosition = style->textEmphasisPosition(); | 486 emphasisPosition = style->textEmphasisPosition(); |
482 if (emphasisPosition == TextEmphasisPositionUnder) | 487 if (emphasisPosition == TextEmphasisPositionUnder) |
(...skipping 679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1162 | 1167 |
1163 do { | 1168 do { |
1164 if (shadow) { | 1169 if (shadow) { |
1165 if (!shadow->next()) { | 1170 if (!shadow->next()) { |
1166 // The last set of lines paints normally inside the clip. | 1171 // The last set of lines paints normally inside the clip. |
1167 localOrigin.move(0, -extraOffset); | 1172 localOrigin.move(0, -extraOffset); |
1168 extraOffset = 0; | 1173 extraOffset = 0; |
1169 } | 1174 } |
1170 int shadowX = isHorizontal() ? shadow->x() : shadow->y(); | 1175 int shadowX = isHorizontal() ? shadow->x() : shadow->y(); |
1171 int shadowY = isHorizontal() ? shadow->y() : -shadow->x(); | 1176 int shadowY = isHorizontal() ? shadow->y() : -shadow->x(); |
1172 context->setShadow(FloatSize(shadowX, shadowY - extraOffset), shadow
->blur(), shadow->color(), colorSpace); | 1177 context->setShadow(FloatSize(shadowX, shadowY - extraOffset), shadow
->blur(), shadow->color()); |
1173 setShadow = true; | 1178 setShadow = true; |
1174 shadow = shadow->next(); | 1179 shadow = shadow->next(); |
1175 } | 1180 } |
1176 | 1181 |
1177 #if ENABLE(CSS3_TEXT) | 1182 #if ENABLE(CSS3_TEXT) |
1178 // Offset between lines - always non-zero, so lines never cross each oth
er. | 1183 // Offset between lines - always non-zero, so lines never cross each oth
er. |
1179 float doubleOffset = textDecorationThickness + 1.f; | 1184 float doubleOffset = textDecorationThickness + 1.f; |
1180 #endif // CSS3_TEXT | 1185 #endif // CSS3_TEXT |
1181 context->setStrokeStyle(textDecorationStyleToStrokeStyle(decorationStyle
)); | 1186 context->setStrokeStyle(textDecorationStyleToStrokeStyle(decorationStyle
)); |
1182 if (deco & UNDERLINE) { | 1187 if (deco & UNDERLINE) { |
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1612 | 1617 |
1613 void InlineTextBox::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const | 1618 void InlineTextBox::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const |
1614 { | 1619 { |
1615 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::Rendering); | 1620 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::Rendering); |
1616 InlineBox::reportMemoryUsage(memoryObjectInfo); | 1621 InlineBox::reportMemoryUsage(memoryObjectInfo); |
1617 info.addMember(m_prevTextBox, "prevTextBox"); | 1622 info.addMember(m_prevTextBox, "prevTextBox"); |
1618 info.addMember(m_nextTextBox, "nextTextBox"); | 1623 info.addMember(m_nextTextBox, "nextTextBox"); |
1619 } | 1624 } |
1620 | 1625 |
1621 } // namespace WebCore | 1626 } // namespace WebCore |
OLD | NEW |