diff options
author | Allan Sandfeld Jensen <allan.jensen@digia.com> | 2013-09-13 12:51:20 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-19 20:50:05 +0200 |
commit | d441d6f39bb846989d95bcf5caf387b42414718d (patch) | |
tree | e367e64a75991c554930278175d403c072de6bb8 /Source/WebCore/rendering/InlineTextBox.cpp | |
parent | 0060b2994c07842f4c59de64b5e3e430525c4b90 (diff) | |
download | qtwebkit-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.cpp | 324 |
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 |