void RenderMathMLUnderOver::addChild(RenderObject* child, RenderObject* beforeChild) { RenderMathMLBlock* row = new (renderArena()) RenderMathMLBlock(node()); RefPtr<RenderStyle> rowStyle = createBlockStyle(); row->setStyle(rowStyle.release()); row->setIsAnonymous(true); // look through the children for rendered elements counting the blocks so we know what child // we are adding int blocks = 0; RenderObject* current = this->firstChild(); while (current) { blocks++; current = current->nextSibling(); } switch (blocks) { case 0: // this is the base so just append it RenderBlock::addChild(row, beforeChild); break; case 1: // the under or over // FIXME: text-align: center does not work row->style()->setTextAlign(CENTER); if (m_kind == Over) { // add the over as first RenderBlock::addChild(row, firstChild()); } else { // add the under as last RenderBlock::addChild(row, beforeChild); } break; case 2: // the under or over // FIXME: text-align: center does not work row->style()->setTextAlign(CENTER); if (m_kind == UnderOver) { // add the over as first RenderBlock::addChild(row, firstChild()); } else { // we really shouldn't get here as only munderover should have three children RenderBlock::addChild(row, beforeChild); } break; default: // munderover shouldn't have more than three children. In theory we shouldn't // get here if the MathML is correctly formed, but that isn't a guarantee. // We will treat this as another under element and they'll get something funky. RenderBlock::addChild(row, beforeChild); } row->addChild(child); }
void RenderMathMLSubSup::layout() { RenderBlock::layout(); if (m_kind != SubSup || !m_scripts) return; RenderMathMLBlock* baseWrapper = toRenderMathMLBlock(firstChild()); RenderMathMLBlock* superscriptWrapper = toRenderMathMLBlock(m_scripts->firstChild()); RenderMathMLBlock* subscriptWrapper = toRenderMathMLBlock(m_scripts->lastChild()); if (!baseWrapper || !superscriptWrapper || !subscriptWrapper || superscriptWrapper == subscriptWrapper) return; LayoutUnit baseWrapperBaseline = toRenderBox(firstChild())->firstLineBoxBaseline(); LayoutUnit baseBaseline = baseWrapperBaseline - baseWrapper->paddingBefore(); LayoutUnit baseExtendUnderBaseline = baseWrapper->logicalHeight() - baseWrapperBaseline; LayoutUnit axis = style()->fontMetrics().xHeight() / 2; LayoutUnit superscriptHeight = superscriptWrapper->logicalHeight() - superscriptWrapper->paddingAfter(); LayoutUnit subscriptHeight = subscriptWrapper->logicalHeight(); // Our layout rules are: Don't let the superscript go below the "axis" (half x-height above the // baseline), or the subscript above the axis. Also, don't let the superscript's top edge be // below the base's top edge, or the subscript's bottom edge above the base's bottom edge. // // FIXME: Check any subscriptshift or superscriptshift attributes, and maybe use more sophisticated // heuristics from TeX or elsewhere. See https://bugs.webkit.org/show_bug.cgi?id=79274#c5. // Above we did scriptsStyle->setVerticalAlign(TOP) for mscripts' style, so the superscript's // top edge will equal the top edge of the base's padding. LayoutUnit basePaddingTop = superscriptHeight + axis - baseBaseline; // If basePaddingTop is positive, it's indeed the base's padding-top that we need. If it's negative, // then we should instead use its absolute value to pad the bottom of the superscript, to get the // superscript's bottom edge down to the axis. First we compute how much more we need to shift the // subscript down, once its top edge is at the axis. LayoutUnit superPaddingBottom = max<LayoutUnit>(baseExtendUnderBaseline + axis - subscriptHeight, 0); if (basePaddingTop < 0) { superPaddingBottom += -basePaddingTop; basePaddingTop = 0; } setChildNeedsLayout(true, MarkOnlyThis); baseWrapper->style()->setPaddingTop(Length(basePaddingTop, Fixed)); baseWrapper->setNeedsLayout(true, MarkOnlyThis); superscriptWrapper->style()->setPaddingBottom(Length(superPaddingBottom, Fixed)); superscriptWrapper->setNeedsLayout(true, MarkOnlyThis); m_scripts->setNeedsLayout(true, MarkOnlyThis); RenderBlock::layout(); }
void RenderMathMLSubSup::layout() { RenderMathMLBlock::layout(); RenderMathMLBlock* baseWrapper = toRenderMathMLBlock(firstChild()); if (!baseWrapper || !m_scripts) return; RenderBox* base = baseWrapper->firstChildBox(); if (!base) return; // Our layout rules include: Don't let the superscript go below the "axis" (half x-height above the // baseline), or the subscript above the axis. Also, don't let the superscript's top edge be // below the base's top edge, or the subscript's bottom edge above the base's bottom edge. // // FIXME: Check any subscriptshift or superscriptshift attributes, and maybe use more sophisticated // heuristics from TeX or elsewhere. See https://bugs.webkit.org/show_bug.cgi?id=79274#c5. LayoutUnit baseHeight = base->logicalHeight(); LayoutUnit baseBaseline = base->firstLineBoxBaseline(); if (baseBaseline == -1) baseBaseline = baseHeight; LayoutUnit axis = style()->fontMetrics().xHeight() / 2; int fontSize = style()->fontSize(); ASSERT(baseWrapper->style()->hasOneRef()); bool needsSecondLayout = false; if (RenderBox* superscript = m_kind == Sub ? 0 : m_scripts->lastChildBox()) { LayoutUnit superscriptHeight = superscript->logicalHeight(); LayoutUnit superscriptBaseline = superscript->firstLineBoxBaseline(); if (superscriptBaseline == -1) superscriptBaseline = superscriptHeight; LayoutUnit minBaseline = max<LayoutUnit>(fontSize / 3 + 1 + superscriptBaseline, superscriptHeight + axis); Length newPadding = Length(max<LayoutUnit>(minBaseline - baseBaseline, 0), Fixed); if (newPadding != baseWrapper->style()->paddingTop()) { baseWrapper->style()->setPaddingTop(newPadding); needsSecondLayout = true; } } if (RenderBox* subscript = m_kind == Super ? 0 : m_scripts->firstChildBox()) { LayoutUnit subscriptHeight = subscript->logicalHeight(); LayoutUnit subscriptBaseline = subscript->firstLineBoxBaseline(); if (subscriptBaseline == -1) subscriptBaseline = subscriptHeight; LayoutUnit baseExtendUnderBaseline = baseHeight - baseBaseline; LayoutUnit subscriptUnderItsBaseline = subscriptHeight - subscriptBaseline; LayoutUnit minExtendUnderBaseline = max<LayoutUnit>(fontSize / 5 + 1 + subscriptUnderItsBaseline, subscriptHeight - axis); Length newPadding = Length(max<LayoutUnit>(minExtendUnderBaseline - baseExtendUnderBaseline, 0), Fixed); if (newPadding != baseWrapper->style()->paddingBottom()) { baseWrapper->style()->setPaddingBottom(newPadding); needsSecondLayout = true; } } if (!needsSecondLayout) return; setNeedsLayout(true, MarkOnlyThis); baseWrapper->setChildNeedsLayout(true, MarkOnlyThis); RenderMathMLBlock::layout(); }