Chromium Code Reviews| Index: Source/core/rendering/InlineTextBox.cpp |
| diff --git a/Source/core/rendering/InlineTextBox.cpp b/Source/core/rendering/InlineTextBox.cpp |
| index dcb093c0379302ef922e0d75d88c12ff06442363..02e4ffa0cfd53df1c6f0c46dcf5eb6e784de9b09 100644 |
| --- a/Source/core/rendering/InlineTextBox.cpp |
| +++ b/Source/core/rendering/InlineTextBox.cpp |
| @@ -42,6 +42,7 @@ |
| #include "core/rendering/RenderRubyRun.h" |
| #include "core/rendering/RenderRubyText.h" |
| #include "core/rendering/RenderTheme.h" |
| +#include "core/rendering/style/AppliedTextDecorationList.h" |
| #include "core/rendering/style/ShadowList.h" |
| #include "core/rendering/svg/SVGTextRunRenderingContext.h" |
| #include "platform/fonts/FontCache.h" |
| @@ -751,12 +752,11 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, |
| } |
| // Paint decorations |
| - TextDecoration textDecorations = styleToUse->textDecorationsInEffect(); |
| - if (textDecorations != TextDecorationNone && paintInfo.phase != PaintPhaseSelection) { |
| + if (styleToUse->hasAppliedTextDecorations() && paintInfo.phase != PaintPhaseSelection) { |
| updateGraphicsContext(context, textFillColor, textStrokeColor, textStrokeWidth); |
| if (combinedText) |
| context->concatCTM(rotation(boxRect, Clockwise)); |
| - paintDecoration(context, boxOrigin, textDecorations, textShadow); |
| + paintDecoration(context, boxOrigin, styleToUse, textShadow); |
| if (combinedText) |
| context->concatCTM(rotation(boxRect, Counterclockwise)); |
| } |
| @@ -916,8 +916,11 @@ static StrokeStyle textDecorationStyleToStrokeStyle(TextDecorationStyle decorati |
| return strokeStyle; |
| } |
| -static int computeUnderlineOffset(const TextUnderlinePosition underlinePosition, const FontMetrics& fontMetrics, const InlineTextBox* inlineTextBox, const float textDecorationThickness) |
| +int InlineTextBox::computeUnderlineOffset(RenderStyle* style, const float textDecorationThickness) |
| { |
| + const TextUnderlinePosition underlinePosition = style->textUnderlinePosition(); |
| + const FontMetrics& fontMetrics = style->fontMetrics(); |
| + |
| // 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 = std::max<int>(1, ceilf(textDecorationThickness / 2.f)); |
| @@ -928,10 +931,10 @@ static int computeUnderlineOffset(const TextUnderlinePosition underlinePosition, |
| 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(); |
| + const float offset = root().maxLogicalTop() - logicalTop(); |
| if (offset > 0) |
| - return inlineTextBox->logicalHeight() + gap + offset; |
| - return inlineTextBox->logicalHeight() + gap; |
| + return logicalHeight() + gap + offset; |
| + return logicalHeight() + gap; |
| } |
| } |
| @@ -1066,34 +1069,71 @@ static bool shouldSetDecorationAntialias(TextDecorationStyle decorationStyle) |
| return decorationStyle == TextDecorationStyleDotted || decorationStyle == TextDecorationStyleDashed; |
| } |
| -static bool shouldSetDecorationAntialias(TextDecorationStyle underline, TextDecorationStyle overline, TextDecorationStyle linethrough) |
| +static void getDecorationMetaData(const AppliedTextDecorationList* decorations, bool& linesAreOpaque, bool& setDecorationAntialias) |
|
esprehn
2014/03/31 17:41:24
I might use a struct instead of all these out para
|
| { |
| - return shouldSetDecorationAntialias(underline) || shouldSetDecorationAntialias(overline) || shouldSetDecorationAntialias(linethrough); |
| + for (size_t i = 0; i < decorations->size(); ++i) { |
|
esprehn
2014/03/31 17:41:24
Pass decorations by reference.
|
| + const AppliedTextDecoration& d = decorations->at(i); |
| + linesAreOpaque &= (d.color().alpha() == 255); |
| + setDecorationAntialias |= shouldSetDecorationAntialias(d.style()); |
| + } |
| } |
| -static void paintAppliedDecoration(GraphicsContext* context, FloatPoint start, float width, float doubleOffset, int wavyOffsetFactor, |
| - RenderObject::AppliedTextDecoration decoration, float thickness, bool antialiasDecoration, bool isPrinting) |
| +struct PaintAppliedDecorationData { |
| + RenderStyle* style; |
| + FloatPoint start; |
| + float width; |
| + float doubleOffset; |
| + float thickness; |
| + bool antialias; |
| + bool isPrinting; |
| + int baseline; |
|
esprehn
2014/03/31 17:41:24
Do we need a constructor that zero inits this thin
|
| +}; |
| + |
| +static void paintAppliedDecorationStyle(GraphicsContext* context, const AppliedTextDecoration& decoration, const PaintAppliedDecorationData& d, int wavyOffsetFactor) |
|
esprehn
2014/03/31 17:41:24
Don't use single letter variable names.
|
| { |
| - context->setStrokeStyle(textDecorationStyleToStrokeStyle(decoration.style)); |
| - context->setStrokeColor(decoration.color); |
| + context->setStrokeStyle(textDecorationStyleToStrokeStyle(decoration.style())); |
| + context->setStrokeColor(decoration.color()); |
| - switch (decoration.style) { |
| + switch (decoration.style()) { |
| case TextDecorationStyleWavy: |
| - strokeWavyTextDecoration(context, start + FloatPoint(0, doubleOffset * wavyOffsetFactor), start + FloatPoint(width, doubleOffset * wavyOffsetFactor), thickness); |
| + strokeWavyTextDecoration(context, d.start + FloatPoint(0, d.doubleOffset * wavyOffsetFactor), d.start + FloatPoint(d.width, d.doubleOffset * wavyOffsetFactor), d.thickness); |
| break; |
| case TextDecorationStyleDotted: |
| case TextDecorationStyleDashed: |
| - context->setShouldAntialias(antialiasDecoration); |
| + context->setShouldAntialias(d.antialias); |
| // Fall through |
| default: |
| - context->drawLineForText(start, width, isPrinting); |
| + context->drawLineForText(d.start, d.width, d.isPrinting); |
| - if (decoration.style == TextDecorationStyleDouble) |
| - context->drawLineForText(start + FloatPoint(0, doubleOffset), width, isPrinting); |
| + if (decoration.style() == TextDecorationStyleDouble) |
| + context->drawLineForText(d.start + FloatPoint(0, d.doubleOffset), d.width, d.isPrinting); |
| } |
| } |
| -void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint& boxOrigin, TextDecoration deco, const ShadowList* shadowList) |
| +void InlineTextBox::paintAppliedDecoration(GraphicsContext* context, const AppliedTextDecoration& decoration, const PaintAppliedDecorationData& d) |
| +{ |
| + PaintAppliedDecorationData data = d; |
| + int wavyOffsetFactor = 1; |
| + |
| + switch (decoration.line()) { |
| + case TextDecorationUnderline: |
| + data.start += FloatPoint(0, computeUnderlineOffset(d.style, d.thickness)); |
| + break; |
| + case TextDecorationOverline: |
| + data.doubleOffset *= -1; |
| + break; |
| + case TextDecorationLineThrough: |
| + data.start += FloatPoint(0, (2 * d.baseline / 3)); |
| + wavyOffsetFactor = 0; |
| + break; |
| + default: |
| + return; |
| + } |
| + |
| + paintAppliedDecorationStyle(context, decoration, data, wavyOffsetFactor); |
| +} |
| + |
| +void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint& boxOrigin, RenderStyle* styleToUse, const ShadowList* shadowList) |
| { |
| GraphicsContextStateSaver stateSaver(*context); |
| @@ -1109,19 +1149,25 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint& |
| localOrigin.move(m_logicalWidth - width, 0); |
| } |
| - // Get the text decoration colors. |
| - RenderObject::AppliedTextDecoration underline, overline, linethrough; |
| + const AppliedTextDecorationList* decorations = styleToUse->appliedTextDecorations(); |
| - renderer().getTextDecorations(deco, underline, overline, linethrough, true); |
| - if (isFirstLineStyle()) |
| - renderer().getTextDecorations(deco, underline, overline, linethrough, true, true); |
| + // If appliedTextUnderline() is true, we must paint an extra underline |
| + // before painting the other decorations. |
| + AppliedTextDecoration underline; |
| + if (styleToUse->appliedTextUnderline()) { |
| + Color color = renderer().getUnderlineColor(true, isFirstLineStyle()); |
|
esprehn
2014/03/31 17:41:24
this boolean argument is confusing, can we use an
|
| + underline = AppliedTextDecoration(TextDecorationUnderline, TextDecorationStyleSolid, color); |
| + } |
| // Use a special function for underlines to get the positioning exactly right. |
| bool isPrinting = textRenderer().document().printing(); |
| - bool linesAreOpaque = !isPrinting && (!(deco & TextDecorationUnderline) || underline.color.alpha() == 255) && (!(deco & TextDecorationOverline) || overline.color.alpha() == 255) && (!(deco & TextDecorationLineThrough) || linethrough.color.alpha() == 255); |
| + bool linesAreOpaque = !isPrinting; |
| + bool setDecorationAntialias = false; |
| + |
| + if (decorations) |
| + getDecorationMetaData(decorations, linesAreOpaque, setDecorationAntialias); |
| - RenderStyle* styleToUse = renderer().style(isFirstLineStyle()); |
| int baseline = styleToUse->fontMetrics().ascent(); |
| size_t shadowCount = shadowList ? shadowList->shadows().size() : 0; |
| @@ -1136,8 +1182,7 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint& |
| context->setStrokeThickness(textDecorationThickness); |
| - bool antialiasDecoration = shouldSetDecorationAntialias(overline.style, underline.style, linethrough.style) |
| - && RenderBoxModelObject::shouldAntialiasLines(context); |
| + bool antialiasDecoration = setDecorationAntialias && RenderBoxModelObject::shouldAntialiasLines(context); |
| float extraOffset = 0; |
| if (!linesAreOpaque && shadowCount > 1) { |
| @@ -1171,20 +1216,23 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint& |
| context->setShadow(FloatSize(shadowX, shadowY - extraOffset), shadow.blur(), shadow.color()); |
| } |
| + PaintAppliedDecorationData data; |
| + data.style = styleToUse; |
| + data.start = localOrigin; |
| + data.width = width; |
| // Offset between lines - always non-zero, so lines never cross each other. |
| - float doubleOffset = textDecorationThickness + 1.f; |
| - |
| - if (deco & TextDecorationUnderline) { |
| - const int underlineOffset = computeUnderlineOffset(styleToUse->textUnderlinePosition(), styleToUse->fontMetrics(), this, textDecorationThickness); |
| - paintAppliedDecoration(context, localOrigin + FloatPoint(0, underlineOffset), width, doubleOffset, 1, underline, textDecorationThickness, antialiasDecoration, isPrinting); |
| - } |
| - if (deco & TextDecorationOverline) { |
| - paintAppliedDecoration(context, localOrigin, width, -doubleOffset, 1, overline, textDecorationThickness, antialiasDecoration, isPrinting); |
| - } |
| - if (deco & TextDecorationLineThrough) { |
| - const float lineThroughOffset = 2 * baseline / 3; |
| - paintAppliedDecoration(context, localOrigin + FloatPoint(0, lineThroughOffset), width, doubleOffset, 0, linethrough, textDecorationThickness, antialiasDecoration, isPrinting); |
| - } |
| + data.doubleOffset = textDecorationThickness + 1.f; |
| + data.thickness = textDecorationThickness; |
| + data.antialias = antialiasDecoration; |
| + data.isPrinting = isPrinting; |
| + data.baseline = baseline; |
| + |
| + if (styleToUse->appliedTextUnderline()) |
| + paintAppliedDecoration(context, underline, data); |
| + |
| + if (decorations) |
| + for (size_t i = 0; i < decorations->size(); ++i) |
| + paintAppliedDecoration(context, decorations->at(i), data); |
| } |
| } |