Esempio n. 1
0
void RenderMathMLRow::computePreferredLogicalWidths()
{
    ASSERT(preferredLogicalWidthsDirty() && needsLayout());
    
    computeChildrenPreferredLogicalHeights();
    int stretchLogicalHeight = 0;
    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
        if (child->isRenderMathMLBlock()) {
            RenderMathMLOperator* renderMo = toRenderMathMLBlock(child)->unembellishedOperator();
            // FIXME: Only skip renderMo if it is stretchy.
            if (renderMo)
                continue;
        }
        stretchLogicalHeight = max<int>(stretchLogicalHeight, roundToInt(preferredLogicalHeightAfterSizing(child)));
    }
    if (!stretchLogicalHeight)
        stretchLogicalHeight = style()->fontSize();
    
    // Set the sizes of (possibly embellished) stretchy operator children.
    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
        if (child->isRenderMathMLBlock()) {
            RenderMathMLOperator* renderMo = toRenderMathMLBlock(child)->unembellishedOperator();
            if (renderMo)
                renderMo->stretchToHeight(stretchLogicalHeight);
        }
    }
    
    RenderMathMLBlock::computePreferredLogicalWidths();
    
    // Shrink our logical width to its probable value now without triggering unnecessary relayout of our children.
    ASSERT(needsLayout() && logicalWidth() >= maxPreferredLogicalWidth());
    setLogicalWidth(maxPreferredLogicalWidth());
}
void RenderMathMLRow::layout() 
{
    RenderBlock::layout();
    
    // Calculate the maximum height of the row without the operators.
    int maxHeight = nonOperatorHeight();
    
    // Set the maximum height of the row for intermediate layouts.
    style()->setHeight(Length(maxHeight, Fixed));

    // Notify contained operators they may need to re-layout their stretched operators.
    // We need to keep track of the number of children and operators because a row of
    // operators needs some special handling.
    int childCount = 0;
    int operatorCount = 0;
    for (RenderObject* current = firstChild(); current; current = current->nextSibling()) {
        childCount++;
        if (current->isRenderMathMLBlock()) {
            RenderMathMLBlock* block = toRenderMathMLBlock(current);
            block->stretchToHeight(maxHeight);
            if (block->isRenderMathMLOperator()) 
                operatorCount++;
        }
    }
    
    // Layout the non-operators which have just been stretched.
    setNeedsLayoutAndPrefWidthsRecalc();
    markContainingBlocksForLayout();
    RenderBlock::layout();

    // Make a second pass with the real height of the operators.
    int operatorHeight = 0;
    for (RenderObject* current = firstChild(); current; current = current->nextSibling()) {
        if (current->isRenderMathMLBlock()) {
            RenderMathMLBlock* block = toRenderMathMLBlock(current);
            if (!block->hasBase() && !block->isRenderMathMLOperator()) {
                // Check to see if this box has a larger height.
                if (block->offsetHeight() > maxHeight)
                    maxHeight = block->offsetHeight();
            }
            if (block->isRenderMathMLOperator())
                if (block->offsetHeight() > operatorHeight)
                    operatorHeight = block->offsetHeight();
        } else if (current->isBoxModelObject()) {
            RenderBoxModelObject* box = toRenderBoxModelObject(current);
            // Check to see if this box has a larger height.
            if (box->offsetHeight() > maxHeight)
                maxHeight = box->offsetHeight();
        }
    }
    
    if (childCount > 0 && childCount == operatorCount) {
        // We have only operators and so set the max height to the operator height.
        maxHeight = operatorHeight;
    }
    
    int stretchHeight = maxHeight;
    
    // Stretch the operators again and re-calculate the row height.
    for (RenderObject* current = firstChild(); current; current = current->nextSibling()) {
        if (current->isRenderMathMLBlock()) {
            RenderMathMLBlock* block = toRenderMathMLBlock(current);
            if (block->isRenderMathMLOperator()) {
                RenderMathMLOperator* mathop = toRenderMathMLOperator(block);
                mathop->stretchToHeight(stretchHeight);
            } else {
                block->stretchToHeight(stretchHeight);
                RenderBoxModelObject* box = toRenderBoxModelObject(current);
                // Check to see if this box has a larger height
                if (box->offsetHeight() > maxHeight)
                    maxHeight = box->offsetHeight();
            }
        } else if (current->isBoxModelObject()) {
            RenderBoxModelObject* box = toRenderBoxModelObject(current);
            // Check to see if this box has a larger height
            if (box->offsetHeight() > maxHeight)
                maxHeight = box->offsetHeight();
        }
    }

    // Set the maximum height of the row based on the calculations.
    style()->setHeight(Length(maxHeight, Fixed));
    
    // Do the final layout by calling our parent's layout again.
    setNeedsLayoutAndPrefWidthsRecalc();
    markContainingBlocksForLayout();
    RenderBlock::layout();
}