diff options
author | Feng Qian <> | 2009-04-10 18:11:29 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-04-10 18:11:29 -0700 |
commit | 8f72e70a9fd78eec56623b3a62e68f16b7b27e28 (patch) | |
tree | 181bf9a400c30a1bf34ea6d72560e8d00111d549 /WebCore/rendering/InlineFlowBox.cpp | |
parent | 7ed56f225e0ade046e1c2178977f72b2d896f196 (diff) | |
download | external_webkit-8f72e70a9fd78eec56623b3a62e68f16b7b27e28.zip external_webkit-8f72e70a9fd78eec56623b3a62e68f16b7b27e28.tar.gz external_webkit-8f72e70a9fd78eec56623b3a62e68f16b7b27e28.tar.bz2 |
AI 145796: Land the WebKit merge @r42026.
Automated import of CL 145796
Diffstat (limited to 'WebCore/rendering/InlineFlowBox.cpp')
-rw-r--r-- | WebCore/rendering/InlineFlowBox.cpp | 464 |
1 files changed, 219 insertions, 245 deletions
diff --git a/WebCore/rendering/InlineFlowBox.cpp b/WebCore/rendering/InlineFlowBox.cpp index 74f4151..2e23bb6 100644 --- a/WebCore/rendering/InlineFlowBox.cpp +++ b/WebCore/rendering/InlineFlowBox.cpp @@ -28,7 +28,7 @@ #include "HitTestResult.h" #include "RootInlineBox.h" #include "RenderBlock.h" -#include "RenderFlow.h" +#include "RenderInline.h" #include "RenderListMarker.h" #include "RenderTableCell.h" #include "RootInlineBox.h" @@ -51,45 +51,19 @@ InlineFlowBox::~InlineFlowBox() #endif -RenderFlow* InlineFlowBox::flowObject() +int InlineFlowBox::height() const { - return static_cast<RenderFlow*>(m_object); -} - -int InlineFlowBox::marginLeft() -{ - if (!includeLeftEdge()) - return 0; - - Length margin = object()->style()->marginLeft(); - if (margin.isAuto()) - return 0; - if (margin.isFixed()) - return margin.value(); - return renderBox()->marginLeft(); -} - -int InlineFlowBox::marginRight() -{ - if (!includeRightEdge()) - return 0; - - Length margin = object()->style()->marginRight(); - if (margin.isAuto()) - return 0; - if (margin.isFixed()) - return margin.value(); - return renderBox()->marginRight(); -} - -int InlineFlowBox::marginBorderPaddingLeft() -{ - return marginLeft() + borderLeft() + paddingLeft(); -} - -int InlineFlowBox::marginBorderPaddingRight() -{ - return marginRight() + borderRight() + paddingRight(); + const Font& font = renderer()->style(m_firstLine)->font(); + int result = font.height(); + bool strictMode = renderer()->document()->inStrictMode(); + RenderBoxModelObject* box = boxModelObject(); + result += box->borderTop() + box->paddingTop() + box->borderBottom() + box->paddingBottom(); + if (!strictMode && !hasTextChildren() && !box->hasHorizontalBordersOrPadding()) { + int bottomOverflow = root()->bottomOverflow(); + if (y() + result > bottomOverflow) + result = bottomOverflow - y(); + } + return result; } int InlineFlowBox::getFlowSpacingWidth() @@ -121,7 +95,7 @@ void InlineFlowBox::addToLine(InlineBox* child) child->setFirstLineStyleBit(m_firstLine); if (child->isText()) m_hasTextChildren = true; - if (child->object()->selectionState() != RenderObject::SelectionNone) + if (child->renderer()->selectionState() != RenderObject::SelectionNone) root()->setHasSelectedChildren(true); checkConsistency(); @@ -168,26 +142,41 @@ void InlineFlowBox::deleteLine(RenderArena* arena) m_lastChild = 0; #endif - static_cast<RenderFlow*>(m_object)->removeLineBox(this); + removeLineBoxFromRenderObject(); destroy(arena); } +void InlineFlowBox::removeLineBoxFromRenderObject() +{ + toRenderInline(renderer())->lineBoxes()->removeLineBox(this); +} + void InlineFlowBox::extractLine() { if (!m_extracted) - static_cast<RenderFlow*>(m_object)->extractLineBox(this); + extractLineBoxFromRenderObject(); for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) child->extractLine(); } +void InlineFlowBox::extractLineBoxFromRenderObject() +{ + toRenderInline(renderer())->lineBoxes()->extractLineBox(this); +} + void InlineFlowBox::attachLine() { if (m_extracted) - static_cast<RenderFlow*>(m_object)->attachLineBox(this); + attachLineBoxToRenderObject(); for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) child->attachLine(); } +void InlineFlowBox::attachLineBoxToRenderObject() +{ + toRenderInline(renderer())->lineBoxes()->attachLineBox(this); +} + void InlineFlowBox::adjustPosition(int dx, int dy) { InlineRunBox::adjustPosition(dx, dy); @@ -195,18 +184,23 @@ void InlineFlowBox::adjustPosition(int dx, int dy) child->adjustPosition(dx, dy); } +RenderLineBoxList* InlineFlowBox::rendererLineBoxes() const +{ + return toRenderInline(renderer())->lineBoxes(); +} + bool InlineFlowBox::onEndChain(RenderObject* endObject) { if (!endObject) return false; - if (endObject == object()) + if (endObject == renderer()) return true; RenderObject* curr = endObject; RenderObject* parent = curr->parent(); while (parent && !parent->isRenderBlock()) { - if (parent->lastChild() != curr || parent == object()) + if (parent->lastChild() != curr || parent == renderer()) return false; curr = parent; @@ -223,19 +217,17 @@ void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, RenderObject* en bool includeLeftEdge = false; bool includeRightEdge = false; - RenderFlow* flow = static_cast<RenderFlow*>(object()); - - if (!flow->firstChild()) - includeLeftEdge = includeRightEdge = true; // Empty inlines never split across lines. - else if (parent()) { // The root inline box never has borders/margins/padding. - bool ltr = flow->style()->direction() == LTR; - + // The root inline box never has borders/margins/padding. + if (parent()) { + bool ltr = renderer()->style()->direction() == LTR; + // Check to see if all initial lines are unconstructed. If so, then - // we know the inline began on this line. - if (!flow->firstLineBox()->isConstructed()) { - if (ltr && flow->firstLineBox() == this) + // we know the inline began on this line (unless we are a continuation). + RenderLineBoxList* lineBoxList = rendererLineBoxes(); + if (!lineBoxList->firstLineBox()->isConstructed() && !renderer()->isInlineContinuation()) { + if (ltr && lineBoxList->firstLineBox() == this) includeLeftEdge = true; - else if (!ltr && flow->lastLineBox() == this) + else if (!ltr && lineBoxList->lastLineBox() == this) includeRightEdge = true; } @@ -246,14 +238,15 @@ void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, RenderObject* en // reverse for rtl), then the inline has closed. // (3) The line may end on the inline. If we are the last child (climbing up // the end object's chain), then we just closed as well. - if (!flow->lastLineBox()->isConstructed()) { + if (!lineBoxList->lastLineBox()->isConstructed()) { + RenderInline* inlineFlow = toRenderInline(renderer()); if (ltr) { if (!nextLineBox() && - ((lastLine && !flow->continuation()) || nextOnLineExists() || onEndChain(endObject))) + ((lastLine && !inlineFlow->continuation()) || nextOnLineExists() || onEndChain(endObject))) includeRightEdge = true; } else { if ((!prevLineBox() || prevLineBox()->isConstructed()) && - ((lastLine && !flow->continuation()) || prevOnLineExists() || onEndChain(endObject))) + ((lastLine && !inlineFlow->continuation()) || prevOnLineExists() || onEndChain(endObject))) includeLeftEdge = true; } } @@ -270,32 +263,32 @@ void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, RenderObject* en } } -int InlineFlowBox::placeBoxesHorizontally(int x, int& leftPosition, int& rightPosition, bool& needsWordSpacing) +int InlineFlowBox::placeBoxesHorizontally(int xPos, int& leftPosition, int& rightPosition, bool& needsWordSpacing) { // Set our x position. - setXPos(x); + setX(xPos); int boxShadowLeft = 0; int boxShadowRight = 0; - for (ShadowData* boxShadow = object()->style(m_firstLine)->boxShadow(); boxShadow; boxShadow = boxShadow->next) { + for (ShadowData* boxShadow = renderer()->style(m_firstLine)->boxShadow(); boxShadow; boxShadow = boxShadow->next) { boxShadowLeft = min(boxShadow->x - boxShadow->blur, boxShadowLeft); boxShadowRight = max(boxShadow->x + boxShadow->blur, boxShadowRight); } - leftPosition = min(x + boxShadowLeft, leftPosition); + leftPosition = min(xPos + boxShadowLeft, leftPosition); - int startX = x; - x += borderLeft() + paddingLeft(); + int startX = xPos; + xPos += borderLeft() + paddingLeft(); for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { - if (curr->object()->isText()) { + if (curr->renderer()->isText()) { InlineTextBox* text = static_cast<InlineTextBox*>(curr); - RenderText* rt = toRenderText(text->object()); + RenderText* rt = toRenderText(text->renderer()); if (rt->textLength()) { if (needsWordSpacing && isSpaceOrNewline(rt->characters()[text->start()])) - x += rt->style(m_firstLine)->font().wordSpacing(); + xPos += rt->style(m_firstLine)->font().wordSpacing(); needsWordSpacing = !isSpaceOrNewline(rt->characters()[text->end()]); } - text->setXPos(x); + text->setX(xPos); int strokeOverflow = static_cast<int>(ceilf(rt->style()->textStrokeWidth() / 2.0f)); @@ -313,41 +306,41 @@ int InlineFlowBox::placeBoxesHorizontally(int x, int& leftPosition, int& rightPo visualOverflowRight = max(visualOverflowRight, shadow->x + shadow->blur + rightGlyphOverflow); } - leftPosition = min(x + visualOverflowLeft, leftPosition); - rightPosition = max(x + text->width() + visualOverflowRight, rightPosition); - m_maxHorizontalVisualOverflow = max(max(visualOverflowRight, -visualOverflowLeft), m_maxHorizontalVisualOverflow); - x += text->width(); + leftPosition = min(xPos + visualOverflowLeft, leftPosition); + rightPosition = max(xPos + text->width() + visualOverflowRight, rightPosition); + m_maxHorizontalVisualOverflow = max(max(visualOverflowRight, -visualOverflowLeft), (int)m_maxHorizontalVisualOverflow); + xPos += text->width(); } else { - if (curr->object()->isPositioned()) { - if (curr->object()->parent()->style()->direction() == LTR) - curr->setXPos(x); + if (curr->renderer()->isPositioned()) { + if (curr->renderer()->parent()->style()->direction() == LTR) + curr->setX(xPos); else // Our offset that we cache needs to be from the edge of the right border box and // not the left border box. We have to subtract |x| from the width of the block // (which can be obtained from the root line box). - curr->setXPos(root()->block()->width()-x); + curr->setX(root()->block()->width() - xPos); continue; // The positioned object has no effect on the width. } - if (curr->object()->isRenderInline()) { + if (curr->renderer()->isRenderInline()) { InlineFlowBox* flow = static_cast<InlineFlowBox*>(curr); - x += flow->marginLeft(); - x = flow->placeBoxesHorizontally(x, leftPosition, rightPosition, needsWordSpacing); - x += flow->marginRight(); - } else if (!curr->object()->isListMarker() || static_cast<RenderListMarker*>(curr->object())->isInside()) { - x += curr->renderBox()->marginLeft(); - curr->setXPos(x); - leftPosition = min(x + curr->renderBox()->overflowLeft(false), leftPosition); - rightPosition = max(x + curr->renderBox()->overflowWidth(false), rightPosition); - x += curr->width() + curr->renderBox()->marginRight(); + xPos += flow->marginLeft(); + xPos = flow->placeBoxesHorizontally(xPos, leftPosition, rightPosition, needsWordSpacing); + xPos += flow->marginRight(); + } else if (!curr->renderer()->isListMarker() || static_cast<RenderListMarker*>(curr->renderer())->isInside()) { + xPos += curr->boxModelObject()->marginLeft(); + curr->setX(xPos); + leftPosition = min(xPos + toRenderBox(curr->renderer())->overflowLeft(false), leftPosition); + rightPosition = max(xPos + toRenderBox(curr->renderer())->overflowWidth(false), rightPosition); + xPos += curr->width() + curr->boxModelObject()->marginRight(); } } } - x += borderRight() + paddingRight(); - setWidth(x - startX); - rightPosition = max(xPos() + width() + boxShadowRight, rightPosition); + xPos += borderRight() + paddingRight(); + setWidth(xPos - startX); + rightPosition = max(x() + width() + boxShadowRight, rightPosition); - return x; + return xPos; } int InlineFlowBox::verticallyAlignBoxes(int heightOfBlock) @@ -359,8 +352,8 @@ int InlineFlowBox::verticallyAlignBoxes(int heightOfBlock) // Figure out if we're in strict mode. Note that we can't simply use !style()->htmlHacks(), // because that would match almost strict mode as well. - RenderObject* curr = object(); - while (curr && !curr->element()) + RenderObject* curr = renderer(); + while (curr && !curr->node()) curr = curr->container(); bool strictMode = (curr && curr->document()->inStrictMode()); @@ -378,10 +371,6 @@ int InlineFlowBox::verticallyAlignBoxes(int heightOfBlock) setVerticalOverflowPositions(topPosition, bottomPosition); setVerticalSelectionPositions(selectionTop, selectionBottom); - - // Shrink boxes with no text children in quirks and almost strict mode. - if (!strictMode) - shrinkBoxesWithNoTextChildren(topPosition, bottomPosition); heightOfBlock += maxHeight; @@ -394,16 +383,17 @@ void InlineFlowBox::adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent, for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { // The computed lineheight needs to be extended for the // positioned elements - if (curr->object()->isPositioned()) + if (curr->renderer()->isPositioned()) continue; // Positioned placeholders don't affect calculations. - if (curr->yPos() == PositionTop || curr->yPos() == PositionBottom) { - if (curr->yPos() == PositionTop) { - if (maxAscent + maxDescent < curr->height()) - maxDescent = curr->height() - maxAscent; + if (curr->y() == PositionTop || curr->y() == PositionBottom) { + int lineHeight = curr->renderer()->lineHeight(m_firstLine); + if (curr->y() == PositionTop) { + if (maxAscent + maxDescent < lineHeight) + maxDescent = lineHeight - maxAscent; } else { - if (maxAscent + maxDescent < curr->height()) - maxAscent = curr->height() - maxDescent; + if (maxAscent + maxDescent < lineHeight) + maxAscent = lineHeight - maxDescent; } if (maxAscent + maxDescent >= max(maxPositionTop, maxPositionBottom)) @@ -415,22 +405,25 @@ void InlineFlowBox::adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent, } } +static int verticalPositionForBox(InlineBox* curr, bool firstLine) +{ + if (curr->renderer()->isText()) + return curr->parent()->y(); + if (curr->renderer()->isBox()) + return toRenderBox(curr->renderer())->verticalPosition(firstLine); + return toRenderInline(curr->renderer())->verticalPositionFromCache(firstLine); +} + void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositionBottom, int& maxAscent, int& maxDescent, bool strictMode) { if (isRootInlineBox()) { // Examine our root box. - setHeight(object()->lineHeight(m_firstLine, true)); - bool isTableCell = object()->isTableCell(); - if (isTableCell) { - RenderTableCell* tableCell = static_cast<RenderTableCell*>(object()); - setBaseline(tableCell->RenderBlock::baselinePosition(m_firstLine, true)); - } - else - setBaseline(object()->baselinePosition(m_firstLine, true)); + int lineHeight = renderer()->lineHeight(m_firstLine, true); + int baseline = renderer()->baselinePosition(m_firstLine, true); if (hasTextChildren() || strictMode) { - int ascent = baseline(); - int descent = height() - ascent; + int ascent = baseline; + int descent = lineHeight - ascent; if (maxAscent < ascent) maxAscent = ascent; if (maxDescent < descent) @@ -439,23 +432,25 @@ void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositi } for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { - if (curr->object()->isPositioned()) + if (curr->renderer()->isPositioned()) continue; // Positioned placeholders don't affect calculations. - curr->setHeight(curr->object()->lineHeight(m_firstLine)); - curr->setBaseline(curr->object()->baselinePosition(m_firstLine)); - curr->setYPos(curr->object()->verticalPositionHint(m_firstLine)); - if (curr->yPos() == PositionTop) { - if (maxPositionTop < curr->height()) - maxPositionTop = curr->height(); + bool isInlineFlow = curr->isInlineFlowBox(); + + int lineHeight = curr->renderer()->lineHeight(m_firstLine); + int baseline = curr->renderer()->baselinePosition(m_firstLine); + curr->setY(verticalPositionForBox(curr, m_firstLine)); + if (curr->y() == PositionTop) { + if (maxPositionTop < lineHeight) + maxPositionTop = lineHeight; } - else if (curr->yPos() == PositionBottom) { - if (maxPositionBottom < curr->height()) - maxPositionBottom = curr->height(); + else if (curr->y() == PositionBottom) { + if (maxPositionBottom < lineHeight) + maxPositionBottom = lineHeight; } - else if (curr->hasTextChildren() || curr->renderBox()->hasHorizontalBordersOrPadding() || strictMode) { - int ascent = curr->baseline() - curr->yPos(); - int descent = curr->height() - ascent; + else if ((!isInlineFlow || static_cast<InlineFlowBox*>(curr)->hasTextChildren()) || curr->boxModelObject()->hasHorizontalBordersOrPadding() || strictMode) { + int ascent = baseline - curr->y(); + int descent = lineHeight - ascent; if (maxAscent < ascent) maxAscent = ascent; if (maxDescent < descent) @@ -467,135 +462,106 @@ void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositi } } -void InlineFlowBox::placeBoxesVertically(int y, int maxHeight, int maxAscent, bool strictMode, +void InlineFlowBox::placeBoxesVertically(int yPos, int maxHeight, int maxAscent, bool strictMode, int& topPosition, int& bottomPosition, int& selectionTop, int& selectionBottom) { if (isRootInlineBox()) - setYPos(y + maxAscent - baseline());// Place our root box. + setY(yPos + max(0, maxAscent - renderer()->baselinePosition(m_firstLine, true))); // Place our root box. for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { - if (curr->object()->isPositioned()) + if (curr->renderer()->isPositioned()) continue; // Positioned placeholders don't affect calculations. // Adjust boxes to use their real box y/height and not the logical height (as dictated by // line-height). - if (curr->isInlineFlowBox()) - static_cast<InlineFlowBox*>(curr)->placeBoxesVertically(y, maxHeight, maxAscent, strictMode, topPosition, bottomPosition, selectionTop, selectionBottom); + bool isInlineFlow = curr->isInlineFlowBox(); + if (isInlineFlow) + static_cast<InlineFlowBox*>(curr)->placeBoxesVertically(yPos, maxHeight, maxAscent, strictMode, topPosition, bottomPosition, selectionTop, selectionBottom); bool childAffectsTopBottomPos = true; - if (curr->yPos() == PositionTop) - curr->setYPos(y); - else if (curr->yPos() == PositionBottom) - curr->setYPos(y + maxHeight - curr->height()); + if (curr->y() == PositionTop) + curr->setY(yPos); + else if (curr->y() == PositionBottom) + curr->setY(yPos + maxHeight - curr->renderer()->lineHeight(m_firstLine)); else { - if (!curr->hasTextChildren() && !curr->renderBox()->hasHorizontalBordersOrPadding() && !strictMode) + if ((isInlineFlow && !static_cast<InlineFlowBox*>(curr)->hasTextChildren()) && !curr->boxModelObject()->hasHorizontalBordersOrPadding() && !strictMode) childAffectsTopBottomPos = false; - curr->setYPos(curr->yPos() + y + maxAscent - curr->baseline()); + int posAdjust = maxAscent - curr->renderer()->baselinePosition(m_firstLine); + if (!childAffectsTopBottomPos) + posAdjust = max(0, posAdjust); + curr->setY(curr->y() + yPos + posAdjust); } - int newY = curr->yPos(); - int newHeight = curr->height(); - int newBaseline = curr->baseline(); + int newY = curr->y(); int overflowTop = 0; int overflowBottom = 0; if (curr->isText() || curr->isInlineFlowBox()) { - const Font& font = curr->object()->style(m_firstLine)->font(); - newBaseline = font.ascent(); - newY += curr->baseline() - newBaseline; - newHeight = newBaseline + font.descent(); - for (ShadowData* shadow = curr->object()->style()->textShadow(); shadow; shadow = shadow->next) { + const Font& font = curr->renderer()->style(m_firstLine)->font(); + newY += curr->renderer()->baselinePosition(m_firstLine) - font.ascent(); + for (ShadowData* shadow = curr->renderer()->style()->textShadow(); shadow; shadow = shadow->next) { overflowTop = min(overflowTop, shadow->y - shadow->blur); overflowBottom = max(overflowBottom, shadow->y + shadow->blur); } - for (ShadowData* boxShadow = curr->object()->style(m_firstLine)->boxShadow(); boxShadow; boxShadow = boxShadow->next) { + for (ShadowData* boxShadow = curr->renderer()->style(m_firstLine)->boxShadow(); boxShadow; boxShadow = boxShadow->next) { overflowTop = min(overflowTop, boxShadow->y - boxShadow->blur); overflowBottom = max(overflowBottom, boxShadow->y + boxShadow->blur); } - for (ShadowData* textShadow = curr->object()->style(m_firstLine)->textShadow(); textShadow; textShadow = textShadow->next) { + for (ShadowData* textShadow = curr->renderer()->style(m_firstLine)->textShadow(); textShadow; textShadow = textShadow->next) { overflowTop = min(overflowTop, textShadow->y - textShadow->blur); overflowBottom = max(overflowBottom, textShadow->y + textShadow->blur); } - if (curr->object()->hasReflection()) { - overflowTop = min(overflowTop, curr->renderBox()->reflectionBox().y()); - overflowBottom = max(overflowBottom, curr->renderBox()->reflectionBox().bottom()); + if (curr->renderer()->hasReflection()) { + RenderBox* box = toRenderBox(curr->renderer()); + overflowTop = min(overflowTop, box->reflectionBox().y()); + overflowBottom = max(overflowBottom, box->reflectionBox().bottom()); } - if (curr->isInlineFlowBox()) { - newHeight += curr->renderBox()->borderTop() + curr->renderBox()->paddingTop() + - curr->renderBox()->borderBottom() + curr->renderBox()->paddingBottom(); - newY -= curr->renderBox()->borderTop() + curr->renderBox()->paddingTop(); - newBaseline += curr->renderBox()->borderTop() + curr->renderBox()->paddingTop(); - } - } else if (!curr->object()->isBR()) { - newY += curr->renderBox()->marginTop(); - newHeight = curr->height() - (curr->renderBox()->marginTop() + curr->renderBox()->marginBottom()); - overflowTop = curr->renderBox()->overflowTop(false); - overflowBottom = curr->renderBox()->overflowHeight(false) - newHeight; + if (curr->isInlineFlowBox()) + newY -= curr->boxModelObject()->borderTop() + curr->boxModelObject()->paddingTop(); + } else if (!curr->renderer()->isBR()) { + RenderBox* box = toRenderBox(curr->renderer()); + newY += box->marginTop(); + overflowTop = box->overflowTop(false); + overflowBottom = box->overflowHeight(false) - box->height(); } - curr->setYPos(newY); - curr->setHeight(newHeight); - curr->setBaseline(newBaseline); + curr->setY(newY); if (childAffectsTopBottomPos) { selectionTop = min(selectionTop, newY); - selectionBottom = max(selectionBottom, newY + newHeight); + selectionBottom = max(selectionBottom, newY + curr->height()); topPosition = min(topPosition, newY + overflowTop); - bottomPosition = max(bottomPosition, newY + newHeight + overflowBottom); + bottomPosition = max(bottomPosition, newY + curr->height() + overflowBottom); } } if (isRootInlineBox()) { - const Font& font = object()->style(m_firstLine)->font(); - setHeight(font.ascent() + font.descent()); - setYPos(yPos() + baseline() - font.ascent()); - setBaseline(font.ascent()); + const Font& font = renderer()->style(m_firstLine)->font(); + setY(y() + renderer()->baselinePosition(m_firstLine, true) - font.ascent()); if (hasTextChildren() || strictMode) { - selectionTop = min(selectionTop, yPos()); - selectionBottom = max(selectionBottom, yPos() + height()); + selectionTop = min(selectionTop, y()); + selectionBottom = max(selectionBottom, y() + height()); } } } -void InlineFlowBox::shrinkBoxesWithNoTextChildren(int topPos, int bottomPos) -{ - // First shrink our kids. - for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { - if (curr->object()->isPositioned()) - continue; // Positioned placeholders don't affect calculations. - - if (curr->isInlineFlowBox()) - static_cast<InlineFlowBox*>(curr)->shrinkBoxesWithNoTextChildren(topPos, bottomPos); - } - - // See if we have text children. If not, then we need to shrink ourselves to fit on the line. - if (!hasTextChildren() && !renderBox()->hasHorizontalBordersOrPadding()) { - if (yPos() < topPos) - setYPos(topPos); - if (yPos() + height() > bottomPos) - setHeight(bottomPos - yPos()); - if (baseline() > height()) - setBaseline(height()); - } -} - bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty) { // Check children first. for (InlineBox* curr = lastChild(); curr; curr = curr->prevOnLine()) { - if (!curr->object()->hasLayer() && curr->nodeAtPoint(request, result, x, y, tx, ty)) { - object()->updateHitTestResult(result, IntPoint(x - tx, y - ty)); + if ((curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer()) && curr->nodeAtPoint(request, result, x, y, tx, ty)) { + renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty)); return true; } } // Now check ourselves. - IntRect rect(tx + m_x, ty + m_y, m_width, m_height); + IntRect rect(tx + m_x, ty + m_y, m_width, height()); if (visibleToHitTesting() && rect.contains(x, y)) { - object()->updateHitTestResult(result, IntPoint(x - tx, y - ty)); // Don't add in m_x or m_y here, we want coords in the containing block's space. + renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty)); // Don't add in m_x or m_y here, we want coords in the containing block's space. return true; } @@ -604,15 +570,15 @@ bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re void InlineFlowBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) { - int xPos = tx + m_x - object()->maximalOutlineSize(paintInfo.phase); - int w = width() + 2 * object()->maximalOutlineSize(paintInfo.phase); + int xPos = tx + m_x - renderer()->maximalOutlineSize(paintInfo.phase); + int w = width() + 2 * renderer()->maximalOutlineSize(paintInfo.phase); int shadowLeft = 0; int shadowRight = 0; - for (ShadowData* boxShadow = object()->style(m_firstLine)->boxShadow(); boxShadow; boxShadow = boxShadow->next) { + for (ShadowData* boxShadow = renderer()->style(m_firstLine)->boxShadow(); boxShadow; boxShadow = boxShadow->next) { shadowLeft = min(boxShadow->x - boxShadow->blur, shadowLeft); shadowRight = max(boxShadow->x + boxShadow->blur, shadowRight); } - for (ShadowData* textShadow = object()->style(m_firstLine)->textShadow(); textShadow; textShadow = textShadow->next) { + for (ShadowData* textShadow = renderer()->style(m_firstLine)->textShadow(); textShadow; textShadow = textShadow->next) { shadowLeft = min(textShadow->x - textShadow->blur, shadowLeft); shadowRight = max(textShadow->x + textShadow->blur, shadowRight); } @@ -624,14 +590,15 @@ void InlineFlowBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) { // Add ourselves to the paint info struct's list of inlines that need to paint their // outlines. - if (object()->style()->visibility() == VISIBLE && object()->hasOutline() && !isRootInlineBox()) { - if ((flowObject()->continuation() || object()->isInlineContinuation()) && !object()->hasLayer()) { + if (renderer()->style()->visibility() == VISIBLE && renderer()->hasOutline() && !isRootInlineBox()) { + RenderInline* inlineFlow = toRenderInline(renderer()); + if ((inlineFlow->continuation() || inlineFlow->isInlineContinuation()) && !boxModelObject()->hasSelfPaintingLayer()) { // Add ourselves to the containing block of the entire continuation so that it can // paint us atomically. - RenderBlock* block = object()->containingBlock()->containingBlock(); - block->addContinuationWithOutline(static_cast<RenderFlow*>(object()->element()->renderer())); - } else if (!object()->isInlineContinuation()) - paintInfo.outlineObjects->add(flowObject()); + RenderBlock* block = renderer()->containingBlock()->containingBlock(); + block->addContinuationWithOutline(toRenderInline(renderer()->node()->renderer())); + } else if (!inlineFlow->isInlineContinuation()) + paintInfo.outlineObjects->add(inlineFlow); } } else if (paintInfo.phase == PaintPhaseMask) { paintMask(paintInfo, tx, ty); @@ -651,12 +618,12 @@ void InlineFlowBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) PaintPhase paintPhase = paintInfo.phase == PaintPhaseChildOutlines ? PaintPhaseOutline : paintInfo.phase; RenderObject::PaintInfo childInfo(paintInfo); childInfo.phase = paintPhase; - childInfo.paintingRoot = object()->paintingRootForChildren(paintInfo); + childInfo.paintingRoot = renderer()->paintingRootForChildren(paintInfo); // 3. Paint our children. if (paintPhase != PaintPhaseSelfOutline) { for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { - if (!curr->object()->hasLayer()) + if (curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer()) curr->paint(childInfo, tx, ty); } } @@ -679,9 +646,9 @@ void InlineFlowBox::paintFillLayer(const RenderObject::PaintInfo& paintInfo, con int my, int mh, int tx, int ty, int w, int h, CompositeOperator op) { StyleImage* img = fillLayer->image(); - bool hasFillImage = img && img->canRender(object()->style()->effectiveZoom()); - if ((!hasFillImage && !object()->style()->hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent()) - object()->paintFillLayerExtended(paintInfo, c, fillLayer, my, mh, tx, ty, w, h, this, op); + bool hasFillImage = img && img->canRender(renderer()->style()->effectiveZoom()); + if ((!hasFillImage && !renderer()->style()->hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent()) + boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, my, mh, tx, ty, w, h, this, op); else { // We have a fill image that spans multiple lines. // We need to adjust _tx and _ty by the width of all previous lines. @@ -700,7 +667,7 @@ void InlineFlowBox::paintFillLayer(const RenderObject::PaintInfo& paintInfo, con totalWidth += curr->width(); paintInfo.context->save(); paintInfo.context->clip(IntRect(tx, ty, width(), height())); - object()->paintFillLayerExtended(paintInfo, c, fillLayer, my, mh, startX, ty, totalWidth, h, this, op); + boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, my, mh, startX, ty, totalWidth, h, this, op); paintInfo.context->restore(); } } @@ -708,17 +675,17 @@ void InlineFlowBox::paintFillLayer(const RenderObject::PaintInfo& paintInfo, con void InlineFlowBox::paintBoxShadow(GraphicsContext* context, RenderStyle* s, int tx, int ty, int w, int h) { if ((!prevLineBox() && !nextLineBox()) || !parent()) - object()->paintBoxShadow(context, tx, ty, w, h, s); + boxModelObject()->paintBoxShadow(context, tx, ty, w, h, s); else { // FIXME: We can do better here in the multi-line case. We want to push a clip so that the shadow doesn't // protrude incorrectly at the edges, and we want to possibly include shadows cast from the previous/following lines - object()->paintBoxShadow(context, tx, ty, w, h, s, includeLeftEdge(), includeRightEdge()); + boxModelObject()->paintBoxShadow(context, tx, ty, w, h, s, includeLeftEdge(), includeRightEdge()); } } void InlineFlowBox::paintBoxDecorations(RenderObject::PaintInfo& paintInfo, int tx, int ty) { - if (!object()->shouldPaintWithinRoot(paintInfo) || object()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseForeground) + if (!renderer()->shouldPaintWithinRoot(paintInfo) || renderer()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseForeground) return; // Move x/y to our coordinates. @@ -739,8 +706,8 @@ void InlineFlowBox::paintBoxDecorations(RenderObject::PaintInfo& paintInfo, int // You can use p::first-line to specify a background. If so, the root line boxes for // a line may actually have to paint a background. - RenderStyle* styleToUse = object()->style(m_firstLine); - if ((!parent() && m_firstLine && styleToUse != object()->style()) || (parent() && object()->hasBoxDecorations())) { + RenderStyle* styleToUse = renderer()->style(m_firstLine); + if ((!parent() && m_firstLine && styleToUse != renderer()->style()) || (parent() && renderer()->hasBoxDecorations())) { // Shadow comes first and is behind the background and border. if (styleToUse->boxShadow()) paintBoxShadow(context, styleToUse, tx, ty, w, h); @@ -750,8 +717,8 @@ void InlineFlowBox::paintBoxDecorations(RenderObject::PaintInfo& paintInfo, int // :first-line cannot be used to put borders on a line. Always paint borders with our // non-first-line style. - if (parent() && object()->style()->hasBorder()) { - StyleImage* borderImage = object()->style()->borderImage().image(); + if (parent() && renderer()->style()->hasBorder()) { + StyleImage* borderImage = renderer()->style()->borderImage().image(); bool hasBorderImage = borderImage && borderImage->canRender(styleToUse->effectiveZoom()); if (hasBorderImage && !borderImage->isLoaded()) return; // Don't paint anything while we wait for the image to load. @@ -759,7 +726,7 @@ void InlineFlowBox::paintBoxDecorations(RenderObject::PaintInfo& paintInfo, int // The simple case is where we either have no border image or we are the only box for this object. In those // cases only a single call to draw is required. if (!hasBorderImage || (!prevLineBox() && !nextLineBox())) - object()->paintBorder(context, tx, ty, w, h, object()->style(), includeLeftEdge(), includeRightEdge()); + boxModelObject()->paintBorder(context, tx, ty, w, h, renderer()->style(), includeLeftEdge(), includeRightEdge()); else { // We have a border image that spans multiple lines. // We need to adjust _tx and _ty by the width of all previous lines. @@ -778,7 +745,7 @@ void InlineFlowBox::paintBoxDecorations(RenderObject::PaintInfo& paintInfo, int totalWidth += curr->width(); context->save(); context->clip(IntRect(tx, ty, width(), height())); - object()->paintBorder(context, startX, ty, totalWidth, h, object()->style()); + boxModelObject()->paintBorder(context, startX, ty, totalWidth, h, renderer()->style()); context->restore(); } } @@ -787,7 +754,7 @@ void InlineFlowBox::paintBoxDecorations(RenderObject::PaintInfo& paintInfo, int void InlineFlowBox::paintMask(RenderObject::PaintInfo& paintInfo, int tx, int ty) { - if (!object()->shouldPaintWithinRoot(paintInfo) || object()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask) + if (!renderer()->shouldPaintWithinRoot(paintInfo) || renderer()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask) return; // Move x/y to our coordinates. @@ -807,9 +774,9 @@ void InlineFlowBox::paintMask(RenderObject::PaintInfo& paintInfo, int tx, int ty // Figure out if we need to push a transparency layer to render our mask. bool pushTransparencyLayer = false; - const NinePieceImage& maskNinePieceImage = object()->style()->maskBoxImage(); - StyleImage* maskBoxImage = object()->style()->maskBoxImage().image(); - if ((maskBoxImage && object()->style()->maskLayers()->hasImage()) || object()->style()->maskLayers()->next()) + const NinePieceImage& maskNinePieceImage = renderer()->style()->maskBoxImage(); + StyleImage* maskBoxImage = renderer()->style()->maskBoxImage().image(); + if ((maskBoxImage && renderer()->style()->maskLayers()->hasImage()) || renderer()->style()->maskLayers()->next()) pushTransparencyLayer = true; CompositeOperator compositeOp = CompositeDestinationIn; @@ -819,16 +786,16 @@ void InlineFlowBox::paintMask(RenderObject::PaintInfo& paintInfo, int tx, int ty compositeOp = CompositeSourceOver; } - paintFillLayers(paintInfo, Color(), object()->style()->maskLayers(), my, mh, tx, ty, w, h, compositeOp); + paintFillLayers(paintInfo, Color(), renderer()->style()->maskLayers(), my, mh, tx, ty, w, h, compositeOp); - bool hasBoxImage = maskBoxImage && maskBoxImage->canRender(object()->style()->effectiveZoom()); + bool hasBoxImage = maskBoxImage && maskBoxImage->canRender(renderer()->style()->effectiveZoom()); if (!hasBoxImage || !maskBoxImage->isLoaded()) return; // Don't paint anything while we wait for the image to load. // The simple case is where we are the only box for this object. In those // cases only a single call to draw is required. if (!prevLineBox() && !nextLineBox()) { - object()->paintNinePieceImage(paintInfo.context, tx, ty, w, h, object()->style(), maskNinePieceImage, compositeOp); + boxModelObject()->paintNinePieceImage(paintInfo.context, tx, ty, w, h, renderer()->style(), maskNinePieceImage, compositeOp); } else { // We have a mask image that spans multiple lines. // We need to adjust _tx and _ty by the width of all previous lines. @@ -841,7 +808,7 @@ void InlineFlowBox::paintMask(RenderObject::PaintInfo& paintInfo, int tx, int ty totalWidth += curr->width(); paintInfo.context->save(); paintInfo.context->clip(IntRect(tx, ty, width(), height())); - object()->paintNinePieceImage(paintInfo.context, startX, ty, totalWidth, h, object()->style(), maskNinePieceImage, compositeOp); + boxModelObject()->paintNinePieceImage(paintInfo.context, startX, ty, totalWidth, h, renderer()->style(), maskNinePieceImage, compositeOp); paintInfo.context->restore(); } @@ -857,7 +824,7 @@ static bool shouldDrawTextDecoration(RenderObject* obj) if (curr->isText() && !curr->isBR()) { if (!curr->style()->collapseWhiteSpace()) return true; - Node* currElement = curr->element(); + Node* currElement = curr->node(); if (!currElement) return true; if (!currElement->isTextNode()) @@ -873,8 +840,8 @@ void InlineFlowBox::paintTextDecorations(RenderObject::PaintInfo& paintInfo, int { // Paint text decorations like underlines/overlines. We only do this if we aren't in quirks mode (i.e., in // almost-strict mode or strict mode). - if (object()->style()->htmlHacks() || !object()->shouldPaintWithinRoot(paintInfo) || - object()->style()->visibility() != VISIBLE) + if (renderer()->style()->htmlHacks() || !renderer()->shouldPaintWithinRoot(paintInfo) || + renderer()->style()->visibility() != VISIBLE) return; // We don't want underlines or other decorations when we're trying to draw nothing but the selection as white text. @@ -884,16 +851,16 @@ void InlineFlowBox::paintTextDecorations(RenderObject::PaintInfo& paintInfo, int GraphicsContext* context = paintInfo.context; tx += m_x; ty += m_y; - RenderStyle* styleToUse = object()->style(m_firstLine); + RenderStyle* styleToUse = renderer()->style(m_firstLine); int deco = parent() ? styleToUse->textDecoration() : styleToUse->textDecorationsInEffect(); if (deco != TDNONE && ((!paintedChildren && ((deco & UNDERLINE) || (deco & OVERLINE))) || (paintedChildren && (deco & LINE_THROUGH))) && - shouldDrawTextDecoration(object())) { + shouldDrawTextDecoration(renderer())) { int x = m_x + borderLeft() + paddingLeft(); int w = m_width - (borderLeft() + paddingLeft() + borderRight() + paddingRight()); RootInlineBox* rootLine = root(); if (rootLine->ellipsisBox()) { - int ellipsisX = rootLine->ellipsisBox()->xPos(); + int ellipsisX = rootLine->ellipsisBox()->x(); int ellipsisWidth = rootLine->ellipsisBox()->width(); // FIXME: Will need to work with RTL @@ -914,9 +881,9 @@ void InlineFlowBox::paintTextDecorations(RenderObject::PaintInfo& paintInfo, int Color underline, overline, linethrough; underline = overline = linethrough = styleToUse->color(); if (!parent()) - object()->getTextDecorationColors(deco, underline, overline, linethrough); + renderer()->getTextDecorationColors(deco, underline, overline, linethrough); - bool isPrinting = object()->document()->printing(); + bool isPrinting = renderer()->document()->printing(); context->setStrokeThickness(1.0f); // FIXME: We should improve this rule and not always just assume 1. bool paintUnderline = deco & UNDERLINE && !paintedChildren; @@ -925,13 +892,17 @@ void InlineFlowBox::paintTextDecorations(RenderObject::PaintInfo& paintInfo, int bool linesAreOpaque = !isPrinting && (!paintUnderline || underline.alpha() == 255) && (!paintOverline || overline.alpha() == 255) && (!paintLineThrough || linethrough.alpha() == 255); + int baselinePos = renderer()->style(m_firstLine)->font().ascent(); + if (!isRootInlineBox()) + baselinePos += borderTop() + paddingTop(); + bool setClip = false; int extraOffset = 0; ShadowData* shadow = styleToUse->textShadow(); if (!linesAreOpaque && shadow && shadow->next) { - IntRect clipRect(tx, ty, w, m_baseline + 2); + IntRect clipRect(tx, ty, w, baselinePos + 2); for (ShadowData* s = shadow; s; s = s->next) { - IntRect shadowRect(tx, ty, w, m_baseline + 2); + IntRect shadowRect(tx, ty, w, baselinePos + 2); shadowRect.inflate(s->blur); shadowRect.move(s->x, s->y); clipRect.unite(shadowRect); @@ -939,7 +910,7 @@ void InlineFlowBox::paintTextDecorations(RenderObject::PaintInfo& paintInfo, int } context->save(); context->clip(clipRect); - extraOffset += m_baseline + 2; + extraOffset += baselinePos + 2; ty += extraOffset; setClip = true; } @@ -959,16 +930,19 @@ void InlineFlowBox::paintTextDecorations(RenderObject::PaintInfo& paintInfo, int if (paintUnderline) { context->setStrokeColor(underline); + context->setStrokeStyle(SolidStroke); // Leave one pixel of white between the baseline and the underline. - context->drawLineForText(IntPoint(tx, ty + m_baseline + 1), w, isPrinting); + context->drawLineForText(IntPoint(tx, ty + baselinePos + 1), w, isPrinting); } if (paintOverline) { context->setStrokeColor(overline); + context->setStrokeStyle(SolidStroke); context->drawLineForText(IntPoint(tx, ty), w, isPrinting); } if (paintLineThrough) { context->setStrokeColor(linethrough); - context->drawLineForText(IntPoint(tx, ty + 2 * m_baseline / 3), w, isPrinting); + context->setStrokeStyle(SolidStroke); + context->drawLineForText(IntPoint(tx, ty + 2 * baselinePos / 3), w, isPrinting); } } while (shadow); |