summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/InlineTextBox.cpp
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@digia.com>2013-09-13 12:51:20 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-19 20:50:05 +0200
commitd441d6f39bb846989d95bcf5caf387b42414718d (patch)
treee367e64a75991c554930278175d403c072de6bb8 /Source/WebCore/rendering/InlineTextBox.cpp
parent0060b2994c07842f4c59de64b5e3e430525c4b90 (diff)
downloadqtwebkit-d441d6f39bb846989d95bcf5caf387b42414718d.tar.gz
Import Qt5x2 branch of QtWebkit for Qt 5.2
Importing a new snapshot of webkit. Change-Id: I2d01ad12cdc8af8cb015387641120a9d7ea5f10c Reviewed-by: Allan Sandfeld Jensen <allan.jensen@digia.com>
Diffstat (limited to 'Source/WebCore/rendering/InlineTextBox.cpp')
-rw-r--r--Source/WebCore/rendering/InlineTextBox.cpp324
1 files changed, 272 insertions, 52 deletions
diff --git a/Source/WebCore/rendering/InlineTextBox.cpp b/Source/WebCore/rendering/InlineTextBox.cpp
index 56ab76cc8..49e2e1dd0 100644
--- a/Source/WebCore/rendering/InlineTextBox.cpp
+++ b/Source/WebCore/rendering/InlineTextBox.cpp
@@ -47,13 +47,20 @@
#include "SVGTextRunRenderingContext.h"
#include "Text.h"
#include "break_lines.h"
-#include <wtf/AlwaysInline.h>
#include <wtf/text/CString.h>
using namespace std;
namespace WebCore {
+struct SameSizeAsInlineTextBox : public InlineBox {
+ unsigned variables[1];
+ unsigned short variables2[2];
+ void* pointers[2];
+};
+
+COMPILE_ASSERT(sizeof(InlineTextBox) == sizeof(SameSizeAsInlineTextBox), InlineTextBox_should_stay_small);
+
typedef WTF::HashMap<const InlineTextBox*, LayoutRect> InlineTextBoxOverflowMap;
static InlineTextBoxOverflowMap* gTextBoxesWithOverflow;
@@ -205,7 +212,12 @@ LayoutRect InlineTextBox::localSelectionRect(int startPos, int endPos)
if (respectHyphen)
endPos = textRun.length();
- LayoutRect r = enclosingIntRect(font.selectionRectForText(textRun, FloatPoint(logicalLeft(), selTop), selHeight, sPos, ePos));
+ FloatPoint startingPoint = FloatPoint(logicalLeft(), selTop);
+ LayoutRect r;
+ if (sPos || ePos != static_cast<int>(m_len))
+ r = enclosingIntRect(font.selectionRectForText(textRun, startingPoint, selHeight, sPos, ePos));
+ else // Avoid computing the font width when the entire line box is selected as an optimization.
+ r = enclosingIntRect(FloatRect(startingPoint, FloatSize(m_logicalWidth, selHeight)));
LayoutUnit logicalWidth = r.width();
if (r.x() > logicalRight())
@@ -285,7 +297,7 @@ float InlineTextBox::placeEllipsisBox(bool flowIsLTR, float visibleLeftEdge, flo
// and the ellipsis edge.
m_truncation = cFullTruncation;
truncatedWidth += ellipsisWidth;
- return min(ellipsisX, x());
+ return flowIsLTR ? min(ellipsisX, x()) : max(ellipsisX, right() - ellipsisWidth);
}
// Set the truncation index on the text run.
@@ -360,13 +372,29 @@ bool InlineTextBox::isLineBreak() const
bool InlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit /* lineTop */, LayoutUnit /*lineBottom*/)
{
+ if (!visibleToHitTesting())
+ return false;
+
if (isLineBreak())
return false;
- FloatPoint boxOrigin = locationIncludingFlipping();
- boxOrigin.moveBy(accumulatedOffset);
- FloatRect rect(boxOrigin, size());
- if (m_truncation != cFullTruncation && visibleToHitTesting() && locationInContainer.intersects(rect)) {
+ if (m_truncation == cFullTruncation)
+ return false;
+
+ FloatRect rect(locationIncludingFlipping(), size());
+ // Make sure truncated text is ignored while hittesting.
+ if (m_truncation != cNoTruncation) {
+ LayoutUnit widthOfVisibleText = toRenderText(renderer())->width(m_start, m_truncation, textPos(), isFirstLineStyle());
+
+ if (isHorizontal())
+ renderer()->style()->isLeftToRightDirection() ? rect.setWidth(widthOfVisibleText) : rect.shiftXEdgeTo(right() - widthOfVisibleText);
+ else
+ rect.setHeight(widthOfVisibleText);
+ }
+
+ rect.moveBy(accumulatedOffset);
+
+ if (locationInContainer.intersects(rect)) {
renderer()->updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - toLayoutSize(accumulatedOffset)));
if (!result.addNodeToRectBasedTestResult(renderer()->node(), request, locationInContainer, rect))
return true;
@@ -383,21 +411,21 @@ FloatSize InlineTextBox::applyShadowToGraphicsContext(GraphicsContext* context,
int shadowX = horizontal ? shadow->x() : shadow->y();
int shadowY = horizontal ? shadow->y() : -shadow->x();
FloatSize shadowOffset(shadowX, shadowY);
- int shadowBlur = shadow->blur();
+ int shadowRadius = shadow->radius();
const Color& shadowColor = shadow->color();
if (shadow->next() || stroked || !opaque) {
FloatRect shadowRect(textRect);
- shadowRect.inflate(shadowBlur);
+ shadowRect.inflate(shadow->paintingExtent());
shadowRect.move(shadowOffset);
context->save();
context->clip(shadowRect);
- extraOffset = FloatSize(0, 2 * textRect.height() + max(0.0f, shadowOffset.height()) + shadowBlur);
+ extraOffset = FloatSize(0, 2 * textRect.height() + max(0.0f, shadowOffset.height()) + shadowRadius);
shadowOffset -= extraOffset;
}
- context->setShadow(shadowOffset, shadowBlur, shadowColor, context->fillColorSpace());
+ context->setShadow(shadowOffset, shadowRadius, shadowColor, context->fillColorSpace());
return extraOffset;
}
@@ -428,7 +456,8 @@ static void paintTextWithShadows(GraphicsContext* context, const Font& font, con
context->drawText(font, textRun, textOrigin + extraOffset, 0, endOffset);
else
context->drawEmphasisMarks(font, textRun, emphasisMark, textOrigin + extraOffset + IntSize(0, emphasisMarkOffset), 0, endOffset);
- } if (startOffset < truncationPoint) {
+ }
+ if (startOffset < truncationPoint) {
if (emphasisMark.isEmpty())
context->drawText(font, textRun, textOrigin + extraOffset, startOffset, truncationPoint);
else
@@ -520,7 +549,6 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
// truncated string i.e. |Hello|CBA| -> |...lo|CBA|
LayoutUnit widthOfVisibleText = toRenderText(renderer())->width(m_start, m_truncation, textPos(), isFirstLineStyle());
LayoutUnit widthOfHiddenText = m_logicalWidth - widthOfVisibleText;
- // FIXME: The hit testing logic also needs to take this translation into account.
LayoutSize truncationOffset(isLeftToRightDirection() ? widthOfHiddenText : -widthOfHiddenText, 0);
adjustedPaintOffset.move(isHorizontal() ? truncationOffset : truncationOffset.transposedSize());
}
@@ -543,17 +571,17 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
context->concatCTM(rotation(boxRect, Clockwise));
// Determine whether or not we have composition underlines to draw.
- bool containsComposition = renderer()->node() && renderer()->frame()->editor()->compositionNode() == renderer()->node();
- bool useCustomUnderlines = containsComposition && renderer()->frame()->editor()->compositionUsesCustomUnderlines();
+ bool containsComposition = renderer()->node() && renderer()->frame()->editor().compositionNode() == renderer()->node();
+ bool useCustomUnderlines = containsComposition && renderer()->frame()->editor().compositionUsesCustomUnderlines();
// Determine the text colors and selection colors.
Color textFillColor;
Color textStrokeColor;
Color emphasisMarkColor;
float textStrokeWidth = styleToUse->textStrokeWidth();
- const ShadowData* textShadow = paintInfo.forceBlackText ? 0 : styleToUse->textShadow();
+ const ShadowData* textShadow = paintInfo.forceBlackText() ? 0 : styleToUse->textShadow();
- if (paintInfo.forceBlackText) {
+ if (paintInfo.forceBlackText()) {
textFillColor = Color::black;
textStrokeColor = Color::black;
emphasisMarkColor = Color::black;
@@ -595,14 +623,14 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
const ShadowData* selectionShadow = textShadow;
if (haveSelection) {
// Check foreground color first.
- Color foreground = paintInfo.forceBlackText ? Color::black : renderer()->selectionForegroundColor();
+ Color foreground = paintInfo.forceBlackText() ? Color::black : renderer()->selectionForegroundColor();
if (foreground.isValid() && foreground != selectionFillColor) {
if (!paintSelectedTextOnly)
paintSelectedTextSeparately = true;
selectionFillColor = foreground;
}
- Color emphasisMarkForeground = paintInfo.forceBlackText ? Color::black : renderer()->selectionEmphasisMarkColor();
+ Color emphasisMarkForeground = paintInfo.forceBlackText() ? Color::black : renderer()->selectionEmphasisMarkColor();
if (emphasisMarkForeground.isValid() && emphasisMarkForeground != selectionEmphasisMarkColor) {
if (!paintSelectedTextOnly)
paintSelectedTextSeparately = true;
@@ -610,7 +638,7 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
}
if (RenderStyle* pseudoStyle = renderer()->getCachedPseudoStyle(SELECTION)) {
- const ShadowData* shadow = paintInfo.forceBlackText ? 0 : pseudoStyle->textShadow();
+ const ShadowData* shadow = paintInfo.forceBlackText() ? 0 : pseudoStyle->textShadow();
if (shadow != selectionShadow) {
if (!paintSelectedTextOnly)
paintSelectedTextSeparately = true;
@@ -624,7 +652,7 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
selectionStrokeWidth = strokeWidth;
}
- Color stroke = paintInfo.forceBlackText ? Color::black : pseudoStyle->visitedDependentColor(CSSPropertyWebkitTextStrokeColor);
+ Color stroke = paintInfo.forceBlackText() ? Color::black : pseudoStyle->visitedDependentColor(CSSPropertyWebkitTextStrokeColor);
if (stroke != selectionStrokeColor) {
if (!paintSelectedTextOnly)
paintSelectedTextSeparately = true;
@@ -652,8 +680,8 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
if (containsComposition && !useCustomUnderlines)
paintCompositionBackground(context, boxOrigin, styleToUse, font,
- renderer()->frame()->editor()->compositionStart(),
- renderer()->frame()->editor()->compositionEnd());
+ renderer()->frame()->editor().compositionStart(),
+ renderer()->frame()->editor().compositionEnd());
paintDocumentMarkers(context, boxOrigin, styleToUse, font, true);
@@ -679,7 +707,7 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
if (!combinedText) {
string = textRenderer()->text();
if (static_cast<unsigned>(length) != string.length() || m_start) {
- ASSERT(static_cast<unsigned>(m_start + length) <= string.length());
+ ASSERT_WITH_SECURITY_IMPLICATION(static_cast<unsigned>(m_start + length) <= string.length());
string = string.substringSharingImpl(m_start, length);
}
maximumLength = textRenderer()->textLength() - m_start;
@@ -766,17 +794,21 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
}
// Paint decorations
- ETextDecoration textDecorations = styleToUse->textDecorationsInEffect();
- if (textDecorations != TDNONE && paintInfo.phase != PaintPhaseSelection) {
+ TextDecoration textDecorations = styleToUse->textDecorationsInEffect();
+ if (textDecorations != TextDecorationNone && paintInfo.phase != PaintPhaseSelection) {
updateGraphicsContext(context, textFillColor, textStrokeColor, textStrokeWidth, styleToUse->colorSpace());
+ if (combinedText)
+ context->concatCTM(rotation(boxRect, Clockwise));
paintDecoration(context, boxOrigin, textDecorations, styleToUse->textDecorationStyle(), textShadow);
+ if (combinedText)
+ context->concatCTM(rotation(boxRect, Counterclockwise));
}
if (paintInfo.phase == PaintPhaseForeground) {
paintDocumentMarkers(context, boxOrigin, styleToUse, font, false);
if (useCustomUnderlines) {
- const Vector<CompositionUnderline>& underlines = renderer()->frame()->editor()->customCompositionUnderlines();
+ const Vector<CompositionUnderline>& underlines = renderer()->frame()->editor().customCompositionUnderlines();
size_t numUnderlines = underlines.size();
for (size_t index = 0; index < numUnderlines; ++index) {
@@ -859,7 +891,7 @@ void InlineTextBox::paintSelection(GraphicsContext* context, const FloatPoint& b
String string = textRenderer()->text();
if (string.length() != static_cast<unsigned>(length) || m_start) {
- ASSERT(static_cast<unsigned>(m_start + length) <= string.length());
+ ASSERT_WITH_SECURITY_IMPLICATION(static_cast<unsigned>(m_start + length) <= string.length());
string = string.substringSharingImpl(m_start, length);
}
@@ -920,7 +952,7 @@ void InlineTextBox::paintCustomHighlight(const LayoutPoint& paintOffset, const A
FloatRect rootRect(paintOffset.x() + r->x(), paintOffset.y() + selectionTop(), r->logicalWidth(), selectionHeight());
FloatRect textRect(paintOffset.x() + x(), rootRect.y(), logicalWidth(), rootRect.height());
- page->chrome()->client()->paintCustomHighlight(renderer()->node(), type, textRect, rootRect, true, false);
+ page->chrome().client()->paintCustomHighlight(renderer()->node(), type, textRect, rootRect, true, false);
}
#endif
@@ -943,7 +975,6 @@ static StrokeStyle textDecorationStyleToStrokeStyle(TextDecorationStyle decorati
strokeStyle = DashedStroke;
break;
case TextDecorationStyleWavy:
- // FIXME: https://bugs.webkit.org/show_bug.cgi?id=92868 - Needs platform support.
strokeStyle = WavyStroke;
break;
#endif // CSS3_TEXT
@@ -952,7 +983,158 @@ static StrokeStyle textDecorationStyleToStrokeStyle(TextDecorationStyle decorati
return strokeStyle;
}
-void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint& boxOrigin, ETextDecoration deco, TextDecorationStyle decorationStyle, const ShadowData* shadow)
+#if ENABLE(CSS3_TEXT)
+static int computeUnderlineOffset(const TextUnderlinePosition underlinePosition, const FontMetrics& fontMetrics, const InlineTextBox* inlineTextBox, const int textDecorationThickness)
+{
+ // Compute the gap between the font and the underline. Use at least one
+ // pixel gap, if underline is thick then use a bigger gap.
+ const int gap = max<int>(1, ceilf(textDecorationThickness / 2.0));
+
+ // According to the specification TextUnderlinePositionAuto should default to 'alphabetic' for horizontal text
+ // and to 'under Left' for vertical text (e.g. japanese). We support only horizontal text for now.
+ switch (underlinePosition) {
+ case TextUnderlinePositionAlphabetic:
+ case TextUnderlinePositionAuto:
+ return fontMetrics.ascent() + gap; // Position underline near the alphabetic baseline.
+ case TextUnderlinePositionUnder: {
+ // Position underline relative to the under edge of the lowest element's content box.
+ const float offset = inlineTextBox->root()->maxLogicalTop() - inlineTextBox->logicalTop();
+ if (offset > 0)
+ return inlineTextBox->logicalHeight() + gap + offset;
+ return inlineTextBox->logicalHeight() + gap;
+ }
+ }
+
+ ASSERT_NOT_REACHED();
+ return fontMetrics.ascent() + gap;
+}
+#endif // CSS3_TEXT
+
+#if ENABLE(CSS3_TEXT)
+static void adjustStepToDecorationLength(float& step, float& controlPointDistance, float length)
+{
+ ASSERT(step > 0);
+
+ if (length <= 0)
+ return;
+
+ unsigned stepCount = static_cast<unsigned>(length / step);
+
+ // Each Bezier curve starts at the same pixel that the previous one
+ // ended. We need to subtract (stepCount - 1) pixels when calculating the
+ // length covered to account for that.
+ float uncoveredLength = length - (stepCount * step - (stepCount - 1));
+ float adjustment = uncoveredLength / stepCount;
+ step += adjustment;
+ controlPointDistance += adjustment;
+}
+
+/*
+ * Draw one cubic Bezier curve and repeat the same pattern long the the decoration's axis.
+ * The start point (p1), controlPoint1, controlPoint2 and end point (p2) of the Bezier curve
+ * form a diamond shape:
+ *
+ * step
+ * |-----------|
+ *
+ * controlPoint1
+ * +
+ *
+ *
+ * . .
+ * . .
+ * . .
+ * (x1, y1) p1 + . + p2 (x2, y2) - <--- Decoration's axis
+ * . . |
+ * . . |
+ * . . | controlPointDistance
+ * |
+ * |
+ * + -
+ * controlPoint2
+ *
+ * |-----------|
+ * step
+ */
+static void strokeWavyTextDecoration(GraphicsContext* context, FloatPoint& p1, FloatPoint& p2, float strokeThickness)
+{
+ context->adjustLineToPixelBoundaries(p1, p2, strokeThickness, context->strokeStyle());
+
+ Path path;
+ path.moveTo(p1);
+
+ // Distance between decoration's axis and Bezier curve's control points.
+ // The height of the curve is based on this distance. Use a minimum of 6 pixels distance since
+ // the actual curve passes approximately at half of that distance, that is 3 pixels.
+ // The minimum height of the curve is also approximately 3 pixels. Increases the curve's height
+ // as strockThickness increases to make the curve looks better.
+ float controlPointDistance = 3 * max<float>(2, strokeThickness);
+
+ // Increment used to form the diamond shape between start point (p1), control
+ // points and end point (p2) along the axis of the decoration. Makes the
+ // curve wider as strockThickness increases to make the curve looks better.
+ float step = 2 * max<float>(2, strokeThickness);
+
+ bool isVerticalLine = (p1.x() == p2.x());
+
+ if (isVerticalLine) {
+ ASSERT(p1.x() == p2.x());
+
+ float xAxis = p1.x();
+ float y1;
+ float y2;
+
+ if (p1.y() < p2.y()) {
+ y1 = p1.y();
+ y2 = p2.y();
+ } else {
+ y1 = p2.y();
+ y2 = p1.y();
+ }
+
+ adjustStepToDecorationLength(step, controlPointDistance, y2 - y1);
+ FloatPoint controlPoint1(xAxis + controlPointDistance, 0);
+ FloatPoint controlPoint2(xAxis - controlPointDistance, 0);
+
+ for (float y = y1; y + 2 * step <= y2;) {
+ controlPoint1.setY(y + step);
+ controlPoint2.setY(y + step);
+ y += 2 * step;
+ path.addBezierCurveTo(controlPoint1, controlPoint2, FloatPoint(xAxis, y));
+ }
+ } else {
+ ASSERT(p1.y() == p2.y());
+
+ float yAxis = p1.y();
+ float x1;
+ float x2;
+
+ if (p1.x() < p2.x()) {
+ x1 = p1.x();
+ x2 = p2.x();
+ } else {
+ x1 = p2.x();
+ x2 = p1.x();
+ }
+
+ adjustStepToDecorationLength(step, controlPointDistance, x2 - x1);
+ FloatPoint controlPoint1(0, yAxis + controlPointDistance);
+ FloatPoint controlPoint2(0, yAxis - controlPointDistance);
+
+ for (float x = x1; x + 2 * step <= x2;) {
+ controlPoint1.setX(x + step);
+ controlPoint2.setX(x + step);
+ x += 2 * step;
+ path.addBezierCurveTo(controlPoint1, controlPoint2, FloatPoint(x, yAxis));
+ }
+ }
+
+ context->setShouldAntialias(true);
+ context->strokePath(path);
+}
+#endif // CSS3_TEXT
+
+void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint& boxOrigin, TextDecoration deco, TextDecorationStyle decorationStyle, const ShadowData* shadow)
{
// FIXME: We should improve this rule and not always just assume 1.
const float textDecorationThickness = 1.f;
@@ -979,7 +1161,7 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint&
bool isPrinting = textRenderer()->document()->printing();
context->setStrokeThickness(textDecorationThickness);
- bool linesAreOpaque = !isPrinting && (!(deco & UNDERLINE) || underline.alpha() == 255) && (!(deco & OVERLINE) || overline.alpha() == 255) && (!(deco & LINE_THROUGH) || linethrough.alpha() == 255);
+ bool linesAreOpaque = !isPrinting && (!(deco & TextDecorationUnderline) || underline.alpha() == 255) && (!(deco & TextDecorationOverline) || overline.alpha() == 255) && (!(deco & TextDecorationLineThrough) || linethrough.alpha() == 255);
RenderStyle* styleToUse = renderer()->style(isFirstLineStyle());
int baseline = styleToUse->fontMetrics().ascent();
@@ -989,13 +1171,14 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint&
if (!linesAreOpaque && shadow && shadow->next()) {
FloatRect clipRect(localOrigin, FloatSize(width, baseline + 2));
for (const ShadowData* s = shadow; s; s = s->next()) {
+ int shadowExtent = s->paintingExtent();
FloatRect shadowRect(localOrigin, FloatSize(width, baseline + 2));
- shadowRect.inflate(s->blur());
+ shadowRect.inflate(shadowExtent);
int shadowX = isHorizontal() ? s->x() : s->y();
int shadowY = isHorizontal() ? s->y() : -s->x();
shadowRect.move(shadowX, shadowY);
clipRect.unite(shadowRect);
- extraOffset = max(extraOffset, max(0, shadowY) + s->blur());
+ extraOffset = max(extraOffset, max(0, shadowY) + shadowExtent);
}
context->save();
context->clip(clipRect);
@@ -1016,7 +1199,7 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint&
}
int shadowX = isHorizontal() ? shadow->x() : shadow->y();
int shadowY = isHorizontal() ? shadow->y() : -shadow->x();
- context->setShadow(FloatSize(shadowX, shadowY - extraOffset), shadow->blur(), shadow->color(), colorSpace);
+ context->setShadow(FloatSize(shadowX, shadowY - extraOffset), shadow->radius(), shadow->color(), colorSpace);
setShadow = true;
shadow = shadow->next();
}
@@ -1026,29 +1209,66 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint&
float doubleOffset = textDecorationThickness + 1.f;
#endif // CSS3_TEXT
context->setStrokeStyle(textDecorationStyleToStrokeStyle(decorationStyle));
- if (deco & UNDERLINE) {
+ if (deco & TextDecorationUnderline) {
context->setStrokeColor(underline, colorSpace);
+#if ENABLE(CSS3_TEXT)
+ TextUnderlinePosition underlinePosition = styleToUse->textUnderlinePosition();
+ const int underlineOffset = computeUnderlineOffset(underlinePosition, styleToUse->fontMetrics(), this, textDecorationThickness);
+
+ switch (decorationStyle) {
+ case TextDecorationStyleWavy: {
+ FloatPoint start(localOrigin.x(), localOrigin.y() + underlineOffset + doubleOffset);
+ FloatPoint end(localOrigin.x() + width, localOrigin.y() + underlineOffset + doubleOffset);
+ strokeWavyTextDecoration(context, start, end, textDecorationThickness);
+ break;
+ }
+ default:
+ context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + underlineOffset), width, isPrinting);
+
+ if (decorationStyle == TextDecorationStyleDouble)
+ context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + underlineOffset + doubleOffset), width, isPrinting);
+ }
+#else
// Leave one pixel of white between the baseline and the underline.
context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + baseline + 1), width, isPrinting);
-#if ENABLE(CSS3_TEXT)
- if (decorationStyle == TextDecorationStyleDouble)
- context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + baseline + 1 + doubleOffset), width, isPrinting);
#endif // CSS3_TEXT
}
- if (deco & OVERLINE) {
+ if (deco & TextDecorationOverline) {
context->setStrokeColor(overline, colorSpace);
- context->drawLineForText(localOrigin, width, isPrinting);
#if ENABLE(CSS3_TEXT)
- if (decorationStyle == TextDecorationStyleDouble)
- context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() - doubleOffset), width, isPrinting);
+ switch (decorationStyle) {
+ case TextDecorationStyleWavy: {
+ FloatPoint start(localOrigin.x(), localOrigin.y() - doubleOffset);
+ FloatPoint end(localOrigin.x() + width, localOrigin.y() - doubleOffset);
+ strokeWavyTextDecoration(context, start, end, textDecorationThickness);
+ break;
+ }
+ default:
+#endif // CSS3_TEXT
+ context->drawLineForText(localOrigin, width, isPrinting);
+#if ENABLE(CSS3_TEXT)
+ if (decorationStyle == TextDecorationStyleDouble)
+ context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() - doubleOffset), width, isPrinting);
+ }
#endif // CSS3_TEXT
}
- if (deco & LINE_THROUGH) {
+ if (deco & TextDecorationLineThrough) {
context->setStrokeColor(linethrough, colorSpace);
- context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + 2 * baseline / 3), width, isPrinting);
#if ENABLE(CSS3_TEXT)
- if (decorationStyle == TextDecorationStyleDouble)
- context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + doubleOffset + 2 * baseline / 3), width, isPrinting);
+ switch (decorationStyle) {
+ case TextDecorationStyleWavy: {
+ FloatPoint start(localOrigin.x(), localOrigin.y() + 2 * baseline / 3);
+ FloatPoint end(localOrigin.x() + width, localOrigin.y() + 2 * baseline / 3);
+ strokeWavyTextDecoration(context, start, end, textDecorationThickness);
+ break;
+ }
+ default:
+#endif // CSS3_TEXT
+ context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + 2 * baseline / 3), width, isPrinting);
+#if ENABLE(CSS3_TEXT)
+ if (decorationStyle == TextDecorationStyleDouble)
+ context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + doubleOffset + 2 * baseline / 3), width, isPrinting);
+ }
#endif // CSS3_TEXT
}
} while (shadow);
@@ -1120,7 +1340,7 @@ void InlineTextBox::paintDocumentMarker(GraphicsContext* pt, const FloatPoint& b
// display a toolTip. We don't do this for misspelling markers.
if (grammar || isDictationMarker) {
markerRect.move(-boxOrigin.x(), -boxOrigin.y());
- markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect), SnapOffsetForTransforms).enclosingBoundingBox();
+ markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox();
toRenderedDocumentMarker(marker)->setRenderedRect(markerRect);
}
}
@@ -1158,11 +1378,11 @@ void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, const FloatPoint&
// Always compute and store the rect associated with this marker. The computed rect is in absolute coordinates.
IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, IntPoint(x(), selectionTop()), selHeight, sPos, ePos));
- markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect), SnapOffsetForTransforms).enclosingBoundingBox();
+ markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox();
toRenderedDocumentMarker(marker)->setRenderedRect(markerRect);
// Optionally highlight the text
- if (renderer()->frame()->editor()->markedTextMatchesAreHighlighted()) {
+ if (renderer()->frame()->editor().markedTextMatchesAreHighlighted()) {
Color color = marker->activeMatch() ?
renderer()->theme()->platformActiveTextSearchHighlightColor() :
renderer()->theme()->platformInactiveTextSearchHighlightColor();
@@ -1186,7 +1406,7 @@ void InlineTextBox::computeRectForReplacementMarker(DocumentMarker* marker, Rend
// Compute and store the rect associated with this marker.
IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, startPoint, h, sPos, ePos));
- markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect), SnapOffsetForTransforms).enclosingBoundingBox();
+ markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox();
toRenderedDocumentMarker(marker)->setRenderedRect(markerRect);
}
@@ -1200,7 +1420,7 @@ void InlineTextBox::paintDocumentMarkers(GraphicsContext* pt, const FloatPoint&
// Give any document markers that touch this run a chance to draw before the text has been drawn.
// Note end() points at the last char, not one past it like endOffset and ranges do.
- for ( ; markerIt != markers.end(); markerIt++) {
+ for ( ; markerIt != markers.end(); ++markerIt) {
DocumentMarker* marker = *markerIt;
// Paint either the background markers or the foreground markers, but not both