GlyphOverflow visualOverflowForDecorations(const RenderStyle& lineStyle, const InlineTextBox* inlineTextBox) { ASSERT(!inlineTextBox || inlineTextBox->lineStyle() == lineStyle); TextDecoration decoration = lineStyle.textDecorationsInEffect(); if (decoration == TextDecorationNone) return GlyphOverflow(); float strokeThickness = textDecorationStrokeThickness(lineStyle.fontSize()); float controlPointDistance; float step; float wavyOffset; TextDecorationStyle decorationStyle = lineStyle.textDecorationStyle(); float height = lineStyle.fontCascade().fontMetrics().floatHeight(); GlyphOverflow overflowResult; if (decorationStyle == TextDecorationStyleWavy) { getWavyStrokeParameters(strokeThickness, controlPointDistance, step); wavyOffset = wavyOffsetFromDecoration(); overflowResult.left = strokeThickness; overflowResult.right = strokeThickness; } // These metrics must match where underlines get drawn. if (decoration & TextDecorationUnderline) { // Compensate for the integral ceiling in GraphicsContext::computeLineBoundsAndAntialiasingModeForText() int underlineOffset = 1; underlineOffset += computeUnderlineOffset(lineStyle.textUnderlinePosition(), lineStyle.fontMetrics(), inlineTextBox, strokeThickness); if (decorationStyle == TextDecorationStyleWavy) { extendIntToFloat(overflowResult.bottom, underlineOffset + wavyOffset + controlPointDistance + strokeThickness - height); extendIntToFloat(overflowResult.top, -(underlineOffset + wavyOffset - controlPointDistance - strokeThickness)); } else { extendIntToFloat(overflowResult.bottom, underlineOffset + strokeThickness - height); extendIntToFloat(overflowResult.top, -underlineOffset); } } if (decoration & TextDecorationOverline) { if (decorationStyle == TextDecorationStyleWavy) { extendIntToFloat(overflowResult.bottom, -wavyOffset + controlPointDistance + strokeThickness - height); extendIntToFloat(overflowResult.top, wavyOffset + controlPointDistance + strokeThickness); } else { extendIntToFloat(overflowResult.bottom, strokeThickness - height); // top is untouched } } if (decoration & TextDecorationLineThrough) { float baseline = lineStyle.fontMetrics().floatAscent(); if (decorationStyle == TextDecorationStyleWavy) { extendIntToFloat(overflowResult.bottom, 2 * baseline / 3 + controlPointDistance + strokeThickness - height); extendIntToFloat(overflowResult.top, -(2 * baseline / 3 - controlPointDistance - strokeThickness)); } else { extendIntToFloat(overflowResult.bottom, 2 * baseline / 3 + strokeThickness - height); extendIntToFloat(overflowResult.top, -(2 * baseline / 3)); } } return overflowResult; }
TextDecorationPainter::TextDecorationPainter(GraphicsContext& context, TextDecoration decoration, const RenderText& renderer, bool isFirstLine) : m_context(context) , m_decoration(decoration) , m_wavyOffset(wavyOffsetFromDecoration()) , m_isPrinting(renderer.document().printing()) , m_styles(stylesForRenderer(renderer, m_decoration, isFirstLine)) , m_lineStyle(isFirstLine ? renderer.firstLineStyle() : renderer.style()) { }