예제 #1
0
void RenderMathMLRow::layout() 
{
    RenderBlock::layout();
    
    LayoutUnit maxHeight = 0;
    int childCount = 0;
    int operatorCount = 0;

    // Calculate the non-operator max height of the row.
    LayoutUnit operatorHeight = 0;
    for (RenderObject* current = firstChild(); current; current = current->nextSibling()) {
        childCount++;
        if (current->isRenderMathMLBlock()) {
            RenderMathMLBlock* block = toRenderMathMLBlock(current);
            // Check to see if the non-operator block has a greater height.
            if (!block->hasBase() && !block->isRenderMathMLOperator() && block->offsetHeight() > maxHeight)
                maxHeight = block->offsetHeight();
            if (block->hasBase() && block->nonOperatorHeight() > maxHeight) 
                maxHeight = block->nonOperatorHeight();
            // If the block is an operator, capture the maximum height and increment the count.
            if (block->isRenderMathMLOperator()) {
                if (block->offsetHeight() > operatorHeight)
                    operatorHeight = block->offsetHeight();
                operatorCount++;
            }
        } 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;
    }
    
    // Stretch everything to the same height (blocks can ignore the request).
    if (maxHeight > 0) {
        bool didStretch = false;
        for (RenderObject* current = firstChild(); current; current = current->nextSibling()) {
            if (current->isRenderMathMLBlock()) {
                RenderMathMLBlock* block = toRenderMathMLBlock(current);
                block->stretchToHeight(maxHeight);
                didStretch = true;
            }
        }
        if (didStretch) {
            setNeedsLayout(true);
            setPreferredLogicalWidthsDirty(true, false);
            RenderBlock::layout();
        }
    }
    
}    
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();
}