float CanvasRenderingContext2D::getFontBaseline( const FontMetrics& fontMetrics) const { // If the font is so tiny that the lroundf operations result in two // different types of text baselines to return the same baseline, use // floating point metrics (crbug.com/338908). // If you changed the heuristic here, for consistency please also change it // in SimpleFontData::platformInit(). bool useFloatAscentDescent = fontMetrics.ascent() < 3 || fontMetrics.height() < 2; switch (state().getTextBaseline()) { case TopTextBaseline: return useFloatAscentDescent ? fontMetrics.floatAscent() : fontMetrics.ascent(); case HangingTextBaseline: // According to // http://wiki.apache.org/xmlgraphics-fop/LineLayout/AlignmentHandling // "FOP (Formatting Objects Processor) puts the hanging baseline at 80% of // the ascender height" return useFloatAscentDescent ? (fontMetrics.floatAscent() * 4.0) / 5.0 : (fontMetrics.ascent() * 4) / 5; case BottomTextBaseline: case IdeographicTextBaseline: return useFloatAscentDescent ? -fontMetrics.floatDescent() : -fontMetrics.descent(); case MiddleTextBaseline: return useFloatAscentDescent ? -fontMetrics.floatDescent() + fontMetrics.floatHeight() / 2.0 : -fontMetrics.descent() + fontMetrics.height() / 2; case AlphabeticTextBaseline: default: // Do nothing. break; } return 0; }
static inline float positionOffsetForDecoration(ETextDecoration decoration, const FontMetrics& fontMetrics, float thickness) { // FIXME: For SVG Fonts we need to use the attributes defined in the <font-face> if specified. // Compatible with Batik/Opera. if (decoration == UNDERLINE) return fontMetrics.ascent() + thickness * 1.5f; if (decoration == OVERLINE) return thickness; if (decoration == LINE_THROUGH) return fontMetrics.ascent() * 5.0f / 8.0f; ASSERT_NOT_REACHED(); return 0.0f; }
int computeUnderlineOffset(TextUnderlinePosition underlinePosition, const FontMetrics& fontMetrics, const InlineTextBox* inlineTextBox, int textDecorationThickness) { // This represents the gap between the baseline and the closest edge of the underline. int gap = std::max<int>(1, ceilf(textDecorationThickness / 2.0)); // FIXME: The code for visual overflow detection passes in a null inline text box. This means it is now // broken for the case where auto needs to behave like "under". // According to the specification TextUnderlinePositionAuto should avoid drawing through glyphs in // scripts where it would not be appropriate (e.g., ideographs). // Strictly speaking this can occur whenever the line contains ideographs // even if it is horizontal, but detecting this has performance implications. For now we only work with // vertical text, since we already determined the baseline type to be ideographic in that // case. TextUnderlinePosition resolvedUnderlinePosition = underlinePosition == TextUnderlinePositionAuto && inlineTextBox && inlineTextBox->root().baselineType() == IdeographicBaseline ? TextUnderlinePositionUnder : TextUnderlinePositionAlphabetic; switch (resolvedUnderlinePosition) { case TextUnderlinePositionAlphabetic: return fontMetrics.ascent() + gap; case TextUnderlinePositionUnder: { ASSERT(inlineTextBox); // Position underline relative to the bottom edge of the lowest element's content box. const RootInlineBox& rootBox = inlineTextBox->root(); const RenderElement* decorationRenderer = inlineTextBox->parent()->renderer().enclosingRendererWithTextDecoration(TextDecorationUnderline, inlineTextBox->isFirstLine()); float offset; if (inlineTextBox->renderer().style().isFlippedLinesWritingMode()) { offset = inlineTextBox->logicalTop(); rootBox.minLogicalTopForTextDecorationLine(offset, decorationRenderer, TextDecorationUnderline); offset = inlineTextBox->logicalTop() - offset; } else { offset = inlineTextBox->logicalBottom(); rootBox.maxLogicalBottomForTextDecorationLine(offset, decorationRenderer, TextDecorationUnderline); offset -= inlineTextBox->logicalBottom(); } return inlineTextBox->logicalHeight() + gap + std::max<float>(offset, 0); } case TextUnderlinePositionAuto: ASSERT_NOT_REACHED(); } ASSERT_NOT_REACHED(); return fontMetrics.ascent() + gap; }