LayoutRect RenderMathMLOperator::paintCharacter(PaintInfo& info, UChar character, const LayoutPoint& origin, CharacterPaintTrimming trim) { GlyphData data = style()->font().glyphDataForCharacter(character, false); FloatRect glyphBounds = data.fontData->boundsForGlyph(data.glyph); LayoutRect glyphPaintRect(origin, LayoutSize(glyphBounds.x() + glyphBounds.width(), glyphBounds.height())); glyphPaintRect.setY(origin.y() + glyphBounds.y()); // In order to have glyphs fit snugly with one another we snap the connecting edges to pixel boundaries // and trim off one pixel. The pixel trim is to account for fonts that have edge pixels that have less // than full coverage. These edge pixels can introduce small seams between connected glyphs FloatRect clipBounds = info.rect; switch (trim) { case TrimTop: glyphPaintRect.shiftYEdgeTo(glyphPaintRect.y().ceil() + 1); clipBounds.shiftYEdgeTo(glyphPaintRect.y()); break; case TrimBottom: glyphPaintRect.shiftMaxYEdgeTo(glyphPaintRect.maxY().floor() - 1); clipBounds.shiftMaxYEdgeTo(glyphPaintRect.maxY()); break; case TrimTopAndBottom: LayoutUnit temp = glyphPaintRect.y() + 1; glyphPaintRect.shiftYEdgeTo(temp.ceil()); glyphPaintRect.shiftMaxYEdgeTo(glyphPaintRect.maxY().floor() - 1); clipBounds.shiftYEdgeTo(glyphPaintRect.y()); clipBounds.shiftMaxYEdgeTo(glyphPaintRect.maxY()); break; } // Clipping the enclosing IntRect avoids any potential issues at joined edges. GraphicsContextStateSaver stateSaver(*info.context); info.context->clip(clipBounds); info.context->drawText(style()->font(), TextRun(&character, 1), origin); return glyphPaintRect; }