diff options
author | Steve Block <steveblock@google.com> | 2009-10-08 17:19:54 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2009-10-20 00:41:58 +0100 |
commit | 231d4e3152a9c27a73b6ac7badbe6be673aa3ddf (patch) | |
tree | a6c7e2d6cd7bfa7011cc39abbb436142d7a4a7c8 /WebCore/rendering | |
parent | e196732677050bd463301566a68a643b6d14b907 (diff) | |
download | external_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.zip external_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.tar.gz external_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.tar.bz2 |
Merge webkit.org at R49305 : Automatic merge by git.
Change-Id: I8968561bc1bfd72b8923b7118d3728579c6dbcc7
Diffstat (limited to 'WebCore/rendering')
94 files changed, 3742 insertions, 2834 deletions
diff --git a/WebCore/rendering/CounterNode.cpp b/WebCore/rendering/CounterNode.cpp index c30ca9a..f546abb 100644 --- a/WebCore/rendering/CounterNode.cpp +++ b/WebCore/rendering/CounterNode.cpp @@ -63,11 +63,17 @@ void CounterNode::recount() for (CounterNode* c = this; c; c = c->m_nextSibling) { int oldCount = c->m_countInParent; int newCount = c->computeCountInParent(); - c->m_countInParent = newCount; if (oldCount == newCount) break; - if (c->m_renderer->isCounter()) - c->m_renderer->setNeedsLayoutAndPrefWidthsRecalc(); + c->m_countInParent = newCount; + // m_renderer contains the parent of the render node + // corresponding to a CounterNode. Let's find the counter + // child and make this re-layout. + for (RenderObject* o = c->m_renderer->firstChild(); o; o = o->nextSibling()) + if (!o->documentBeingDestroyed() && o->isCounter()) { + o->setNeedsLayoutAndPrefWidthsRecalc(); + break; + } } } @@ -167,13 +173,13 @@ static void showTreeAndMark(const CounterNode* node) for (const CounterNode* c = root; c; c = nextInPreOrder(c)) { if (c == node) - fprintf(stderr, "*"); + fprintf(stderr, "*"); for (const CounterNode* d = c; d && d != root; d = d->parent()) fprintf(stderr, "\t"); if (c->isReset()) - fprintf(stderr, "reset: %d\n", c->value()); + fprintf(stderr, "reset: %d %d\n", c->value(), c->countInParent()); else - fprintf(stderr, "increment: %d\n", c->value()); + fprintf(stderr, "increment: %d %d\n", c->value(), c->countInParent()); } } diff --git a/WebCore/rendering/FixedTableLayout.cpp b/WebCore/rendering/FixedTableLayout.cpp index ee3e75a..4852708 100644 --- a/WebCore/rendering/FixedTableLayout.cpp +++ b/WebCore/rendering/FixedTableLayout.cpp @@ -188,6 +188,11 @@ int FixedTableLayout::calcWidthArray(int) return usedWidth; } +// Use a very large value (in effect infinite). But not too large! +// numeric_limits<int>::max() will too easily overflow widths. +// Keep this in synch with BLOCK_MAX_WIDTH in RenderBlock.cpp +#define TABLE_MAX_WIDTH 15000 + void FixedTableLayout::calcPrefWidths(int& minWidth, int& maxWidth) { // FIXME: This entire calculation is incorrect for both minwidth and maxwidth. @@ -206,6 +211,24 @@ void FixedTableLayout::calcPrefWidths(int& minWidth, int& maxWidth) minWidth = max(mw, tableWidth); maxWidth = minWidth; + + // This quirk is very similar to one that exists in RenderBlock::calcBlockPrefWidths(). + // Here's the example for this one: + /* + <table style="width:100%; background-color:red"><tr><td> + <table style="background-color:blue"><tr><td> + <table style="width:100%; background-color:green; table-layout:fixed"><tr><td> + Content + </td></tr></table> + </td></tr></table> + </td></tr></table> + */ + // In this example, the two inner tables should be as large as the outer table. + // We can achieve this effect by making the maxwidth of fixed tables with percentage + // widths be infinite. + if (m_table->style()->htmlHacks() && m_table->style()->width().isPercent() + && maxWidth < TABLE_MAX_WIDTH) + maxWidth = TABLE_MAX_WIDTH; } void FixedTableLayout::layout() diff --git a/WebCore/rendering/HitTestResult.cpp b/WebCore/rendering/HitTestResult.cpp index b7de46b..0aaddc9 100644 --- a/WebCore/rendering/HitTestResult.cpp +++ b/WebCore/rendering/HitTestResult.cpp @@ -209,7 +209,7 @@ String HitTestResult::altDisplayString() const if (m_innerNonSharedNode->hasTagName(imgTag)) { HTMLImageElement* image = static_cast<HTMLImageElement*>(m_innerNonSharedNode.get()); - return displayString(image->alt(), m_innerNonSharedNode.get()); + return displayString(image->getAttribute(altAttr), m_innerNonSharedNode.get()); } if (m_innerNonSharedNode->hasTagName(inputTag)) { diff --git a/WebCore/rendering/InlineBox.cpp b/WebCore/rendering/InlineBox.cpp index bbf11b3..2575fb7 100644 --- a/WebCore/rendering/InlineBox.cpp +++ b/WebCore/rendering/InlineBox.cpp @@ -98,18 +98,11 @@ int InlineBox::height() const return toRenderBox(m_renderer)->height(); ASSERT(isInlineFlowBox()); - const InlineFlowBox* flowBox = static_cast<const InlineFlowBox*>(this); RenderBoxModelObject* flowObject = boxModelObject(); const Font& font = renderer()->style(m_firstLine)->font(); int result = font.height(); - bool strictMode = renderer()->document()->inStrictMode(); if (parent()) result += flowObject->borderTop() + flowObject->paddingTop() + flowObject->borderBottom() + flowObject->paddingBottom(); - if (strictMode || flowBox->hasTextChildren() || flowObject->hasHorizontalBordersOrPadding()) - return result; - int bottom = root()->bottomOverflow(); - if (y() + result > bottom) - result = bottom - y(); return result; } diff --git a/WebCore/rendering/InlineBox.h b/WebCore/rendering/InlineBox.h index c03758d..e165f0c 100644 --- a/WebCore/rendering/InlineBox.h +++ b/WebCore/rendering/InlineBox.h @@ -208,11 +208,6 @@ public: inline int baselinePosition(bool isRootLineBox) const { return renderer()->baselinePosition(m_firstLine, isRootLineBox); } inline int lineHeight(bool isRootLineBox) const { return renderer()->lineHeight(m_firstLine, isRootLineBox); } - virtual int topOverflow() const { return y(); } - virtual int bottomOverflow() const { return y() + height(); } - virtual int leftOverflow() const { return x(); } - virtual int rightOverflow() const { return x() + width(); } - virtual int caretMinOffset() const; virtual int caretMaxOffset() const; virtual unsigned caretMaxRenderedOffset() const; diff --git a/WebCore/rendering/InlineFlowBox.cpp b/WebCore/rendering/InlineFlowBox.cpp index 543c190..143d3d8 100644 --- a/WebCore/rendering/InlineFlowBox.cpp +++ b/WebCore/rendering/InlineFlowBox.cpp @@ -29,6 +29,7 @@ #include "RootInlineBox.h" #include "RenderBlock.h" #include "RenderInline.h" +#include "RenderLayer.h" #include "RenderListMarker.h" #include "RenderTableCell.h" #include "RootInlineBox.h" @@ -167,6 +168,8 @@ void InlineFlowBox::adjustPosition(int dx, int dy) InlineRunBox::adjustPosition(dx, dy); for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) child->adjustPosition(dx, dy); + if (m_overflow) + m_overflow->move(dx, dy); } RenderLineBoxList* InlineFlowBox::rendererLineBoxes() const @@ -248,16 +251,21 @@ void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, RenderObject* en } } -int InlineFlowBox::placeBoxesHorizontally(int xPos, int& leftPosition, int& rightPosition, bool& needsWordSpacing) +int InlineFlowBox::placeBoxesHorizontally(int xPos, bool& needsWordSpacing) { // Set our x position. setX(xPos); + int leftLayoutOverflow = xPos; + int rightLayoutOverflow = xPos; + int leftVisualOverflow = xPos; + int rightVisualOverflow = xPos; + int boxShadowLeft; int boxShadowRight; renderer()->style(m_firstLine)->getBoxShadowHorizontalExtent(boxShadowLeft, boxShadowRight); - leftPosition = min(xPos + boxShadowLeft, leftPosition); + leftVisualOverflow = min(xPos + boxShadowLeft, leftVisualOverflow); int startX = xPos; xPos += borderLeft() + paddingLeft(); @@ -275,23 +283,24 @@ int InlineFlowBox::placeBoxesHorizontally(int xPos, int& leftPosition, int& righ int strokeOverflow = static_cast<int>(ceilf(rt->style()->textStrokeWidth() / 2.0f)); - // If letter-spacing is negative, we should factor that into right overflow. (Even in RTL, letter-spacing is + // If letter-spacing is negative, we should factor that into right layout overflow. (Even in RTL, letter-spacing is // applied to the right, so this is not an issue with left overflow. int letterSpacing = min(0, (int)rt->style(m_firstLine)->font().letterSpacing()); - + rightLayoutOverflow = max(xPos + text->width() - letterSpacing, rightLayoutOverflow); + int leftGlyphOverflow = -strokeOverflow; int rightGlyphOverflow = strokeOverflow - letterSpacing; - int visualOverflowLeft = leftGlyphOverflow; - int visualOverflowRight = rightGlyphOverflow; + int childOverflowLeft = leftGlyphOverflow; + int childOverflowRight = rightGlyphOverflow; for (ShadowData* shadow = rt->style()->textShadow(); shadow; shadow = shadow->next) { - visualOverflowLeft = min(visualOverflowLeft, shadow->x - shadow->blur + leftGlyphOverflow); - visualOverflowRight = max(visualOverflowRight, shadow->x + shadow->blur + rightGlyphOverflow); + childOverflowLeft = min(childOverflowLeft, shadow->x - shadow->blur + leftGlyphOverflow); + childOverflowRight = max(childOverflowRight, shadow->x + shadow->blur + rightGlyphOverflow); } - leftPosition = min(xPos + visualOverflowLeft, leftPosition); - rightPosition = max(xPos + text->width() + visualOverflowRight, rightPosition); - m_maxHorizontalVisualOverflow = max(max(visualOverflowRight, -visualOverflowLeft), (int)m_maxHorizontalVisualOverflow); + leftVisualOverflow = min(xPos + childOverflowLeft, leftVisualOverflow); + rightVisualOverflow = max(xPos + text->width() + childOverflowRight, rightVisualOverflow); + xPos += text->width(); } else { if (curr->renderer()->isPositioned()) { @@ -307,13 +316,26 @@ int InlineFlowBox::placeBoxesHorizontally(int xPos, int& leftPosition, int& righ if (curr->renderer()->isRenderInline()) { InlineFlowBox* flow = static_cast<InlineFlowBox*>(curr); xPos += flow->marginLeft(); - xPos = flow->placeBoxesHorizontally(xPos, leftPosition, rightPosition, needsWordSpacing); + xPos = flow->placeBoxesHorizontally(xPos, needsWordSpacing); xPos += flow->marginRight(); + leftLayoutOverflow = min(leftLayoutOverflow, flow->leftLayoutOverflow()); + rightLayoutOverflow = max(rightLayoutOverflow, flow->rightLayoutOverflow()); + leftVisualOverflow = min(leftVisualOverflow, flow->leftVisualOverflow()); + rightVisualOverflow = max(rightVisualOverflow, flow->rightVisualOverflow()); } else if (!curr->renderer()->isListMarker() || toRenderListMarker(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); + + RenderBox* box = toRenderBox(curr->renderer()); + int childLeftOverflow = box->hasOverflowClip() ? 0 : box->leftLayoutOverflow(); + int childRightOverflow = box->hasOverflowClip() ? curr->width() : box->rightLayoutOverflow(); + + leftLayoutOverflow = min(xPos + childLeftOverflow, leftLayoutOverflow); + rightLayoutOverflow = max(xPos + childRightOverflow, rightLayoutOverflow); + + leftVisualOverflow = min(xPos + box->leftVisualOverflow(), leftVisualOverflow); + rightVisualOverflow = max(xPos + box->rightVisualOverflow(), rightVisualOverflow); + xPos += curr->width() + curr->boxModelObject()->marginRight(); } } @@ -321,45 +343,13 @@ int InlineFlowBox::placeBoxesHorizontally(int xPos, int& leftPosition, int& righ xPos += borderRight() + paddingRight(); setWidth(xPos - startX); - rightPosition = max(x() + width() + boxShadowRight, rightPosition); + rightVisualOverflow = max(x() + width() + boxShadowRight, rightVisualOverflow); + rightLayoutOverflow = max(x() + width(), rightLayoutOverflow); + setHorizontalOverflowPositions(leftLayoutOverflow, rightLayoutOverflow, leftVisualOverflow, rightVisualOverflow); return xPos; } -int InlineFlowBox::verticallyAlignBoxes(int heightOfBlock) -{ - int maxPositionTop = 0; - int maxPositionBottom = 0; - int maxAscent = 0; - int maxDescent = 0; - - // 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 = renderer(); - while (curr && !curr->node()) - curr = curr->container(); - bool strictMode = (curr && curr->document()->inStrictMode()); - - computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode); - - if (maxAscent + maxDescent < max(maxPositionTop, maxPositionBottom)) - adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom); - - int maxHeight = maxAscent + maxDescent; - int topPosition = heightOfBlock; - int bottomPosition = heightOfBlock; - int selectionTop = heightOfBlock; - int selectionBottom = heightOfBlock; - placeBoxesVertically(heightOfBlock, maxHeight, maxAscent, strictMode, topPosition, bottomPosition, selectionTop, selectionBottom); - - setVerticalOverflowPositions(topPosition, bottomPosition); - setVerticalSelectionPositions(selectionTop, selectionBottom); - - heightOfBlock += maxHeight; - - return heightOfBlock; -} - void InlineFlowBox::adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent, int maxPositionTop, int maxPositionBottom) { @@ -479,11 +469,10 @@ void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositi } } -void InlineFlowBox::placeBoxesVertically(int yPos, int maxHeight, int maxAscent, bool strictMode, - int& topPosition, int& bottomPosition, int& selectionTop, int& selectionBottom) +void InlineFlowBox::placeBoxesVertically(int yPos, int maxHeight, int maxAscent, bool strictMode, int& selectionTop, int& selectionBottom) { if (isRootInlineBox()) - setY(yPos + max(0, maxAscent - baselinePosition(true))); // Place our root box. + setY(yPos + maxAscent - baselinePosition(true)); // Place our root box. for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { if (curr->renderer()->isPositioned()) @@ -493,7 +482,7 @@ void InlineFlowBox::placeBoxesVertically(int yPos, int maxHeight, int maxAscent, // line-height). bool isInlineFlow = curr->isInlineFlowBox(); if (isInlineFlow) - static_cast<InlineFlowBox*>(curr)->placeBoxesVertically(yPos, maxHeight, maxAscent, strictMode, topPosition, bottomPosition, selectionTop, selectionBottom); + static_cast<InlineFlowBox*>(curr)->placeBoxesVertically(yPos, maxHeight, maxAscent, strictMode, selectionTop, selectionBottom); bool childAffectsTopBottomPos = true; if (curr->y() == PositionTop) @@ -504,43 +493,18 @@ void InlineFlowBox::placeBoxesVertically(int yPos, int maxHeight, int maxAscent, if ((isInlineFlow && !static_cast<InlineFlowBox*>(curr)->hasTextChildren()) && !curr->boxModelObject()->hasHorizontalBordersOrPadding() && !strictMode) childAffectsTopBottomPos = false; int posAdjust = maxAscent - curr->baselinePosition(false); - if (!childAffectsTopBottomPos) - posAdjust = max(0, posAdjust); curr->setY(curr->y() + yPos + posAdjust); } - // FIXME: By only considering overflow as part of the root line box, we can't get an accurate picture regarding what the line - // actually needs to paint. A line box that is part of a self-painting layer technically shouldn't contribute to the overflow - // of the line, but in order to not do this and paint accurately, we have to track the overflow somewhere else (either by storing overflow - // in each InlineFlowBox up the chain or in the layer itself). Relative positioned objects on a line will cause scrollbars - // to appear when they shouldn't until we fix this issue. int newY = curr->y(); - int overflowTop = 0; - int overflowBottom = 0; if (curr->isText() || curr->isInlineFlowBox()) { const Font& font = curr->renderer()->style(m_firstLine)->font(); newY += curr->baselinePosition(false) - font.ascent(); - - curr->renderer()->style(m_firstLine)->getBoxShadowVerticalExtent(overflowTop, overflowBottom); - - 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->renderer()->hasReflection()) { - RenderBox* box = toRenderBox(curr->renderer()); - overflowTop = min(overflowTop, box->reflectionBox().y()); - overflowBottom = max(overflowBottom, box->reflectionBox().bottom()); - } - 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->setY(newY); @@ -549,8 +513,6 @@ void InlineFlowBox::placeBoxesVertically(int yPos, int maxHeight, int maxAscent, int boxHeight = curr->height(); selectionTop = min(selectionTop, newY); selectionBottom = max(selectionBottom, newY + boxHeight); - topPosition = min(topPosition, newY + overflowTop); - bottomPosition = max(bottomPosition, newY + boxHeight + overflowBottom); } } @@ -564,8 +526,88 @@ void InlineFlowBox::placeBoxesVertically(int yPos, int maxHeight, int maxAscent, } } +void InlineFlowBox::computeVerticalOverflow(int lineTop, int lineBottom, bool strictMode) +{ + int boxHeight = height(); + + // Any spillage outside of the line top and bottom is not considered overflow. We just ignore this, since it only happens + // from the "your ascent/descent don't affect the line" quirk. + // FIXME: Technically this means there can be repaint errors in the case where a line box has a shadow or background that spills + // outside of the block. We should consider making any line box that has anything to render just stop respecting the quirk or making + // boxes that render something set visual overflow. + int topOverflow = max(y(), lineTop); + int bottomOverflow = min(y() + boxHeight, lineBottom); + + int topLayoutOverflow = topOverflow; + int bottomLayoutOverflow = bottomOverflow; + + int topVisualOverflow = topOverflow; + int bottomVisualOverflow = bottomOverflow; + + // box-shadow on root line boxes is applying to the block and not to the lines. + if (parent()) { + int boxShadowTop; + int boxShadowBottom; + renderer()->style(m_firstLine)->getBoxShadowVerticalExtent(boxShadowTop, boxShadowBottom); + + topVisualOverflow = min(y() + boxShadowTop, topVisualOverflow); + bottomVisualOverflow = max(y() + boxHeight + boxShadowBottom, bottomVisualOverflow); + } + + for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { + if (curr->renderer()->isPositioned()) + continue; // Positioned placeholders don't affect calculations. + + if (curr->renderer()->isText()) { + InlineTextBox* text = static_cast<InlineTextBox*>(curr); + RenderText* rt = toRenderText(text->renderer()); + if (rt->isBR()) + continue; + + int strokeOverflow = static_cast<int>(ceilf(rt->style()->textStrokeWidth() / 2.0f)); + + int topGlyphOverflow = -strokeOverflow; + int bottomGlyphOverflow = strokeOverflow; + + int childOverflowTop = topGlyphOverflow; + int childOverflowBottom = bottomGlyphOverflow; + for (ShadowData* shadow = rt->style()->textShadow(); shadow; shadow = shadow->next) { + childOverflowTop = min(childOverflowTop, shadow->y - shadow->blur + topGlyphOverflow); + childOverflowBottom = max(childOverflowBottom, shadow->y + shadow->blur + bottomGlyphOverflow); + } + + topVisualOverflow = min(curr->y() + childOverflowTop, topVisualOverflow); + bottomVisualOverflow = max(curr->y() + text->height() + childOverflowBottom, bottomVisualOverflow); + } else if (curr->renderer()->isRenderInline()) { + InlineFlowBox* flow = static_cast<InlineFlowBox*>(curr); + flow->computeVerticalOverflow(lineTop, lineBottom, strictMode); + topLayoutOverflow = min(topLayoutOverflow, flow->topLayoutOverflow()); + bottomLayoutOverflow = max(bottomLayoutOverflow, flow->bottomLayoutOverflow()); + topVisualOverflow = min(topVisualOverflow, flow->topVisualOverflow()); + bottomVisualOverflow = max(bottomVisualOverflow, flow->bottomVisualOverflow()); + } else if (!curr->boxModelObject()->hasSelfPaintingLayer()){ + // Only include overflow from replaced inlines if they do not paint themselves. + RenderBox* box = toRenderBox(curr->renderer()); + int boxY = curr->y(); + int childTopOverflow = box->hasOverflowClip() ? 0 : box->topLayoutOverflow(); + int childBottomOverflow = box->hasOverflowClip() ? curr->height() : box->bottomLayoutOverflow(); + topLayoutOverflow = min(boxY + childTopOverflow, topLayoutOverflow); + bottomLayoutOverflow = max(boxY + childBottomOverflow, bottomLayoutOverflow); + topVisualOverflow = min(boxY + box->topVisualOverflow(), topVisualOverflow); + bottomVisualOverflow = max(boxY + box->bottomVisualOverflow(), bottomVisualOverflow); + } + } + + setVerticalOverflowPositions(topLayoutOverflow, bottomLayoutOverflow, topVisualOverflow, bottomVisualOverflow, boxHeight); +} + bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty) { + IntRect overflowRect(visibleOverflowRect()); + overflowRect.move(tx, ty); + if (!overflowRect.contains(x, y)) + return false; + // Check children first. for (InlineBox* curr = lastChild(); curr; curr = curr->prevOnLine()) { if ((curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer()) && curr->nodeAtPoint(request, result, x, y, tx, ty)) { @@ -586,23 +628,14 @@ bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re void InlineFlowBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) { - int xPos = tx + m_x - renderer()->maximalOutlineSize(paintInfo.phase); - int w = width() + 2 * renderer()->maximalOutlineSize(paintInfo.phase); - int shadowLeft; - int shadowRight; - - renderer()->style(m_firstLine)->getBoxShadowHorizontalExtent(shadowLeft, shadowRight); - - 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); - } - - xPos += shadowLeft; - w += -shadowLeft + shadowRight; - bool intersectsDamageRect = xPos < paintInfo.rect.right() && xPos + w > paintInfo.rect.x(); + IntRect overflowRect(visibleOverflowRect()); + overflowRect.inflate(renderer()->maximalOutlineSize(paintInfo.phase)); + overflowRect.move(tx, ty); + + if (!paintInfo.rect.intersects(overflowRect)) + return; - if (intersectsDamageRect && paintInfo.phase != PaintPhaseChildOutlines) { + if (paintInfo.phase != PaintPhaseChildOutlines) { if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) { // Add ourselves to the paint info struct's list of inlines that need to paint their // outlines. @@ -645,7 +678,7 @@ void InlineFlowBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) } // 4. Paint our strike-through - if (intersectsDamageRect && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection)) + if (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection) paintTextDecorations(paintInfo, tx, ty, true); } @@ -774,18 +807,23 @@ void InlineFlowBox::paintMask(RenderObject::PaintInfo& paintInfo, int tx, int ty int w = width(); int h = height(); - // Figure out if we need to push a transparency layer to render our mask. - bool pushTransparencyLayer = false; 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; - if (pushTransparencyLayer) { - paintInfo.context->setCompositeOperation(CompositeDestinationIn); - paintInfo.context->beginTransparencyLayer(1.0f); - compositeOp = CompositeSourceOver; + + // Figure out if we need to push a transparency layer to render our mask. + bool pushTransparencyLayer = false; + bool compositedMask = renderer()->hasLayer() && boxModelObject()->layer()->hasCompositedMask(); + CompositeOperator compositeOp = CompositeSourceOver; + if (!compositedMask) { + if ((maskBoxImage && renderer()->style()->maskLayers()->hasImage()) || renderer()->style()->maskLayers()->next()) + pushTransparencyLayer = true; + + compositeOp = CompositeDestinationIn; + if (pushTransparencyLayer) { + paintInfo.context->setCompositeOperation(CompositeDestinationIn); + paintInfo.context->beginTransparencyLayer(1.0f); + compositeOp = CompositeSourceOver; + } } paintFillLayers(paintInfo, Color(), renderer()->style()->maskLayers(), tx, ty, w, h, compositeOp); diff --git a/WebCore/rendering/InlineFlowBox.h b/WebCore/rendering/InlineFlowBox.h index 809fd54..23b5cc9 100644 --- a/WebCore/rendering/InlineFlowBox.h +++ b/WebCore/rendering/InlineFlowBox.h @@ -22,6 +22,7 @@ #define InlineFlowBox_h #include "InlineRunBox.h" +#include "RenderOverflow.h" namespace WebCore { @@ -35,10 +36,8 @@ public: : InlineRunBox(obj) , m_firstChild(0) , m_lastChild(0) - , m_maxHorizontalVisualOverflow(0) , m_includeLeftEdge(false) , m_includeRightEdge(false) - , m_hasTextChildren(true) #ifndef NDEBUG , m_hasBadChildList(false) #endif @@ -121,18 +120,13 @@ public: void determineSpacingForFlowBoxes(bool lastLine, RenderObject* endObject); int getFlowSpacingWidth(); bool onEndChain(RenderObject* endObject); - virtual int placeBoxesHorizontally(int x, int& leftPosition, int& rightPosition, bool& needsWordSpacing); - virtual int verticallyAlignBoxes(int heightOfBlock); + virtual int placeBoxesHorizontally(int x, bool& needsWordSpacing); void computeLogicalBoxHeights(int& maxPositionTop, int& maxPositionBottom, int& maxAscent, int& maxDescent, bool strictMode); void adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent, int maxPositionTop, int maxPositionBottom); - void placeBoxesVertically(int y, int maxHeight, int maxAscent, bool strictMode, - int& topPosition, int& bottomPosition, int& selectionTop, int& selectionBottom); - - virtual void setVerticalOverflowPositions(int /*top*/, int /*bottom*/) { } - virtual void setVerticalSelectionPositions(int /*top*/, int /*bottom*/) { } - short maxHorizontalVisualOverflow() const { return m_maxHorizontalVisualOverflow; } + void placeBoxesVertically(int y, int maxHeight, int maxAscent, bool strictMode, int& lineTop, int& lineBottom); + void computeVerticalOverflow(int lineTop, int lineBottom, bool strictMode); void removeChild(InlineBox* child); @@ -146,12 +140,35 @@ public: void checkConsistency() const; void setHasBadChildList(); + int topVisibleOverflow() const { return std::min(topLayoutOverflow(), topVisualOverflow()); } + int bottomVisibleOverflow() const { return std::max(bottomLayoutOverflow(), bottomVisualOverflow()); } + int leftVisibleOverflow() const { return std::min(leftLayoutOverflow(), leftVisualOverflow()); } + int rightVisibleOverflow() const { return std::max(rightLayoutOverflow(), rightVisualOverflow()); } + IntRect visibleOverflowRect() const { return m_overflow ? m_overflow->visibleOverflowRect() : IntRect(m_x, m_y, m_width, height()); } + + int topLayoutOverflow() const { return m_overflow ? m_overflow->topLayoutOverflow() : m_y; } + int bottomLayoutOverflow() const { return m_overflow ? m_overflow->bottomLayoutOverflow() : m_y + height(); } + int leftLayoutOverflow() const { return m_overflow ? m_overflow->leftLayoutOverflow() : m_x; } + int rightLayoutOverflow() const { return m_overflow ? m_overflow->rightLayoutOverflow() : m_x + m_width; } + IntRect layoutOverflowRect() const { return m_overflow ? m_overflow->layoutOverflowRect() : IntRect(m_x, m_y, m_width, height()); } + + int topVisualOverflow() const { return m_overflow ? m_overflow->topVisualOverflow() : m_y; } + int bottomVisualOverflow() const { return m_overflow ? m_overflow->bottomVisualOverflow() : m_y + height(); } + int leftVisualOverflow() const { return m_overflow ? m_overflow->leftVisualOverflow() : m_x; } + int rightVisualOverflow() const { return m_overflow ? m_overflow->rightVisualOverflow() : m_x + m_width; } + IntRect visualOverflowRect() const { return m_overflow ? m_overflow->visualOverflowRect() : IntRect(m_x, m_y, m_width, height()); } + + void setHorizontalOverflowPositions(int leftLayoutOverflow, int rightLayoutOverflow, int leftVisualOverflow, int rightVisualOverflow); + void setVerticalOverflowPositions(int topLayoutOverflow, int bottomLayoutOverflow, int topVisualOverflow, int bottomVisualOverflow, int boxHeight); + +protected: + OwnPtr<RenderOverflow> m_overflow; + private: virtual bool isInlineFlowBox() const { return true; } InlineBox* m_firstChild; InlineBox* m_lastChild; - short m_maxHorizontalVisualOverflow; bool m_includeLeftEdge : 1; bool m_includeRightEdge : 1; @@ -162,6 +179,34 @@ private: #endif }; +inline void InlineFlowBox::setHorizontalOverflowPositions(int leftLayoutOverflow, int rightLayoutOverflow, int leftVisualOverflow, int rightVisualOverflow) +{ + if (!m_overflow) { + if (leftLayoutOverflow == m_x && rightLayoutOverflow == m_x + m_width && leftVisualOverflow == m_x && rightVisualOverflow == m_x + m_width) + return; + m_overflow.set(new RenderOverflow(IntRect(m_x, m_y, m_width, m_renderer->style(m_firstLine)->font().height()))); + } + + m_overflow->setLeftLayoutOverflow(leftLayoutOverflow); + m_overflow->setRightLayoutOverflow(rightLayoutOverflow); + m_overflow->setLeftVisualOverflow(leftVisualOverflow); + m_overflow->setRightVisualOverflow(rightVisualOverflow); +} + +inline void InlineFlowBox::setVerticalOverflowPositions(int topLayoutOverflow, int bottomLayoutOverflow, int topVisualOverflow, int bottomVisualOverflow, int boxHeight) +{ + if (!m_overflow) { + if (topLayoutOverflow == m_y && bottomLayoutOverflow == m_y + boxHeight && topVisualOverflow == m_y && bottomVisualOverflow == m_y + boxHeight) + return; + m_overflow.set(new RenderOverflow(IntRect(m_x, m_y, m_width, boxHeight))); + } + + m_overflow->setTopLayoutOverflow(topLayoutOverflow); + m_overflow->setBottomLayoutOverflow(bottomLayoutOverflow); + m_overflow->setTopVisualOverflow(topVisualOverflow); + m_overflow->setBottomVisualOverflow(bottomVisualOverflow); +} + #ifdef NDEBUG inline void InlineFlowBox::checkConsistency() const { diff --git a/WebCore/rendering/InlineTextBox.cpp b/WebCore/rendering/InlineTextBox.cpp index 619fb95..751340d 100644 --- a/WebCore/rendering/InlineTextBox.cpp +++ b/WebCore/rendering/InlineTextBox.cpp @@ -312,8 +312,12 @@ void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) ASSERT(paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintPhaseChildOutlines); - int xPos = tx + m_x - parent()->maxHorizontalVisualOverflow(); - int w = width() + 2 * parent()->maxHorizontalVisualOverflow(); + // FIXME: Technically we're potentially incorporating other visual overflow that had nothing to do with us. + // Would it be simpler to just check our own shadow and stroke overflow by hand here? + int leftOverflow = parent()->x() - parent()->leftVisualOverflow(); + int rightOverflow = parent()->rightVisualOverflow() - (parent()->x() + parent()->width()); + int xPos = tx + m_x - leftOverflow; + int w = width() + leftOverflow + rightOverflow; if (xPos >= paintInfo.rect.right() || xPos + w <= paintInfo.rect.x()) return; diff --git a/WebCore/rendering/MediaControlElements.cpp b/WebCore/rendering/MediaControlElements.cpp index 352f270..73b9a3a 100644 --- a/WebCore/rendering/MediaControlElements.cpp +++ b/WebCore/rendering/MediaControlElements.cpp @@ -32,28 +32,37 @@ #include "MediaControlElements.h" -#include "LocalizedStrings.h" #include "EventNames.h" #include "FloatConversion.h" #include "Frame.h" #include "HTMLNames.h" +#include "LocalizedStrings.h" #include "MouseEvent.h" #include "RenderMedia.h" #include "RenderSlider.h" #include "RenderTheme.h" -#include "CString.h" namespace WebCore { using namespace HTMLNames; -// FIXME: These constants may need to be tweaked to better match the seeking in the QT plugin +HTMLMediaElement* toParentMediaElement(RenderObject* o) +{ + Node* node = o->node(); + Node* mediaNode = node ? node->shadowAncestorNode() : 0; + if (!mediaNode || (!mediaNode->hasTagName(HTMLNames::videoTag) && !mediaNode->hasTagName(HTMLNames::audioTag))) + return 0; + + return static_cast<HTMLMediaElement*>(mediaNode); +} + +// FIXME: These constants may need to be tweaked to better match the seeking in the QuickTime plug-in. static const float cSeekRepeatDelay = 0.1f; static const float cStepTime = 0.07f; static const float cSeekTime = 0.2f; -MediaControlShadowRootElement::MediaControlShadowRootElement(Document* doc, HTMLMediaElement* mediaElement) - : HTMLDivElement(divTag, doc) +MediaControlShadowRootElement::MediaControlShadowRootElement(Document* document, HTMLMediaElement* mediaElement) + : HTMLDivElement(divTag, document) , m_mediaElement(mediaElement) { RefPtr<RenderStyle> rootStyle = RenderStyle::create(); @@ -76,14 +85,36 @@ void MediaControlShadowRootElement::updateStyle() } // ---------------------------- - -MediaControlElement::MediaControlElement(Document* doc, PseudoId pseudo, HTMLMediaElement* mediaElement) - : HTMLDivElement(divTag, doc) +MediaControlElement::MediaControlElement(Document* document, PseudoId pseudo, HTMLMediaElement* mediaElement) + : HTMLDivElement(divTag, document) , m_mediaElement(mediaElement) , m_pseudoStyleId(pseudo) { setInDocument(true); + switch (pseudo) { + case MEDIA_CONTROLS_CURRENT_TIME_DISPLAY: + m_displayType = MediaCurrentTimeDisplay; + break; + case MEDIA_CONTROLS_TIME_REMAINING_DISPLAY: + m_displayType = MediaTimeRemainingDisplay; + break; + case MEDIA_CONTROLS_TIMELINE_CONTAINER: + m_displayType = MediaTimelineContainer; + break; + case MEDIA_CONTROLS_STATUS_DISPLAY: + m_displayType = MediaStatusDisplay; + break; + case MEDIA_CONTROLS_PANEL: + m_displayType = MediaControlsPanel; + break; + case MEDIA_CONTROLS_VOLUME_SLIDER_CONTAINER: + m_displayType = MediaVolumeSliderContainer; + break; + default: + ASSERT_NOT_REACHED(); + break; + } } void MediaControlElement::attachToParent(Element* parent) @@ -114,7 +145,10 @@ PassRefPtr<RenderStyle> MediaControlElement::styleForElement() bool MediaControlElement::rendererIsNeeded(RenderStyle* style) { - return HTMLDivElement::rendererIsNeeded(style) && parent() && parent()->renderer(); + ASSERT(document()->page()); + + return HTMLDivElement::rendererIsNeeded(style) && parent() && parent()->renderer() + && (!style->hasAppearance() || document()->page()->theme()->shouldRenderMediaControlPart(style->appearance(), m_mediaElement)); } void MediaControlElement::attach() @@ -165,8 +199,8 @@ void MediaControlElement::updateStyle() // ---------------------------- -MediaControlTimelineContainerElement::MediaControlTimelineContainerElement(Document* doc, HTMLMediaElement* element) -: MediaControlElement(doc, MEDIA_CONTROLS_TIMELINE_CONTAINER, element) +MediaControlTimelineContainerElement::MediaControlTimelineContainerElement(Document* document, HTMLMediaElement* element) + : MediaControlElement(document, MEDIA_CONTROLS_TIMELINE_CONTAINER, element) { } @@ -185,12 +219,54 @@ bool MediaControlTimelineContainerElement::rendererIsNeeded(RenderStyle* style) return !isnan(duration) && !isinf(duration); } - // ---------------------------- -MediaControlStatusDisplayElement::MediaControlStatusDisplayElement(Document* doc, HTMLMediaElement* element) -: MediaControlElement(doc, MEDIA_CONTROLS_STATUS_DISPLAY, element) -, m_stateBeingDisplayed(Nothing) +MediaControlVolumeSliderContainerElement::MediaControlVolumeSliderContainerElement(Document* doc, HTMLMediaElement* element) + : MediaControlElement(doc, MEDIA_CONTROLS_VOLUME_SLIDER_CONTAINER, element) + , m_isVisible(false) + , m_x(0) + , m_y(0) +{ +} + +PassRefPtr<RenderStyle> MediaControlVolumeSliderContainerElement::styleForElement() +{ + RefPtr<RenderStyle> style = MediaControlElement::styleForElement(); + style->setPosition(AbsolutePosition); + style->setLeft(Length(m_x, Fixed)); + style->setTop(Length(m_y, Fixed)); + style->setDisplay(m_isVisible ? BLOCK : NONE); + return style; +} + +void MediaControlVolumeSliderContainerElement::setVisible(bool visible) +{ + if (visible == m_isVisible) + return; + m_isVisible = visible; +} + +void MediaControlVolumeSliderContainerElement::setPosition(int x, int y) +{ + if (x == m_x && y == m_y) + return; + m_x = x; + m_y = y; +} + +bool MediaControlVolumeSliderContainerElement::hitTest(const IntPoint& absPoint) +{ + if (renderer() && renderer()->style()->hasAppearance()) + return renderer()->theme()->hitTestMediaControlPart(renderer(), absPoint); + + return false; +} + +// ---------------------------- + +MediaControlStatusDisplayElement::MediaControlStatusDisplayElement(Document* document, HTMLMediaElement* element) + : MediaControlElement(document, MEDIA_CONTROLS_STATUS_DISPLAY, element) + , m_stateBeingDisplayed(Nothing) { } @@ -235,14 +311,46 @@ bool MediaControlStatusDisplayElement::rendererIsNeeded(RenderStyle* style) // ---------------------------- -MediaControlInputElement::MediaControlInputElement(Document* doc, PseudoId pseudo, const String& type, HTMLMediaElement* mediaElement, MediaControlElementType displayType) - : HTMLInputElement(inputTag, doc) +MediaControlInputElement::MediaControlInputElement(Document* document, PseudoId pseudo, const String& type, HTMLMediaElement* mediaElement) + : HTMLInputElement(inputTag, document) , m_mediaElement(mediaElement) , m_pseudoStyleId(pseudo) - , m_displayType(displayType) { setInputType(type); setInDocument(true); + + switch (pseudo) { + case MEDIA_CONTROLS_MUTE_BUTTON: + m_displayType = MediaMuteButton; + break; + case MEDIA_CONTROLS_PLAY_BUTTON: + m_displayType = MediaPlayButton; + break; + case MEDIA_CONTROLS_SEEK_FORWARD_BUTTON: + m_displayType = MediaSeekForwardButton; + break; + case MEDIA_CONTROLS_SEEK_BACK_BUTTON: + m_displayType = MediaSeekBackButton; + break; + case MEDIA_CONTROLS_FULLSCREEN_BUTTON: + m_displayType = MediaFullscreenButton; + break; + case MEDIA_CONTROLS_TIMELINE: + m_displayType = MediaSlider; + break; + case MEDIA_CONTROLS_RETURN_TO_REALTIME_BUTTON: + m_displayType = MediaReturnToRealtimeButton; + break; + case MEDIA_CONTROLS_REWIND_BUTTON: + m_displayType = MediaRewindButton; + break; + case MEDIA_CONTROLS_VOLUME_SLIDER: + m_displayType = MediaVolumeSlider; + break; + default: + ASSERT_NOT_REACHED(); + break; + } } void MediaControlInputElement::attachToParent(Element* parent) @@ -265,7 +373,10 @@ PassRefPtr<RenderStyle> MediaControlInputElement::styleForElement() bool MediaControlInputElement::rendererIsNeeded(RenderStyle* style) { - return HTMLInputElement::rendererIsNeeded(style) && parent() && parent()->renderer(); + ASSERT(document()->page()); + + return HTMLInputElement::rendererIsNeeded(style) && parent() && parent()->renderer() + && (!style->hasAppearance() || document()->page()->theme()->shouldRenderMediaControlPart(style->appearance(), m_mediaElement)); } void MediaControlInputElement::attach() @@ -324,14 +435,14 @@ void MediaControlInputElement::setDisplayType(MediaControlElementType displayTyp return; m_displayType = displayType; - if (RenderObject* o = renderer()) - o->repaint(); + if (RenderObject* object = renderer()) + object->repaint(); } // ---------------------------- -MediaControlMuteButtonElement::MediaControlMuteButtonElement(Document* doc, HTMLMediaElement* element) - : MediaControlInputElement(doc, MEDIA_CONTROLS_MUTE_BUTTON, "button", element, element->muted() ? MediaUnMuteButton : MediaMuteButton) +MediaControlMuteButtonElement::MediaControlMuteButtonElement(Document* document, HTMLMediaElement* element) + : MediaControlInputElement(document, MEDIA_CONTROLS_MUTE_BUTTON, "button", element) { } @@ -351,8 +462,8 @@ void MediaControlMuteButtonElement::updateDisplayType() // ---------------------------- -MediaControlPlayButtonElement::MediaControlPlayButtonElement(Document* doc, HTMLMediaElement* element) - : MediaControlInputElement(doc, MEDIA_CONTROLS_PLAY_BUTTON, "button", element, element->canPlay() ? MediaPlayButton : MediaPauseButton) +MediaControlPlayButtonElement::MediaControlPlayButtonElement(Document* document, HTMLMediaElement* element) + : MediaControlInputElement(document, MEDIA_CONTROLS_PLAY_BUTTON, "button", element) { } @@ -372,9 +483,9 @@ void MediaControlPlayButtonElement::updateDisplayType() // ---------------------------- -MediaControlSeekButtonElement::MediaControlSeekButtonElement(Document* doc, HTMLMediaElement* element, bool forward) - : MediaControlInputElement(doc, forward ? MEDIA_CONTROLS_SEEK_FORWARD_BUTTON : MEDIA_CONTROLS_SEEK_BACK_BUTTON, - "button", element, forward ? MediaSeekForwardButton : MediaSeekBackButton) +MediaControlSeekButtonElement::MediaControlSeekButtonElement(Document* document, HTMLMediaElement* element, bool forward) + : MediaControlInputElement(document, forward ? MEDIA_CONTROLS_SEEK_FORWARD_BUTTON : MEDIA_CONTROLS_SEEK_BACK_BUTTON, + "button", element) , m_forward(forward) , m_seeking(false) , m_capturing(false) @@ -432,8 +543,8 @@ void MediaControlSeekButtonElement::detach() // ---------------------------- -MediaControlRewindButtonElement::MediaControlRewindButtonElement(Document* doc, HTMLMediaElement* element) -: MediaControlInputElement(doc, MEDIA_CONTROLS_REWIND_BUTTON, "button", element, MediaRewindButton) +MediaControlRewindButtonElement::MediaControlRewindButtonElement(Document* document, HTMLMediaElement* element) + : MediaControlInputElement(document, MEDIA_CONTROLS_REWIND_BUTTON, "button", element) { } @@ -446,16 +557,11 @@ void MediaControlRewindButtonElement::defaultEventHandler(Event* event) HTMLInputElement::defaultEventHandler(event); } -bool MediaControlRewindButtonElement::rendererIsNeeded(RenderStyle* style) -{ - return MediaControlInputElement::rendererIsNeeded(style) && m_mediaElement->movieLoadType() != MediaPlayer::LiveStream; -} - // ---------------------------- -MediaControlReturnToRealtimeButtonElement::MediaControlReturnToRealtimeButtonElement(Document* doc, HTMLMediaElement* element) -: MediaControlInputElement(doc, MEDIA_CONTROLS_RETURN_TO_REALTIME_BUTTON, "button", element, MediaReturnToRealtimeButton) +MediaControlReturnToRealtimeButtonElement::MediaControlReturnToRealtimeButtonElement(Document* document, HTMLMediaElement* element) + : MediaControlInputElement(document, MEDIA_CONTROLS_RETURN_TO_REALTIME_BUTTON, "button", element) { } @@ -468,22 +574,18 @@ void MediaControlReturnToRealtimeButtonElement::defaultEventHandler(Event* event HTMLInputElement::defaultEventHandler(event); } -bool MediaControlReturnToRealtimeButtonElement::rendererIsNeeded(RenderStyle* style) -{ - return MediaControlInputElement::rendererIsNeeded(style) && m_mediaElement->movieLoadType() == MediaPlayer::LiveStream; -} // ---------------------------- MediaControlTimelineElement::MediaControlTimelineElement(Document* document, HTMLMediaElement* element) - : MediaControlInputElement(document, MEDIA_CONTROLS_TIMELINE, "range", element, MediaTimelineContainer) -{ + : MediaControlInputElement(document, MEDIA_CONTROLS_TIMELINE, "range", element) +{ } void MediaControlTimelineElement::defaultEventHandler(Event* event) { - // Left button is 0. Accepts only if mouse event is from left button. - if (!event->isMouseEvent() || static_cast<MouseEvent*>(event)->button()) + // Left button is 0. Rejects mouse events not from left button. + if (event->isMouseEvent() && static_cast<MouseEvent*>(event)->button()) return; if (event->type() == eventNames().mousedownEvent) @@ -520,29 +622,51 @@ void MediaControlTimelineElement::update(bool updateDuration) // ---------------------------- -MediaControlFullscreenButtonElement::MediaControlFullscreenButtonElement(Document* doc, HTMLMediaElement* element) - : MediaControlInputElement(doc, MEDIA_CONTROLS_FULLSCREEN_BUTTON, "button", element, MediaFullscreenButton) +MediaControlVolumeSliderElement::MediaControlVolumeSliderElement(Document* document, HTMLMediaElement* element) + : MediaControlInputElement(document, MEDIA_CONTROLS_VOLUME_SLIDER, "range", element) { } -void MediaControlFullscreenButtonElement::defaultEventHandler(Event* event) +void MediaControlVolumeSliderElement::defaultEventHandler(Event* event) { - if (event->type() == eventNames().clickEvent) { - event->setDefaultHandled(); + // Left button is 0. Rejects mouse events not from left button. + if (event->isMouseEvent() && static_cast<MouseEvent*>(event)->button()) + return; + + MediaControlInputElement::defaultEventHandler(event); + + if (event->type() == eventNames().mouseoverEvent || event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mousemoveEvent) + return; + + float volume = narrowPrecisionToFloat(value().toDouble()); + if (volume != m_mediaElement->volume()) { + ExceptionCode ec = 0; + m_mediaElement->setVolume(volume, ec); + ASSERT(!ec); } - HTMLInputElement::defaultEventHandler(event); } -bool MediaControlFullscreenButtonElement::rendererIsNeeded(RenderStyle* style) +// ---------------------------- + +MediaControlFullscreenButtonElement::MediaControlFullscreenButtonElement(Document* document, HTMLMediaElement* element) + : MediaControlInputElement(document, MEDIA_CONTROLS_FULLSCREEN_BUTTON, "button", element) { - return MediaControlInputElement::rendererIsNeeded(style) && m_mediaElement->supportsFullscreen(); } +void MediaControlFullscreenButtonElement::defaultEventHandler(Event* event) +{ + if (event->type() == eventNames().clickEvent) { + m_mediaElement->enterFullscreen(); + event->setDefaultHandled(); + } + HTMLInputElement::defaultEventHandler(event); +} // ---------------------------- -MediaControlTimeDisplayElement::MediaControlTimeDisplayElement(Document* doc, PseudoId pseudo, HTMLMediaElement* element) - : MediaControlElement(doc, pseudo, element) +MediaControlTimeDisplayElement::MediaControlTimeDisplayElement(Document* document, PseudoId pseudo, HTMLMediaElement* element) + : MediaControlElement(document, pseudo, element) + , m_currentValue(0) , m_isVisible(true) { } @@ -572,6 +696,32 @@ void MediaControlTimeDisplayElement::setVisible(bool visible) renderer()->setStyle(style.get()); } +String MediaControlTimeDisplayElement::formatTime(float time) +{ + if (!isfinite(time)) + time = 0; + int seconds = (int)fabsf(time); + int hours = seconds / (60 * 60); + int minutes = (seconds / 60) % 60; + seconds %= 60; + if (hours) { + if (hours > 9) + return String::format("%s%02d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds); + + return String::format("%s%01d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds); + } + + return String::format("%s%02d:%02d", (time < 0 ? "-" : ""), minutes, seconds); +} + +void MediaControlTimeDisplayElement::setCurrentValue(float time) +{ + m_currentValue = time; + + ExceptionCode ec; + setInnerText(formatTime(m_currentValue), ec); +} + } //namespace WebCore #endif // enable(video) diff --git a/WebCore/rendering/MediaControlElements.h b/WebCore/rendering/MediaControlElements.h index d5fa5d2..e562bb5 100644 --- a/WebCore/rendering/MediaControlElements.h +++ b/WebCore/rendering/MediaControlElements.h @@ -57,12 +57,17 @@ enum MediaControlElementType { MediaUnMuteButton, MediaPauseButton, MediaTimelineContainer, - MediaCurrentTimeDisplay, + MediaCurrentTimeDisplay, MediaTimeRemainingDisplay, MediaStatusDisplay, - MediaControlsPanel + MediaControlsPanel, + MediaVolumeSliderContainer, + MediaVolumeSlider, + MediaVolumeSliderThumb }; +HTMLMediaElement* toParentMediaElement(RenderObject*); + class MediaControlShadowRootElement : public HTMLDivElement { public: MediaControlShadowRootElement(Document*, HTMLMediaElement*); @@ -89,9 +94,15 @@ public: void update(); virtual void updateStyle(); + MediaControlElementType displayType() const { return m_displayType; } + + HTMLMediaElement* mediaElement() const { return m_mediaElement; } + virtual bool isMediaControlElement() const { return true; } + protected: HTMLMediaElement* m_mediaElement; PseudoId m_pseudoStyleId; + MediaControlElementType m_displayType; // some elements can show multiple types (e.g. play/pause) }; // ---------------------------- @@ -104,6 +115,22 @@ public: // ---------------------------- +class MediaControlVolumeSliderContainerElement : public MediaControlElement { +public: + MediaControlVolumeSliderContainerElement(Document*, HTMLMediaElement*); + virtual PassRefPtr<RenderStyle> styleForElement(); + void setVisible(bool); + bool isVisible() { return m_isVisible; } + void setPosition(int x, int y); + bool hitTest(const IntPoint& absPoint); + +private: + bool m_isVisible; + int m_x, m_y; +}; + +// ---------------------------- + class MediaControlStatusDisplayElement : public MediaControlElement { public: MediaControlStatusDisplayElement(Document*, HTMLMediaElement*); @@ -118,7 +145,7 @@ private: class MediaControlInputElement : public HTMLInputElement { public: - MediaControlInputElement(Document*, PseudoId, const String& type, HTMLMediaElement*, MediaControlElementType); + MediaControlInputElement(Document*, PseudoId, const String& type, HTMLMediaElement*); virtual void attach(); virtual bool rendererIsNeeded(RenderStyle*); @@ -130,13 +157,16 @@ public: bool hitTest(const IntPoint& absPoint); MediaControlElementType displayType() const { return m_displayType; } + HTMLMediaElement* mediaElement() const { return m_mediaElement; } + virtual bool isMediaControlElement() const { return true; } + protected: virtual void updateDisplayType() { } void setDisplayType(MediaControlElementType); HTMLMediaElement* m_mediaElement; PseudoId m_pseudoStyleId; - MediaControlElementType m_displayType; // some elements can show multiple types (e.g. play/pause) + MediaControlElementType m_displayType; }; // ---------------------------- @@ -179,7 +209,6 @@ class MediaControlRewindButtonElement : public MediaControlInputElement { public: MediaControlRewindButtonElement(Document*, HTMLMediaElement*); virtual void defaultEventHandler(Event*); - virtual bool rendererIsNeeded(RenderStyle*); }; // ---------------------------- @@ -188,7 +217,6 @@ class MediaControlReturnToRealtimeButtonElement : public MediaControlInputElemen public: MediaControlReturnToRealtimeButtonElement(Document*, HTMLMediaElement*); virtual void defaultEventHandler(Event*); - virtual bool rendererIsNeeded(RenderStyle*); }; // ---------------------------- @@ -202,11 +230,18 @@ public: // ---------------------------- +class MediaControlVolumeSliderElement : public MediaControlInputElement { +public: + MediaControlVolumeSliderElement(Document*, HTMLMediaElement*); + virtual void defaultEventHandler(Event*); +}; + +// ---------------------------- + class MediaControlFullscreenButtonElement : public MediaControlInputElement { public: MediaControlFullscreenButtonElement(Document*, HTMLMediaElement*); virtual void defaultEventHandler(Event*); - virtual bool rendererIsNeeded(RenderStyle*); }; // ---------------------------- @@ -217,7 +252,13 @@ public: void setVisible(bool); virtual PassRefPtr<RenderStyle> styleForElement(); + void setCurrentValue(float); + float currentValue() const { return m_currentValue; } + private: + String formatTime(float time); + + float m_currentValue; bool m_isVisible; }; diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp index e10c331..c6d18d2 100644 --- a/WebCore/rendering/RenderBlock.cpp +++ b/WebCore/rendering/RenderBlock.cpp @@ -33,6 +33,7 @@ #include "HTMLNames.h" #include "HitTestResult.h" #include "InlineTextBox.h" +#include "RenderFlexibleBox.h" #include "RenderImage.h" #include "RenderInline.h" #include "RenderMarquee.h" @@ -118,8 +119,6 @@ RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, int top, int bottom) m_posMargin = m_canCollapseTopWithChildren ? block->maxTopMargin(true) : 0; m_negMargin = m_canCollapseTopWithChildren ? block->maxTopMargin(false) : 0; - - m_selfCollapsingBlockClearedFloat = false; m_topQuirk = m_bottomQuirk = m_determinedTopQuirk = false; } @@ -132,10 +131,6 @@ RenderBlock::RenderBlock(Node* node) , m_positionedObjects(0) , m_inlineContinuation(0) , m_maxMargin(0) - , m_overflowHeight(0) - , m_overflowWidth(0) - , m_overflowLeft(0) - , m_overflowTop(0) , m_lineHeight(-1) { setChildrenInline(true); @@ -554,103 +549,6 @@ void RenderBlock::removeChild(RenderObject* oldChild) } } -int RenderBlock::overflowHeight(bool includeInterior) const -{ - if (!includeInterior && hasOverflowClip()) { - int shadowTop; - int shadowBottom; - style()->getBoxShadowVerticalExtent(shadowTop, shadowBottom); - - int inflatedHeight = height() + shadowBottom; - if (hasReflection()) - inflatedHeight = max(inflatedHeight, reflectionBox().bottom()); - return inflatedHeight; - } - return m_overflowHeight; -} - -int RenderBlock::overflowWidth(bool includeInterior) const -{ - if (!includeInterior && hasOverflowClip()) { - int shadowLeft; - int shadowRight; - style()->getBoxShadowHorizontalExtent(shadowLeft, shadowRight); - - int inflatedWidth = width() + shadowRight; - if (hasReflection()) - inflatedWidth = max(inflatedWidth, reflectionBox().right()); - return inflatedWidth; - } - return m_overflowWidth; -} - -int RenderBlock::overflowLeft(bool includeInterior) const -{ - if (!includeInterior && hasOverflowClip()) { - int shadowLeft; - int shadowRight; - style()->getBoxShadowHorizontalExtent(shadowLeft, shadowRight); - - int left = shadowLeft; - if (hasReflection()) - left = min(left, reflectionBox().x()); - return left; - } - return m_overflowLeft; -} - -int RenderBlock::overflowTop(bool includeInterior) const -{ - if (!includeInterior && hasOverflowClip()) { - int shadowTop; - int shadowBottom; - style()->getBoxShadowVerticalExtent(shadowTop, shadowBottom); - - int top = shadowTop; - if (hasReflection()) - top = min(top, reflectionBox().y()); - return top; - } - return m_overflowTop; -} - -IntRect RenderBlock::overflowRect(bool includeInterior) const -{ - if (!includeInterior && hasOverflowClip()) { - IntRect box = borderBoxRect(); - - int shadowLeft; - int shadowRight; - int shadowTop; - int shadowBottom; - style()->getBoxShadowExtent(shadowTop, shadowRight, shadowBottom, shadowLeft); - - box.move(shadowLeft, shadowTop); - box.setWidth(box.width() - shadowLeft + shadowRight); - box.setHeight(box.height() - shadowTop + shadowBottom); - - if (hasReflection()) { - IntRect reflection(reflectionBox()); - int reflectTop = min(box.y(), reflection.y()); - int reflectBottom = max(box.bottom(), reflection.bottom()); - box.setHeight(reflectBottom - reflectTop); - box.setY(reflectTop); - - int reflectLeft = min(box.x(), reflection.x()); - int reflectRight = max(box.right(), reflection.right()); - box.setWidth(reflectRight - reflectLeft); - box.setX(reflectLeft); - } - return box; - } - - if (!includeInterior && hasOverflowClip()) - return borderBoxRect(); - int l = overflowLeft(includeInterior); - int t = overflowTop(includeInterior); - return IntRect(l, t, overflowWidth(includeInterior) - l, max(overflowHeight(includeInterior), height()) - t); -} - bool RenderBlock::isSelfCollapsingBlock() const { // We are not self-collapsing if we @@ -744,13 +642,9 @@ void RenderBlock::layout() layoutBlock(false); // It's safe to check for control clip here, since controls can never be table cells. - if (hasControlClip()) { - // Because of the lightweight clip, there can never be any overflow from children. - m_overflowWidth = width(); - m_overflowHeight = height(); - m_overflowLeft = 0; - m_overflowTop = 0; - } + // If we have a lightweight clip, there can never be any overflow from children. + if (hasControlClip() && m_overflow) + clearLayoutOverflow(); } void RenderBlock::layoutBlock(bool relayoutChildren) @@ -776,8 +670,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren) calcWidth(); calcColumnWidth(); - m_overflowWidth = width(); - m_overflowLeft = 0; + m_overflow.clear(); if (oldWidth != width() || oldColumnWidth != desiredColumnWidth()) relayoutChildren = true; @@ -795,8 +688,6 @@ void RenderBlock::layoutBlock(bool relayoutChildren) int previousHeight = height(); setHeight(0); - m_overflowHeight = 0; - // We use four values, maxTopPos, maxTopNeg, maxBottomPos, and maxBottomNeg, to track // our current maximal positive and negative margins. These values are used when we // are collapsed with adjacent blocks, so for example, if you have block A and B @@ -861,50 +752,35 @@ void RenderBlock::layoutBlock(bool relayoutChildren) } } } + // We have to rebalance columns to the new height. layoutColumns(singleColumnBottom); - - // If the block got expanded in size, then increase our overflowheight to match. - if (m_overflowHeight > height()) - m_overflowHeight -= toAdd; - if (m_overflowHeight < height()) - m_overflowHeight = height(); } + if (previousHeight != height()) relayoutChildren = true; - if ((isCell || isInline() || isFloatingOrPositioned() || isRoot()) && !hasOverflowClip() && !hasControlClip()) - addVisualOverflow(floatRect()); + // It's weird that we're treating float information as normal flow overflow, but we do this because floatRect() isn't + // able to be propagated up the render tree yet. Overflow information is however. This check is designed to catch anyone + // who wasn't going to propagate float information up to the parent and yet could potentially be painted by its ancestor. + if (isRoot() || expandsToEncloseOverhangingFloats()) + addOverflowFromFloats(); - layoutPositionedObjects(relayoutChildren || isRoot()); + // Add overflow from children (unless we're multi-column, since in that case all our child overflow is clipped anyway). + if (!hasColumns()) { + if (childrenInline()) + addOverflowFromInlineChildren(); + else + addOverflowFromBlockChildren(); + } - positionListMarker(); + // Add visual overflow from box-shadow and reflections. + addShadowOverflow(); - // Always ensure our overflow width/height are at least as large as our width/height. - m_overflowWidth = max(m_overflowWidth, width()); - m_overflowHeight = max(m_overflowHeight, height()); - - if (!hasOverflowClip()) { - int shadowLeft; - int shadowRight; - int shadowTop; - int shadowBottom; - style()->getBoxShadowExtent(shadowTop, shadowRight, shadowBottom, shadowLeft); - - m_overflowLeft = min(m_overflowLeft, shadowLeft); - m_overflowWidth = max(m_overflowWidth, width() + shadowRight); - m_overflowTop = min(m_overflowTop, shadowTop); - m_overflowHeight = max(m_overflowHeight, height() + shadowBottom); - - if (hasReflection()) { - IntRect reflection(reflectionBox()); - m_overflowLeft = min(m_overflowLeft, reflection.x()); - m_overflowWidth = max(m_overflowWidth, reflection.right()); - m_overflowTop = min(m_overflowTop, reflection.y()); - m_overflowHeight = max(m_overflowHeight, reflection.bottom()); - } - } + layoutPositionedObjects(relayoutChildren || isRoot()); + positionListMarker(); + statePusher.pop(); // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if @@ -914,7 +790,9 @@ void RenderBlock::layoutBlock(bool relayoutChildren) // Repaint with our new bounds if they are different from our old bounds. bool didFullRepaint = repainter.repaintAfterLayout(); if (!didFullRepaint && repaintTop != repaintBottom && (style()->visibility() == VISIBLE || enclosingLayer()->hasVisibleContent())) { - IntRect repaintRect(m_overflowLeft, repaintTop, m_overflowWidth - m_overflowLeft, repaintBottom - repaintTop); + int repaintLeft = min(leftVisualOverflow(), leftLayoutOverflow()); + int repaintRight = max(rightVisualOverflow(), rightLayoutOverflow()); + IntRect repaintRect(repaintLeft, repaintTop, repaintRight - repaintLeft, repaintBottom - repaintTop); // FIXME: Deal with multiple column repainting. We have to split the repaint // rect up into multiple rects if it spans columns. @@ -943,6 +821,28 @@ void RenderBlock::layoutBlock(bool relayoutChildren) setNeedsLayout(false); } +void RenderBlock::addOverflowFromBlockChildren() +{ + for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) { + if (!child->isFloatingOrPositioned()) + addOverflowFromChild(child); + } +} + +void RenderBlock::addOverflowFromFloats() +{ + IntRect result; + if (!m_floatingObjects) + return; + FloatingObject* r; + DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); + for (; (r = it.current()); ++it) { + if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) + addOverflowFromChild(r->m_renderer, IntSize(r->m_left + r->m_renderer->marginLeft(), r->m_top + r->m_renderer->marginTop())); + } + return; +} + bool RenderBlock::expandsToEncloseOverhangingFloats() const { return isInlineBlockOrInlineTable() || isFloatingOrPositioned() || hasOverflowClip() || (parent() && parent()->isFlexibleBox()) || hasColumns() || isTableCell() || isFieldset(); @@ -1032,7 +932,10 @@ bool RenderBlock::handleRunInChild(RenderBox* child) // See if we have a run-in element with inline children. If the // children aren't inline, then just treat the run-in as a normal // block. - if (!child->isRunIn() || !child->childrenInline() && !child->isReplaced()) + if (!child->isRunIn() || !child->childrenInline()) + return false; + // FIXME: We don't handle non-block elements with run-in for now. + if (!child->isRenderBlock()) return false; // Get the next non-positioned/non-floating RenderBlock. @@ -1166,8 +1069,6 @@ int RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo) if (marginInfo.margin()) marginInfo.setBottomQuirk(child->isBottomMarginQuirk() || style()->marginBottomCollapse() == MDISCARD); - - marginInfo.setSelfCollapsingBlockClearedFloat(false); } return ypos; @@ -1183,16 +1084,26 @@ int RenderBlock::clearFloatsIfNeeded(RenderBox* child, MarginInfo& marginInfo, i // For self-collapsing blocks that clear, they can still collapse their // margins with following siblings. Reset the current margins to represent // the self-collapsing block's margins only. - marginInfo.setPosMargin(max(child->maxTopMargin(true), child->maxBottomMargin(true))); - marginInfo.setNegMargin(max(child->maxTopMargin(false), child->maxBottomMargin(false))); + // CSS2.1 states: + // "An element that has had clearance applied to it never collapses its top margin with its parent block's bottom margin. + // Therefore if we are at the bottom of the block, let's go ahead and reset margins to only include the + // self-collapsing block's bottom margin. + bool atBottomOfBlock = true; + for (RenderBox* curr = child->nextSiblingBox(); curr && atBottomOfBlock; curr = curr->nextSiblingBox()) { + if (!curr->isFloatingOrPositioned()) + atBottomOfBlock = false; + } + if (atBottomOfBlock) { + marginInfo.setPosMargin(child->maxBottomMargin(true)); + marginInfo.setNegMargin(child->maxBottomMargin(false)); + } else { + marginInfo.setPosMargin(max(child->maxTopMargin(true), child->maxBottomMargin(true))); + marginInfo.setNegMargin(max(child->maxTopMargin(false), child->maxBottomMargin(false))); + } - // Adjust our height such that we are ready to be collapsed with subsequent siblings. + // Adjust our height such that we are ready to be collapsed with subsequent siblings (or the bottom + // of the parent block). setHeight(child->y() - max(0, marginInfo.margin())); - - // Set a flag that we cleared a float so that we know both to increase the height of the block - // to compensate for the clear and to avoid collapsing our margins with the parent block's - // bottom margin. - marginInfo.setSelfCollapsingBlockClearedFloat(true); } else // Increase our height by the amount we had to clear. setHeight(height() + heightIncrease); @@ -1296,17 +1207,7 @@ void RenderBlock::setCollapsedBottomMargin(const MarginInfo& marginInfo) void RenderBlock::handleBottomOfBlock(int top, int bottom, MarginInfo& marginInfo) { - // If our last flow was a self-collapsing block that cleared a float, then we don't - // collapse it with the bottom of the block. - if (!marginInfo.selfCollapsingBlockClearedFloat()) - marginInfo.setAtBottomOfBlock(true); - else { - // We have to special case the negative margin situation (where the collapsed - // margin of the self-collapsing block is negative), since there's no need - // to make an adjustment in that case. - if (marginInfo.margin() < 0) - marginInfo.clearMargin(); - } + marginInfo.setAtBottomOfBlock(true); // If we can't collapse with children then go ahead and add in the bottom margin. if (!marginInfo.canCollapseWithBottom() && !marginInfo.canCollapseWithTop() @@ -1320,9 +1221,6 @@ void RenderBlock::handleBottomOfBlock(int top, int bottom, MarginInfo& marginInf // If this happens, ensure that the computed height is increased to the minimal height. setHeight(max(height(), top + bottom)); - // Always make sure our overflow height is at least our height. - m_overflowHeight = max(height(), m_overflowHeight); - // Update our bottom collapsed margin info. setCollapsedBottomMargin(marginInfo); } @@ -1350,8 +1248,7 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom int top = borderTop() + paddingTop(); int bottom = borderBottom() + paddingBottom() + horizontalScrollbarHeight(); - m_overflowHeight = top; - setHeight(m_overflowHeight); + setHeight(top); // The margin struct caches all our current margin collapsing state. The compact struct caches state when we encounter compacts, MarginInfo marginInfo(this, top, bottom); @@ -1372,9 +1269,6 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom if (legend == child) continue; // Skip the legend, since it has already been positioned up in the fieldset's border. - int oldTopPosMargin = maxTopPosMargin(); - int oldTopNegMargin = maxTopNegMargin(); - // Make sure we layout children if they need it. // FIXME: Technically percentage height objects only need a relayout if their percentage isn't going to be turned into // an auto value. Add a method to determine this, so that we can avoid the relayout. @@ -1390,127 +1284,127 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom if (handleSpecialChild(child, marginInfo)) continue; - // The child is a normal flow object. Compute its vertical margins now. - child->calcVerticalMargins(); + // Lay out the child. + layoutBlockChild(child, marginInfo, previousFloatBottom, maxFloatBottom); + } + + // Now do the handling of the bottom of the block, adding in our bottom border/padding and + // determining the correct collapsed bottom margin information. + handleBottomOfBlock(top, bottom, marginInfo); +} - // Do not allow a collapse if the margin top collapse style is set to SEPARATE. - if (child->style()->marginTopCollapse() == MSEPARATE) { - marginInfo.setAtTopOfBlock(false); - marginInfo.clearMargin(); - } +void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, int& previousFloatBottom, int& maxFloatBottom) +{ + int oldTopPosMargin = maxTopPosMargin(); + int oldTopNegMargin = maxTopNegMargin(); - // Try to guess our correct y position. In most cases this guess will - // be correct. Only if we're wrong (when we compute the real y position) - // will we have to potentially relayout. - int yPosEstimate = estimateVerticalPosition(child, marginInfo); + // The child is a normal flow object. Compute its vertical margins now. + child->calcVerticalMargins(); - // Cache our old rect so that we can dirty the proper repaint rects if the child moves. - IntRect oldRect(child->x(), child->y() , child->width(), child->height()); + // Do not allow a collapse if the margin top collapse style is set to SEPARATE. + if (child->style()->marginTopCollapse() == MSEPARATE) { + marginInfo.setAtTopOfBlock(false); + marginInfo.clearMargin(); + } + + // Try to guess our correct y position. In most cases this guess will + // be correct. Only if we're wrong (when we compute the real y position) + // will we have to potentially relayout. + int yPosEstimate = estimateVerticalPosition(child, marginInfo); + + // Cache our old rect so that we can dirty the proper repaint rects if the child moves. + IntRect oldRect(child->x(), child->y() , child->width(), child->height()); #ifndef NDEBUG - IntSize oldLayoutDelta = view()->layoutDelta(); + IntSize oldLayoutDelta = view()->layoutDelta(); #endif - // Go ahead and position the child as though it didn't collapse with the top. - view()->addLayoutDelta(IntSize(0, child->y() - yPosEstimate)); - child->setLocation(child->x(), yPosEstimate); - - bool markDescendantsWithFloats = false; - if (yPosEstimate != oldRect.y() && !child->avoidsFloats() && child->isBlockFlow() && toRenderBlock(child)->containsFloats()) + // Go ahead and position the child as though it didn't collapse with the top. + view()->addLayoutDelta(IntSize(0, child->y() - yPosEstimate)); + child->setLocation(child->x(), yPosEstimate); + + bool markDescendantsWithFloats = false; + if (yPosEstimate != oldRect.y() && !child->avoidsFloats() && child->isBlockFlow() && toRenderBlock(child)->containsFloats()) + markDescendantsWithFloats = true; + else if (!child->avoidsFloats() || child->shrinkToAvoidFloats()) { + // If an element might be affected by the presence of floats, then always mark it for + // layout. + int fb = max(previousFloatBottom, floatBottom()); + if (fb > yPosEstimate) markDescendantsWithFloats = true; - else if (!child->avoidsFloats() || child->shrinkToAvoidFloats()) { - // If an element might be affected by the presence of floats, then always mark it for - // layout. - int fb = max(previousFloatBottom, floatBottom()); - if (fb > yPosEstimate) - markDescendantsWithFloats = true; - } + } - if (child->isRenderBlock()) { - if (markDescendantsWithFloats) - toRenderBlock(child)->markAllDescendantsWithFloatsForLayout(); + if (child->isRenderBlock()) { + if (markDescendantsWithFloats) + toRenderBlock(child)->markAllDescendantsWithFloatsForLayout(); - previousFloatBottom = max(previousFloatBottom, oldRect.y() + toRenderBlock(child)->floatBottom()); - } + previousFloatBottom = max(previousFloatBottom, oldRect.y() + toRenderBlock(child)->floatBottom()); + } - bool childHadLayout = child->m_everHadLayout; - bool childNeededLayout = child->needsLayout(); - if (childNeededLayout) - child->layout(); + bool childHadLayout = child->m_everHadLayout; + bool childNeededLayout = child->needsLayout(); + if (childNeededLayout) + child->layout(); - // Now determine the correct ypos based off examination of collapsing margin - // values. - int yBeforeClear = collapseMargins(child, marginInfo); + // Now determine the correct ypos based off examination of collapsing margin + // values. + int yBeforeClear = collapseMargins(child, marginInfo); - // Now check for clear. - int yAfterClear = clearFloatsIfNeeded(child, marginInfo, oldTopPosMargin, oldTopNegMargin, yBeforeClear); - - view()->addLayoutDelta(IntSize(0, yPosEstimate - yAfterClear)); - child->setLocation(child->x(), yAfterClear); + // Now check for clear. + int yAfterClear = clearFloatsIfNeeded(child, marginInfo, oldTopPosMargin, oldTopNegMargin, yBeforeClear); - // Now we have a final y position. See if it really does end up being different from our estimate. - if (yAfterClear != yPosEstimate) { - if (child->shrinkToAvoidFloats()) { - // The child's width depends on the line width. - // When the child shifts to clear an item, its width can - // change (because it has more available line width). - // So go ahead and mark the item as dirty. - child->setChildNeedsLayout(true, false); - } - if (!child->avoidsFloats() && child->isBlockFlow() && toRenderBlock(child)->containsFloats()) - toRenderBlock(child)->markAllDescendantsWithFloatsForLayout(); - // Our guess was wrong. Make the child lay itself out again. - child->layoutIfNeeded(); + view()->addLayoutDelta(IntSize(0, yPosEstimate - yAfterClear)); + child->setLocation(child->x(), yAfterClear); + + // Now we have a final y position. See if it really does end up being different from our estimate. + if (yAfterClear != yPosEstimate) { + if (child->shrinkToAvoidFloats()) { + // The child's width depends on the line width. + // When the child shifts to clear an item, its width can + // change (because it has more available line width). + // So go ahead and mark the item as dirty. + child->setChildNeedsLayout(true, false); } + if (!child->avoidsFloats() && child->isBlockFlow() && toRenderBlock(child)->containsFloats()) + toRenderBlock(child)->markAllDescendantsWithFloatsForLayout(); + // Our guess was wrong. Make the child lay itself out again. + child->layoutIfNeeded(); + } - // We are no longer at the top of the block if we encounter a non-empty child. - // This has to be done after checking for clear, so that margins can be reset if a clear occurred. - if (marginInfo.atTopOfBlock() && !child->isSelfCollapsingBlock()) - marginInfo.setAtTopOfBlock(false); - - // Now place the child in the correct horizontal position - determineHorizontalPosition(child); + // We are no longer at the top of the block if we encounter a non-empty child. + // This has to be done after checking for clear, so that margins can be reset if a clear occurred. + if (marginInfo.atTopOfBlock() && !child->isSelfCollapsingBlock()) + marginInfo.setAtTopOfBlock(false); - // Update our height now that the child has been placed in the correct position. - setHeight(height() + child->height()); - if (child->style()->marginBottomCollapse() == MSEPARATE) { - setHeight(height() + child->marginBottom()); - marginInfo.clearMargin(); - } - // If the child has overhanging floats that intrude into following siblings (or possibly out - // of this block), then the parent gets notified of the floats now. - if (child->isBlockFlow() && toRenderBlock(child)->containsFloats()) - maxFloatBottom = max(maxFloatBottom, addOverhangingFloats(toRenderBlock(child), -child->x(), -child->y(), !childNeededLayout)); - - // Update our visual overflow in case the child spills out the block, but only if we were going to paint - // the child block ourselves. - if (!child->hasSelfPaintingLayer()) { - m_overflowTop = min(m_overflowTop, child->y() + child->overflowTop(false)); - m_overflowHeight = max(m_overflowHeight, height() + child->overflowHeight(false) - child->height()); - m_overflowWidth = max(child->x() + child->overflowWidth(false), m_overflowWidth); - m_overflowLeft = min(child->x() + child->overflowLeft(false), m_overflowLeft); - } + // Now place the child in the correct horizontal position + determineHorizontalPosition(child); - IntSize childOffset(child->x() - oldRect.x(), child->y() - oldRect.y()); - if (childOffset.width() || childOffset.height()) { - view()->addLayoutDelta(childOffset); + // Update our height now that the child has been placed in the correct position. + setHeight(height() + child->height()); + if (child->style()->marginBottomCollapse() == MSEPARATE) { + setHeight(height() + child->marginBottom()); + marginInfo.clearMargin(); + } + // If the child has overhanging floats that intrude into following siblings (or possibly out + // of this block), then the parent gets notified of the floats now. + if (child->isBlockFlow() && toRenderBlock(child)->containsFloats()) + maxFloatBottom = max(maxFloatBottom, addOverhangingFloats(toRenderBlock(child), -child->x(), -child->y(), !childNeededLayout)); - // If the child moved, we have to repaint it as well as any floating/positioned - // descendants. An exception is if we need a layout. In this case, we know we're going to - // repaint ourselves (and the child) anyway. - if (childHadLayout && !selfNeedsLayout() && child->checkForRepaintDuringLayout()) - child->repaintDuringLayoutIfMoved(oldRect); - } + IntSize childOffset(child->x() - oldRect.x(), child->y() - oldRect.y()); + if (childOffset.width() || childOffset.height()) { + view()->addLayoutDelta(childOffset); - if (!childHadLayout && child->checkForRepaintDuringLayout()) { - child->repaint(); - child->repaintOverhangingFloats(true); - } + // If the child moved, we have to repaint it as well as any floating/positioned + // descendants. An exception is if we need a layout. In this case, we know we're going to + // repaint ourselves (and the child) anyway. + if (childHadLayout && !selfNeedsLayout() && child->checkForRepaintDuringLayout()) + child->repaintDuringLayoutIfMoved(oldRect); + } - ASSERT(oldLayoutDelta == view()->layoutDelta()); + if (!childHadLayout && child->checkForRepaintDuringLayout()) { + child->repaint(); + child->repaintOverhangingFloats(true); } - // Now do the handling of the bottom of the block, adding in our bottom border/padding and - // determining the correct collapsed bottom margin information. - handleBottomOfBlock(top, bottom, marginInfo); + ASSERT(oldLayoutDelta == view()->layoutDelta()); } bool RenderBlock::layoutOnlyPositionedObjects() @@ -1623,7 +1517,7 @@ void RenderBlock::paint(PaintInfo& paintInfo, int tx, int ty) // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView // paints the root's background. if (!isRoot()) { - IntRect overflowBox = overflowRect(false); + IntRect overflowBox = visibleOverflowRect(); overflowBox.inflate(maximalOutlineSize(paintInfo.phase)); overflowBox.move(tx, ty); if (!overflowBox.intersects(paintInfo.rect)) @@ -2160,9 +2054,9 @@ GapRects RenderBlock::fillInlineSelectionGaps(RenderBlock* rootBlock, int blockX if (lastSelectedLine && selectionState() != SelectionEnd && selectionState() != SelectionBoth) { // Go ahead and update our lastY to be the bottom of the last selected line. - lastTop = (ty - blockY) + lastSelectedLine->bottomOverflow(); - lastLeft = leftSelectionOffset(rootBlock, lastSelectedLine->bottomOverflow()); - lastRight = rightSelectionOffset(rootBlock, lastSelectedLine->bottomOverflow()); + lastTop = (ty - blockY) + lastSelectedLine->selectionBottom(); + lastLeft = leftSelectionOffset(rootBlock, lastSelectedLine->selectionBottom()); + lastRight = rightSelectionOffset(rootBlock, lastSelectedLine->selectionBottom()); } return result; } @@ -2713,13 +2607,13 @@ RenderBlock::floatBottom() const IntRect RenderBlock::floatRect() const { IntRect result; - if (!m_floatingObjects || hasOverflowClip()) + if (!m_floatingObjects || hasOverflowClip() || hasColumns()) return result; FloatingObject* r; DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); for (; (r = it.current()); ++it) { if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) { - IntRect childRect = r->m_renderer->overflowRect(false); + IntRect childRect = r->m_renderer->visibleOverflowRect(); childRect.move(r->m_left + r->m_renderer->marginLeft(), r->m_top + r->m_renderer->marginTop()); result.unite(childRect); } @@ -2730,10 +2624,11 @@ IntRect RenderBlock::floatRect() const int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf) const { + int bottom = includeSelf && width() > 0 ? height() : 0; + if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip())) - return includeSelf && width() > 0 ? overflowHeight(false) : 0; + return bottom; - int bottom = includeSelf && width() > 0 ? height() : 0; if (!hasColumns()) { // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids. // For now, we have to descend into all the children, since we may have a huge abs div inside @@ -2757,7 +2652,7 @@ int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf) int relativeOffset = includeSelf && isRelPositioned() ? relativePositionOffsetY() : 0; if (includeSelf) - bottom = max(bottom, m_overflowHeight + relativeOffset); + bottom = max(bottom, bottomLayoutOverflow() + relativeOffset); if (m_positionedObjects) { RenderBox* r; @@ -2799,8 +2694,8 @@ int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf) if (!includeSelf) { bottom = max(bottom, borderTop() + paddingTop() + paddingBottom() + relativeOffset); if (childrenInline()) { - if (lastLineBox()) { - int childBottomEdge = lastLineBox()->y() + lastLineBox()->height(); + if (lastRootBox()) { + int childBottomEdge = lastRootBox()->selectionBottom(); bottom = max(bottom, childBottomEdge + paddingBottom() + relativeOffset); } } else { @@ -2820,11 +2715,11 @@ int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf) int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const { - if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip())) - return includeSelf && height() > 0 ? overflowWidth(false) : 0; - int right = includeSelf && height() > 0 ? width() : 0; + if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip())) + return right; + if (!hasColumns()) { // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids. // For now, we have to descend into all the children, since we may have a huge abs div inside @@ -2847,7 +2742,7 @@ int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSel int relativeOffset = includeSelf && isRelPositioned() ? relativePositionOffsetX() : 0; if (includeSelf) - right = max(right, m_overflowWidth + relativeOffset); + right = max(right, rightLayoutOverflow() + relativeOffset); if (m_positionedObjects) { RenderBox* r; @@ -2914,10 +2809,11 @@ int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSel int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const { + int left = includeSelf && height() > 0 ? 0 : width(); + if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip())) - return includeSelf && height() > 0 ? overflowLeft(false) : width(); + return left; - int left = includeSelf && height() > 0 ? 0 : width(); if (!hasColumns()) { // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids. // For now, we have to descend into all the children, since we may have a huge abs div inside @@ -2940,7 +2836,7 @@ int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf int relativeOffset = includeSelf && isRelPositioned() ? relativePositionOffsetX() : 0; if (includeSelf) - left = min(left, m_overflowLeft + relativeOffset); + left = min(left, leftLayoutOverflow() + relativeOffset); if (m_positionedObjects) { RenderBox* r; @@ -3134,9 +3030,8 @@ int RenderBlock::addOverhangingFloats(RenderBlock* child, int xoff, int yoff, bo int lowestFloatBottom = 0; - // Floats that will remain the child's responsiblity to paint should factor into its - // visual overflow. - IntRect floatsOverflowRect; + // Floats that will remain the child's responsibility to paint should factor into its + // overflow. DeprecatedPtrListIterator<FloatingObject> it(*child->m_floatingObjects); for (FloatingObject* r; (r = it.current()); ++it) { int bottom = child->y() + r->m_bottom; @@ -3177,13 +3072,9 @@ int RenderBlock::addOverhangingFloats(RenderBlock* child, int xoff, int yoff, bo // it should paint. r->m_shouldPaint = true; - if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) { - IntRect floatOverflowRect = r->m_renderer->overflowRect(false); - floatOverflowRect.move(r->m_left + r->m_renderer->marginLeft(), r->m_top + r->m_renderer->marginTop()); - floatsOverflowRect.unite(floatOverflowRect); - } + if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) + child->addOverflowFromChild(r->m_renderer, IntSize(r->m_left + r->m_renderer->marginLeft(), r->m_top + r->m_renderer->marginTop())); } - child->addVisualOverflow(floatsOverflowRect); return lowestFloatBottom; } @@ -3298,26 +3189,20 @@ int RenderBlock::getClearDelta(RenderBox* child, int yPos) // We also clear floats if we are too big to sit on the same line as a float (and wish to avoid floats by default). // FIXME: Note that the remaining space checks aren't quite accurate, since you should be able to clear only some floats (the minimum # needed // to fit) and not all (we should be using nextFloatBottomBelow and looping). - // Do not allow tables to wrap in quirks or even in almost strict mode - // (ebay on the PLT, finance.yahoo.com in the real world, versiontracker.com forces even almost strict mode not to work) int result = clearSet ? max(0, bottom - yPos) : 0; - if (!result && child->avoidsFloats() && child->style()->width().isFixed() && - child->minPrefWidth() > lineWidth(yPos, false) && child->minPrefWidth() <= availableWidth() && - document()->inStrictMode()) - result = max(0, floatBottom() - yPos); + if (!result && child->avoidsFloats()) { + int oldYPos = child->y(); + int oldWidth = child->width(); + child->setY(yPos); + child->calcWidth(); + if (child->width() > lineWidth(yPos, false) && child->minPrefWidth() <= availableWidth()) + result = max(0, floatBottom() - yPos); + child->setY(oldYPos); + child->setWidth(oldWidth); + } return result; } -void RenderBlock::addVisualOverflow(const IntRect& r) -{ - if (r.isEmpty()) - return; - m_overflowLeft = min(m_overflowLeft, r.x()); - m_overflowWidth = max(m_overflowWidth, r.right()); - m_overflowTop = min(m_overflowTop, r.y()); - m_overflowHeight = max(m_overflowHeight, r.bottom()); -} - bool RenderBlock::isPointInOverflowControl(HitTestResult& result, int _x, int _y, int _tx, int _ty) { if (!scrollsOverflow()) @@ -3333,7 +3218,7 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu if (!isRenderView()) { // Check if we need to do anything at all. - IntRect overflowBox = overflowRect(false); + IntRect overflowBox = visibleOverflowRect(); overflowBox.move(tx, ty); if (!overflowBox.contains(_x, _y)) return false; @@ -3542,9 +3427,9 @@ VisiblePosition RenderBlock::positionForPointWithInlineChildren(const IntPoint& if (root->nextRootBox()) { // FIXME: We would prefer to make the break point halfway between the bottom // of the previous root box and the top of the next root box. - bottom = root->nextRootBox()->topOverflow(); + bottom = root->nextRootBox()->lineTop(); } else - bottom = root->bottomOverflow() + verticalLineClickFudgeFactor; + bottom = root->lineBottom() + verticalLineClickFudgeFactor; // check if this root line box is located at this y coordinate if (pointInContents.y() < bottom) { @@ -3563,7 +3448,7 @@ VisiblePosition RenderBlock::positionForPointWithInlineChildren(const IntPoint& } if (closestBox) { - if (!useWindowsBehavior && pointInContents.y() < firstRootBoxWithChildren->topOverflow() - verticalLineClickFudgeFactor) { + if (!useWindowsBehavior && pointInContents.y() < firstRootBoxWithChildren->lineTop() - verticalLineClickFudgeFactor) { // y coordinate is above first root line box, so return the start of the first return VisiblePosition(positionForBox(firstRootBoxWithChildren->firstLeafChild(), true), DOWNSTREAM); } @@ -3699,7 +3584,7 @@ void RenderBlock::calcColumnWidth() void RenderBlock::setDesiredColumnCountAndWidth(int count, int width) { - if (count == 1) { + if (count == 1 && style()->hasAutoColumnWidth()) { if (hasColumns()) { delete gColumnInfoMap->take(this); setHasColumns(false); @@ -3836,14 +3721,16 @@ int RenderBlock::layoutColumns(int endOfContent) colCount++; } - m_overflowWidth = max(width(), currX - colGap); - m_overflowLeft = min(0, currX + desiredColumnWidth + colGap); - - m_overflowHeight = maxColBottom; + int overflowRight = max(width(), currX - colGap); + int overflowLeft = min(0, currX + desiredColumnWidth + colGap); + int overflowHeight = maxColBottom; int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight(); if (computeIntrinsicHeight) - setHeight(m_overflowHeight + toAdd); + setHeight(maxColBottom + toAdd); + + m_overflow.clear(); + addLayoutOverflow(IntRect(overflowLeft, 0, overflowRight - overflowLeft, overflowHeight)); v->setPrintRect(IntRect()); v->setTruncatedAt(0); @@ -4767,7 +4654,7 @@ static int getHeightForLineCount(RenderBlock* block, int l, bool includeBottom, if (block->childrenInline()) { for (RootInlineBox* box = block->firstRootBox(); box; box = box->nextRootBox()) { if (++count == l) - return box->bottomOverflow() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : 0); + return box->lineBottom() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : 0); } } else { @@ -5098,8 +4985,11 @@ void RenderBlock::addFocusRingRects(GraphicsContext* graphicsContext, int tx, in graphicsContext->addFocusRingRect(IntRect(tx, ty, width(), height())); if (!hasOverflowClip() && !hasControlClip()) { - for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) - graphicsContext->addFocusRingRect(IntRect(tx + curr->x(), ty + curr->y(), curr->width(), curr->height())); + for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) { + int top = max(curr->lineTop(), curr->y()); + int bottom = min(curr->lineBottom(), curr->y() + curr->height()); + graphicsContext->addFocusRingRect(IntRect(tx + curr->x(), ty + top, curr->width(), bottom - top)); + } for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) { if (!curr->isText() && !curr->isListMarker() && curr->isBox()) { @@ -5121,13 +5011,20 @@ void RenderBlock::addFocusRingRects(GraphicsContext* graphicsContext, int tx, in ty - y() + inlineContinuation()->containingBlock()->y()); } -RenderBlock* RenderBlock::createAnonymousBlock() const +RenderBlock* RenderBlock::createAnonymousBlock(bool isFlexibleBox) const { RefPtr<RenderStyle> newStyle = RenderStyle::create(); newStyle->inheritFrom(style()); - newStyle->setDisplay(BLOCK); - RenderBlock* newBox = new (renderArena()) RenderBlock(document() /* anonymous box */); + RenderBlock* newBox = 0; + if (isFlexibleBox) { + newStyle->setDisplay(BOX); + newBox = new (renderArena()) RenderFlexibleBox(document() /* anonymous box */); + } else { + newStyle->setDisplay(BLOCK); + newBox = new (renderArena()) RenderBlock(document() /* anonymous box */); + } + newBox->setStyle(newStyle.release()); return newBox; } diff --git a/WebCore/rendering/RenderBlock.h b/WebCore/rendering/RenderBlock.h index 839be16..e23ebda 100644 --- a/WebCore/rendering/RenderBlock.h +++ b/WebCore/rendering/RenderBlock.h @@ -67,17 +67,6 @@ public: void deleteLineBoxTree(); - // The height (and width) of a block when you include overflow spillage out of the bottom - // of the block (e.g., a <div style="height:25px"> that has a 100px tall image inside - // it would have an overflow height of borderTop() + paddingTop() + 100px. - virtual int overflowHeight(bool includeInterior = true) const; - virtual int overflowWidth(bool includeInterior = true) const; - virtual int overflowLeft(bool includeInterior = true) const; - virtual int overflowTop(bool includeInterior = true) const; - virtual IntRect overflowRect(bool includeInterior = true) const; - - void addVisualOverflow(const IntRect&); - virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0); virtual void removeChild(RenderObject*); @@ -104,6 +93,7 @@ public: IntRect floatRect() const; int lineWidth(int y, bool firstLine) const; + virtual int lowestPosition(bool includeOverflowInterior = true, bool includeSelf = true) const; virtual int rightmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const; virtual int leftmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const; @@ -147,15 +137,12 @@ public: // This function is a convenience helper for creating an anonymous block that inherits its // style from this RenderBlock. - RenderBlock* createAnonymousBlock() const; + RenderBlock* createAnonymousBlock(bool isFlexibleBox = false) const; Vector<IntRect>* columnRects() const; int columnGap() const; protected: - virtual void setOverflowHeight(int h) { m_overflowHeight = h; } - virtual void setOverflowWidth(int w) { m_overflowWidth = w; } - int maxTopPosMargin() const { return m_maxMargin ? m_maxMargin->m_topPos : MaxMargin::topPosDefault(this); } int maxTopNegMargin() const { return m_maxMargin ? m_maxMargin->m_topNeg : MaxMargin::topNegDefault(this); } int maxBottomPosMargin() const { return m_maxMargin ? m_maxMargin->m_bottomPos : MaxMargin::bottomPosDefault(this); } @@ -207,7 +194,7 @@ protected: virtual bool hasLineIfEmpty() const; bool layoutOnlyPositionedObjects(); - + private: virtual RenderObjectChildList* virtualChildren() { return children(); } virtual const RenderObjectChildList* virtualChildren() const { return children(); } @@ -275,11 +262,14 @@ private: InlineFlowBox* createLineBoxes(RenderObject*, bool firstLine); void computeHorizontalPositionsForLine(RootInlineBox*, bool firstLine, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd); void computeVerticalPositionsForLine(RootInlineBox*, BidiRun*); - void checkLinesForOverflow(); void deleteEllipsisLineBoxes(); void checkLinesForTextOverflow(); + void addOverflowFromInlineChildren(); // End of functions defined in RenderBlockLineLayout.cpp. + void addOverflowFromBlockChildren(); + void addOverflowFromFloats(); + void paintFloats(PaintInfo&, int tx, int ty, bool preservePhase = false); void paintContents(PaintInfo&, int tx, int ty); void paintColumnContents(PaintInfo&, int tx, int ty, bool paintFloats = false); @@ -432,10 +422,6 @@ private: // This flag is set when we know we're examining bottom margins and we know we're at the bottom of the block. bool m_atBottomOfBlock : 1; - // If our last normal flow child was a self-collapsing block that cleared a float, - // we track it in this variable. - bool m_selfCollapsingBlockClearedFloat : 1; - // These variables are used to detect quirky margins that we need to collapse away (in table cells // and in the body element). bool m_topQuirk : 1; @@ -452,7 +438,6 @@ private: void setAtTopOfBlock(bool b) { m_atTopOfBlock = b; } void setAtBottomOfBlock(bool b) { m_atBottomOfBlock = b; } void clearMargin() { m_posMargin = m_negMargin = 0; } - void setSelfCollapsingBlockClearedFloat(bool b) { m_selfCollapsingBlockClearedFloat = b; } void setTopQuirk(bool b) { m_topQuirk = b; } void setBottomQuirk(bool b) { m_bottomQuirk = b; } void setDeterminedTopQuirk(bool b) { m_determinedTopQuirk = b; } @@ -468,7 +453,6 @@ private: bool canCollapseWithBottom() const { return m_atBottomOfBlock && m_canCollapseBottomWithChildren; } bool canCollapseTopWithChildren() const { return m_canCollapseTopWithChildren; } bool canCollapseBottomWithChildren() const { return m_canCollapseBottomWithChildren; } - bool selfCollapsingBlockClearedFloat() const { return m_selfCollapsingBlockClearedFloat; } bool quirkContainer() const { return m_quirkContainer; } bool determinedTopQuirk() const { return m_determinedTopQuirk; } bool topQuirk() const { return m_topQuirk; } @@ -478,6 +462,7 @@ private: int margin() const { return m_posMargin - m_negMargin; } }; + void layoutBlockChild(RenderBox* child, MarginInfo&, int& previousFloatBottom, int& maxFloatBottom); void adjustPositionedBlock(RenderBox* child, const MarginInfo&); void adjustFloatingBlock(const MarginInfo&); bool handleSpecialChild(RenderBox* child, const MarginInfo&); @@ -528,14 +513,6 @@ private: RenderObjectChildList m_children; RenderLineBoxList m_lineBoxes; // All of the root line boxes created for this block flow. For example, <div>Hello<br>world.</div> will have two total lines for the <div>. -protected: - // How much content overflows out of our block vertically or horizontally. - int m_overflowHeight; - int m_overflowWidth; - int m_overflowLeft; - int m_overflowTop; - -private: mutable int m_lineHeight; }; diff --git a/WebCore/rendering/RenderBlockLineLayout.cpp b/WebCore/rendering/RenderBlockLineLayout.cpp index 3950372..538225d 100644 --- a/WebCore/rendering/RenderBlockLineLayout.cpp +++ b/WebCore/rendering/RenderBlockLineLayout.cpp @@ -770,11 +770,8 @@ void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, bool // The widths of all runs are now known. We can now place every inline box (and // compute accurate widths for the inline flow boxes). - int leftPosition = x; - int rightPosition = x; needsWordSpacing = false; - lineBox->placeBoxesHorizontally(x, leftPosition, rightPosition, needsWordSpacing); - lineBox->setHorizontalOverflowPositions(leftPosition, rightPosition); + lineBox->placeBoxesHorizontally(x, needsWordSpacing); } void RenderBlock::computeVerticalPositionsForLine(RootInlineBox* lineBox, BidiRun* firstRun) @@ -782,11 +779,6 @@ void RenderBlock::computeVerticalPositionsForLine(RootInlineBox* lineBox, BidiRu setHeight(lineBox->verticallyAlignBoxes(height())); lineBox->setBlockHeight(height()); - // See if the line spilled out. If so set overflow height accordingly. - int bottomOfLine = lineBox->bottomOverflow(); - if (bottomOfLine > height() && bottomOfLine > m_overflowHeight) - m_overflowHeight = bottomOfLine; - // Now make sure we place replaced render objects correctly. for (BidiRun* r = firstRun; r; r = r->next()) { ASSERT(r->m_box); @@ -831,7 +823,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i { bool useRepaintBounds = false; - m_overflowHeight = 0; + m_overflow.clear(); setHeight(borderTop() + paddingTop()); int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight(); @@ -1022,8 +1014,8 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i RenderArena* arena = renderArena(); RootInlineBox* box = startLine; while (box) { - repaintTop = min(repaintTop, box->topOverflow()); - repaintBottom = max(repaintBottom, box->bottomOverflow()); + repaintTop = min(repaintTop, box->topVisibleOverflow()); + repaintBottom = max(repaintBottom, box->bottomVisibleOverflow()); RootInlineBox* next = box->nextRootBox(); box->deleteLine(arena); box = next; @@ -1159,8 +1151,8 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i if (lineBox) { lineBox->setLineBreakInfo(end.obj, end.pos, resolver.status()); if (useRepaintBounds) { - repaintTop = min(repaintTop, lineBox->topOverflow()); - repaintBottom = max(repaintBottom, lineBox->bottomOverflow()); + repaintTop = min(repaintTop, lineBox->topVisibleOverflow()); + repaintBottom = max(repaintBottom, lineBox->bottomVisibleOverflow()); } } @@ -1199,8 +1191,8 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i for (RootInlineBox* line = endLine; line; line = line->nextRootBox()) { line->attachLine(); if (delta) { - repaintTop = min(repaintTop, line->topOverflow() + min(delta, 0)); - repaintBottom = max(repaintBottom, line->bottomOverflow() + max(delta, 0)); + repaintTop = min(repaintTop, line->topVisibleOverflow() + min(delta, 0)); + repaintBottom = max(repaintBottom, line->bottomVisibleOverflow() + max(delta, 0)); line->adjustPosition(0, delta); } if (Vector<RenderBox*>* cleanLineFloats = line->floatsPtr()) { @@ -1216,12 +1208,12 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i setHeight(lastRootBox()->blockHeight()); } else { // Delete all the remaining lines. - InlineRunBox* line = endLine; + RootInlineBox* line = endLine; RenderArena* arena = renderArena(); while (line) { - repaintTop = min(repaintTop, line->topOverflow()); - repaintBottom = max(repaintBottom, line->bottomOverflow()); - InlineRunBox* next = line->nextLineBox(); + repaintTop = min(repaintTop, line->topVisibleOverflow()); + repaintBottom = max(repaintBottom, line->bottomVisibleOverflow()); + RootInlineBox* next = line->nextRootBox(); line->deleteLine(arena); line = next; } @@ -1259,12 +1251,6 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i // Now add in the bottom border/padding. setHeight(height() + toAdd); - // Always make sure this is at least our height. - m_overflowHeight = max(height(), m_overflowHeight); - - // See if any lines spill out of the block. If so, we need to update our overflow width. - checkLinesForOverflow(); - if (!firstLineBox() && hasLineIfEmpty()) setHeight(height() + lineHeight(true, true)); @@ -1491,8 +1477,8 @@ bool RenderBlock::matchedEndLine(const InlineBidiResolver& resolver, const Inlin RootInlineBox* boxToDelete = endLine; RenderArena* arena = renderArena(); while (boxToDelete && boxToDelete != result) { - repaintTop = min(repaintTop, boxToDelete->topOverflow()); - repaintBottom = max(repaintBottom, boxToDelete->bottomOverflow()); + repaintTop = min(repaintTop, boxToDelete->topVisibleOverflow()); + repaintBottom = max(repaintBottom, boxToDelete->bottomVisibleOverflow()); RootInlineBox* next = boxToDelete->nextRootBox(); boxToDelete->deleteLine(arena); boxToDelete = next; @@ -2312,14 +2298,12 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool return lBreak; } -void RenderBlock::checkLinesForOverflow() +void RenderBlock::addOverflowFromInlineChildren() { - m_overflowWidth = width(); for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) { - m_overflowLeft = min(curr->leftOverflow(), m_overflowLeft); - m_overflowTop = min(curr->topOverflow(), m_overflowTop); - m_overflowWidth = max(curr->rightOverflow(), m_overflowWidth); - m_overflowHeight = max(curr->bottomOverflow(), m_overflowHeight); + addLayoutOverflow(curr->layoutOverflowRect()); + if (!hasOverflowClip()) + addVisualOverflow(curr->visualOverflowRect()); } } diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp index 4c2bff0..efd88a7 100644 --- a/WebCore/rendering/RenderBox.cpp +++ b/WebCore/rendering/RenderBox.cpp @@ -406,16 +406,28 @@ int RenderBox::horizontalScrollbarHeight() const return includeHorizontalScrollbarSize() ? layer()->horizontalScrollbarHeight() : 0; } -bool RenderBox::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier) +bool RenderBox::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier, Node** stopNode) { RenderLayer* l = layer(); - if (l && l->scroll(direction, granularity, multiplier)) + if (l && l->scroll(direction, granularity, multiplier)) { + if (stopNode) + *stopNode = node(); return true; + } + + if (stopNode && *stopNode && *stopNode == node()) + return true; + RenderBlock* b = containingBlock(); if (b && !b->isRenderView()) - return b->scroll(direction, granularity, multiplier); + return b->scroll(direction, granularity, multiplier, stopNode); return false; } + +bool RenderBox::canBeScrolledAndHasScrollableArea() const +{ + return canBeProgramaticallyScrolled(false) && (scrollHeight() != clientHeight() || scrollWidth() != clientWidth()); +} bool RenderBox::canBeProgramaticallyScrolled(bool) const { @@ -653,31 +665,36 @@ void RenderBox::paintMaskImages(const PaintInfo& paintInfo, int tx, int ty, int { // Figure out if we need to push a transparency layer to render our mask. bool pushTransparencyLayer = false; - StyleImage* maskBoxImage = style()->maskBoxImage().image(); - if (maskBoxImage && style()->maskLayers()->hasImage()) { - pushTransparencyLayer = true; - } else { - // We have to use an extra image buffer to hold the mask. Multiple mask images need - // to composite together using source-over so that they can then combine into a single unified mask that - // can be composited with the content using destination-in. SVG images need to be able to set compositing modes - // as they draw images contained inside their sub-document, so we paint all our images into a separate buffer - // and composite that buffer as the mask. - // We have to check that the mask images to be rendered contain at least one image that can be actually used in rendering - // before pushing the transparency layer. - for (const FillLayer* fillLayer = style()->maskLayers()->next(); fillLayer; fillLayer = fillLayer->next()) { - if (fillLayer->hasImage() && fillLayer->image()->canRender(style()->effectiveZoom())) { - pushTransparencyLayer = true; - // We found one image that can be used in rendering, exit the loop - break; + bool compositedMask = hasLayer() && layer()->hasCompositedMask(); + CompositeOperator compositeOp = CompositeSourceOver; + + if (!compositedMask) { + StyleImage* maskBoxImage = style()->maskBoxImage().image(); + if (maskBoxImage && style()->maskLayers()->hasImage()) { + pushTransparencyLayer = true; + } else { + // We have to use an extra image buffer to hold the mask. Multiple mask images need + // to composite together using source-over so that they can then combine into a single unified mask that + // can be composited with the content using destination-in. SVG images need to be able to set compositing modes + // as they draw images contained inside their sub-document, so we paint all our images into a separate buffer + // and composite that buffer as the mask. + // We have to check that the mask images to be rendered contain at least one image that can be actually used in rendering + // before pushing the transparency layer. + for (const FillLayer* fillLayer = style()->maskLayers()->next(); fillLayer; fillLayer = fillLayer->next()) { + if (fillLayer->hasImage() && fillLayer->image()->canRender(style()->effectiveZoom())) { + pushTransparencyLayer = true; + // We found one image that can be used in rendering, exit the loop + break; + } } } - } - - CompositeOperator compositeOp = CompositeDestinationIn; - if (pushTransparencyLayer) { - paintInfo.context->setCompositeOperation(CompositeDestinationIn); - paintInfo.context->beginTransparencyLayer(1.0f); - compositeOp = CompositeSourceOver; + + compositeOp = CompositeDestinationIn; + if (pushTransparencyLayer) { + paintInfo.context->setCompositeOperation(CompositeDestinationIn); + paintInfo.context->beginTransparencyLayer(1.0f); + compositeOp = CompositeSourceOver; + } } paintFillLayers(paintInfo, Color(), style()->maskLayers(), tx, ty, w, h, compositeOp); @@ -930,7 +947,8 @@ void RenderBox::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool if (style()->position() == FixedPosition) fixed = true; - RenderObject* o = container(); + bool containerSkipped; + RenderObject* o = container(repaintContainer, &containerSkipped); if (!o) return; @@ -948,6 +966,14 @@ void RenderBox::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool } else transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform); + if (containerSkipped) { + // There can't be a transform between repaintContainer and o, because transforms create containers, so it should be safe + // to just subtract the delta between the repaintContainer and o. + IntSize containerOffset = repaintContainer->offsetFromAncestorContainer(o); + transformState.move(-containerOffset.width(), -containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform); + return; + } + o->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState); } @@ -1068,7 +1094,7 @@ IntRect RenderBox::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintCo if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent()) return IntRect(); - IntRect r = overflowRect(false); + IntRect r = visibleOverflowRect(); RenderView* v = view(); if (v) { @@ -1120,7 +1146,8 @@ void RenderBox::computeRectForRepaint(RenderBoxModelObject* repaintContainer, In if (repaintContainer == this) return; - RenderObject* o = container(); + bool containerSkipped; + RenderObject* o = container(repaintContainer, &containerSkipped); if (!o) return; @@ -1177,6 +1204,13 @@ void RenderBox::computeRectForRepaint(RenderBoxModelObject* repaintContainer, In return; } else rect.setLocation(topLeft); + + if (containerSkipped) { + // If the repaintContainer is below o, then we need to map the rect into repaintContainer's coordinates. + IntSize containerOffset = repaintContainer->offsetFromAncestorContainer(o); + rect.move(-containerOffset); + return; + } o->computeRectForRepaint(repaintContainer, rect, fixed); } @@ -1520,7 +1554,7 @@ int RenderBox::calcHeightUsing(const Length& h) int RenderBox::calcPercentageHeight(const Length& height) { int result = -1; - bool includeBorderPadding = isTable(); + bool skippedAutoHeightContainingBlock = false; RenderBlock* cb = containingBlock(); if (style()->htmlHacks()) { // In quirks mode, blocks with auto height are skipped, and we keep looking for an enclosing @@ -1528,6 +1562,7 @@ int RenderBox::calcPercentageHeight(const Length& height) // specification, which states that percentage heights just revert to auto if the containing // block has an auto height. while (!cb->isRenderView() && !cb->isBody() && !cb->isTableCell() && !cb->isPositioned() && cb->style()->height().isAuto()) { + skippedAutoHeightContainingBlock = true; cb = cb->containingBlock(); cb->addPercentHeightDescendant(this); } @@ -1537,25 +1572,29 @@ int RenderBox::calcPercentageHeight(const Length& height) // explicitly specified that can be used for any percentage computations. bool isPositionedWithSpecifiedHeight = cb->isPositioned() && (!cb->style()->height().isAuto() || (!cb->style()->top().isAuto() && !cb->style()->bottom().isAuto())); + bool includeBorderPadding = isTable(); + // Table cells violate what the CSS spec says to do with heights. Basically we // don't care if the cell specified a height or not. We just always make ourselves // be a percentage of the cell's current content height. if (cb->isTableCell()) { - result = cb->overrideSize(); - if (result == -1) { - // Normally we would let the cell size intrinsically, but scrolling overflow has to be - // treated differently, since WinIE lets scrolled overflow regions shrink as needed. - // While we can't get all cases right, we can at least detect when the cell has a specified - // height or when the table has a specified height. In these cases we want to initially have - // no size and allow the flexing of the table or the cell to its specified height to cause us - // to grow to fill the space. This could end up being wrong in some cases, but it is - // preferable to the alternative (sizing intrinsically and making the row end up too big). - RenderTableCell* cell = toRenderTableCell(cb); - if (scrollsOverflowY() && (!cell->style()->height().isAuto() || !cell->table()->style()->height().isAuto())) - return 0; - return -1; + if (!skippedAutoHeightContainingBlock) { + result = cb->overrideSize(); + if (result == -1) { + // Normally we would let the cell size intrinsically, but scrolling overflow has to be + // treated differently, since WinIE lets scrolled overflow regions shrink as needed. + // While we can't get all cases right, we can at least detect when the cell has a specified + // height or when the table has a specified height. In these cases we want to initially have + // no size and allow the flexing of the table or the cell to its specified height to cause us + // to grow to fill the space. This could end up being wrong in some cases, but it is + // preferable to the alternative (sizing intrinsically and making the row end up too big). + RenderTableCell* cell = toRenderTableCell(cb); + if (scrollsOverflowY() && (!cell->style()->height().isAuto() || !cell->table()->style()->height().isAuto())) + return 0; + return -1; + } + includeBorderPadding = true; } - includeBorderPadding = true; } // Otherwise we only use our percentage height if our containing block had a specified // height. @@ -2485,7 +2524,7 @@ void RenderBox::calcAbsoluteHorizontalReplaced() // positioned, inline containing block because right now, it is using the xPos // of the first line box when really it should use the last line box. When // this is fixed elsewhere, this block should be removed. - if (containerBlock->isInline() && containerBlock->style()->direction() == RTL) { + if (containerBlock->isRenderInline() && containerBlock->style()->direction() == RTL) { const RenderInline* flow = toRenderInline(containerBlock); InlineFlowBox* firstLine = flow->firstLineBox(); InlineFlowBox* lastLine = flow->lastLineBox(); @@ -2646,9 +2685,9 @@ IntRect RenderBox::localCaretRect(InlineBox* box, int caretOffset, int* extraWid if (box) { RootInlineBox* rootBox = box->root(); - int top = rootBox->topOverflow(); + int top = rootBox->lineTop(); rect.setY(top); - rect.setHeight(rootBox->bottomOverflow() - top); + rect.setHeight(rootBox->lineBottom() - top); } // If height of box is smaller than font height, use the latter one, @@ -2701,11 +2740,6 @@ int RenderBox::leftmostPosition(bool /*includeOverflowInterior*/, bool includeSe return left; } -bool RenderBox::isAfterContent(RenderObject* child) const -{ - return (child && child->style()->styleType() == AFTER && (!child->isText() || child->isBR())); -} - VisiblePosition RenderBox::positionForPoint(const IntPoint& point) { // no children...return this render object's element, if there is one, and offset 0 @@ -2813,6 +2847,81 @@ bool RenderBox::avoidsFloats() const return isReplaced() || hasOverflowClip() || isHR(); } +void RenderBox::addShadowOverflow() +{ + int shadowLeft; + int shadowRight; + int shadowTop; + int shadowBottom; + style()->getBoxShadowExtent(shadowTop, shadowRight, shadowBottom, shadowLeft); + IntRect borderBox = borderBoxRect(); + int overflowLeft = borderBox.x() + shadowLeft; + int overflowRight = borderBox.right() + shadowRight; + int overflowTop = borderBox.y() + shadowTop; + int overflowBottom = borderBox.bottom() + shadowBottom; + addVisualOverflow(IntRect(overflowLeft, overflowTop, overflowRight - overflowLeft, overflowBottom - overflowTop)); +} + +void RenderBox::addOverflowFromChild(RenderBox* child, const IntSize& delta) +{ + // Update our overflow in case the child spills out the block, but only if we were going to paint + // the child block ourselves. + if (child->hasSelfPaintingLayer()) + return; + + // Only propagate layout overflow from the child if the child isn't clipping its overflow. If it is, then + // its overflow is internal to it, and we don't care about it. + IntRect childLayoutOverflowRect = child->hasOverflowClip() ? child->borderBoxRect() : child->layoutOverflowRect(); + childLayoutOverflowRect.move(delta); + addLayoutOverflow(childLayoutOverflowRect); + + // Add in visual overflow from the child. Even if the child clips its overflow, it may still + // have visual overflow of its own set from box shadows or reflections. It is unnecessary to propagate this + // overflow if we are clipping our own overflow. + if (hasOverflowClip()) + return; + IntRect childVisualOverflowRect = child->visualOverflowRect(); + childVisualOverflowRect.move(delta); + addVisualOverflow(childVisualOverflowRect); +} + +void RenderBox::addLayoutOverflow(const IntRect& rect) +{ + IntRect borderBox = borderBoxRect(); + if (borderBox.contains(rect)) + return; + + if (!m_overflow) + m_overflow.set(new RenderOverflow(borderBox)); + + m_overflow->addLayoutOverflow(rect); +} + +void RenderBox::addVisualOverflow(const IntRect& rect) +{ + IntRect borderBox = borderBoxRect(); + if (borderBox.contains(rect)) + return; + + if (!m_overflow) + m_overflow.set(new RenderOverflow(borderBox)); + + m_overflow->addVisualOverflow(rect); +} + +void RenderBox::clearLayoutOverflow() +{ + if (!m_overflow) + return; + + if (visualOverflowRect() == borderBoxRect()) { + m_overflow.clear(); + return; + } + + m_overflow->resetLayoutOverflow(borderBoxRect()); +} + #if ENABLE(SVG) TransformationMatrix RenderBox::localTransform() const diff --git a/WebCore/rendering/RenderBox.h b/WebCore/rendering/RenderBox.h index cb2297b..897d9b3 100644 --- a/WebCore/rendering/RenderBox.h +++ b/WebCore/rendering/RenderBox.h @@ -24,6 +24,7 @@ #define RenderBox_h #include "RenderBoxModelObject.h" +#include "RenderOverflow.h" #include "ScrollTypes.h" namespace WebCore { @@ -80,16 +81,31 @@ public: RenderBox* nextSiblingBox() const; RenderBox* parentBox() const; - // The height of a block when you include normal flow overflow spillage out of the bottom - // of the block (e.g., a <div style="height:25px"> that has a 100px tall image inside - // it would have an overflow height of borderTop() + paddingTop() + 100px. - virtual int overflowHeight(bool /*includeInterior*/ = true) const { return height(); } - virtual int overflowWidth(bool /*includeInterior*/ = true) const { return width(); } - virtual void setOverflowHeight(int) { } - virtual void setOverflowWidth(int) { } - virtual int overflowLeft(bool /*includeInterior*/ = true) const { return 0; } - virtual int overflowTop(bool /*includeInterior*/ = true) const { return 0; } - virtual IntRect overflowRect(bool /*includeInterior*/ = true) const { return borderBoxRect(); } + IntRect visibleOverflowRect() const { return hasOverflowClip() ? visualOverflowRect() : (m_overflow ? m_overflow->visibleOverflowRect() : borderBoxRect()); } + int topVisibleOverflow() const { return hasOverflowClip() ? topVisualOverflow() : std::min(topLayoutOverflow(), topVisualOverflow()); } + int bottomVisibleOverflow() const { return hasOverflowClip() ? bottomVisualOverflow() : std::max(bottomLayoutOverflow(), bottomVisualOverflow()); } + int leftVisibleOverflow() const { return hasOverflowClip() ? leftVisualOverflow() : std::min(leftLayoutOverflow(), leftVisualOverflow()); } + int rightVisibleOverflow() const { return hasOverflowClip() ? rightVisualOverflow() : std::max(rightLayoutOverflow(), rightVisualOverflow()); } + + IntRect layoutOverflowRect() const { return m_overflow ? m_overflow->layoutOverflowRect() : borderBoxRect(); } + int topLayoutOverflow() const { return m_overflow? m_overflow->topLayoutOverflow() : 0; } + int bottomLayoutOverflow() const { return m_overflow ? m_overflow->bottomLayoutOverflow() : height(); } + int leftLayoutOverflow() const { return m_overflow ? m_overflow->leftLayoutOverflow() : 0; } + int rightLayoutOverflow() const { return m_overflow ? m_overflow->rightLayoutOverflow() : width(); } + + IntRect visualOverflowRect() const { return m_overflow ? m_overflow->visualOverflowRect() : borderBoxRect(); } + int topVisualOverflow() const { return m_overflow? m_overflow->topVisualOverflow() : 0; } + int bottomVisualOverflow() const { return m_overflow ? m_overflow->bottomVisualOverflow() : height(); } + int leftVisualOverflow() const { return m_overflow ? m_overflow->leftVisualOverflow() : 0; } + int rightVisualOverflow() const { return m_overflow ? m_overflow->rightVisualOverflow() : width(); } + + void addLayoutOverflow(const IntRect&); + void addVisualOverflow(const IntRect&); + + void addShadowOverflow(); + void addOverflowFromChild(RenderBox* child) { addOverflowFromChild(child, IntSize(child->x(), child->y())); } + void addOverflowFromChild(RenderBox* child, const IntSize& delta); + void clearLayoutOverflow(); int contentWidth() const { return clientWidth() - paddingLeft() - paddingRight(); } int contentHeight() const { return clientHeight() - paddingTop() - paddingBottom(); } @@ -229,7 +245,8 @@ public: virtual int verticalScrollbarWidth() const; int horizontalScrollbarHeight() const; - virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1.0f); + virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1.0f, Node** stopNode = 0); + bool canBeScrolledAndHasScrollableArea() const; virtual bool canBeProgramaticallyScrolled(bool) const; virtual void autoscroll(); virtual void stopAutoscroll() { } @@ -333,9 +350,6 @@ private: // These include tables, positioned objects, floats and flexible boxes. virtual void calcPrefWidths() { setPrefWidthsDirty(false); } -protected: - bool isAfterContent(RenderObject* child) const; - private: // The width/height of the contents + borders + padding. The x/y location is relative to our container (which is not always our parent). IntRect m_frameRect; @@ -360,6 +374,9 @@ protected: // For inline replaced elements, the inline box that owns us. InlineBox* m_inlineBoxWrapper; + // Our overflow information. + OwnPtr<RenderOverflow> m_overflow; + private: // Used to store state between styleWillChange and styleDidChange static bool s_hadOverflowClip; diff --git a/WebCore/rendering/RenderBoxModelObject.cpp b/WebCore/rendering/RenderBoxModelObject.cpp index 2b05170..23dad2d 100644 --- a/WebCore/rendering/RenderBoxModelObject.cpp +++ b/WebCore/rendering/RenderBoxModelObject.cpp @@ -316,10 +316,14 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co bool clippedToBorderRadius = false; if (style()->hasBorderRadius() && (includeLeftEdge || includeRightEdge)) { + IntRect borderRect(tx, ty, w, h); + + if (borderRect.isEmpty()) + return; + context->save(); IntSize topLeft, topRight, bottomLeft, bottomRight; - IntRect borderRect(tx, ty, w, h); style()->getBorderRadiiForRect(borderRect, topLeft, topRight, bottomLeft, bottomRight); context->addRoundedRectClip(borderRect, includeLeftEdge ? topLeft : IntSize(), @@ -489,153 +493,130 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co context->restore(); } -IntSize RenderBoxModelObject::calculateBackgroundSize(const FillLayer* bgLayer, int scaledWidth, int scaledHeight) const +IntSize RenderBoxModelObject::calculateFillTileSize(const FillLayer* fillLayer, IntSize positioningAreaSize) const { - StyleImage* bg = bgLayer->image(); - bg->setImageContainerSize(IntSize(scaledWidth, scaledHeight)); // Use the box established by background-origin. - - if (bgLayer->isSizeSet()) { - int w = scaledWidth; - int h = scaledHeight; - Length bgWidth = bgLayer->size().width(); - Length bgHeight = bgLayer->size().height(); - - if (bgWidth.isFixed()) - w = bgWidth.value(); - else if (bgWidth.isPercent()) - w = bgWidth.calcValue(scaledWidth); - - if (bgHeight.isFixed()) - h = bgHeight.value(); - else if (bgHeight.isPercent()) - h = bgHeight.calcValue(scaledHeight); - - // If one of the values is auto we have to use the appropriate - // scale to maintain our aspect ratio. - if (bgWidth.isAuto() && !bgHeight.isAuto()) - w = bg->imageSize(this, style()->effectiveZoom()).width() * h / bg->imageSize(this, style()->effectiveZoom()).height(); - else if (!bgWidth.isAuto() && bgHeight.isAuto()) - h = bg->imageSize(this, style()->effectiveZoom()).height() * w / bg->imageSize(this, style()->effectiveZoom()).width(); - else if (bgWidth.isAuto() && bgHeight.isAuto()) { - // If both width and height are auto, we just want to use the image's - // intrinsic size. - w = bg->imageSize(this, style()->effectiveZoom()).width(); - h = bg->imageSize(this, style()->effectiveZoom()).height(); + StyleImage* image = fillLayer->image(); + image->setImageContainerSize(positioningAreaSize); // Use the box established by background-origin. + + EFillSizeType type = fillLayer->size().type; + + switch (type) { + case SizeLength: { + int w = positioningAreaSize.width(); + int h = positioningAreaSize.height(); + Length layerWidth = fillLayer->size().size.width(); + Length layerHeight = fillLayer->size().size.height(); + + if (layerWidth.isFixed()) + w = layerWidth.value(); + else if (layerWidth.isPercent()) + w = layerWidth.calcValue(positioningAreaSize.width()); + + if (layerHeight.isFixed()) + h = layerHeight.value(); + else if (layerHeight.isPercent()) + h = layerHeight.calcValue(positioningAreaSize.height()); + + // If one of the values is auto we have to use the appropriate + // scale to maintain our aspect ratio. + if (layerWidth.isAuto() && !layerHeight.isAuto()) + w = image->imageSize(this, style()->effectiveZoom()).width() * h / image->imageSize(this, style()->effectiveZoom()).height(); + else if (!layerWidth.isAuto() && layerHeight.isAuto()) + h = image->imageSize(this, style()->effectiveZoom()).height() * w / image->imageSize(this, style()->effectiveZoom()).width(); + else if (layerWidth.isAuto() && layerHeight.isAuto()) { + // If both width and height are auto, we just want to use the image's + // intrinsic size. + w = image->imageSize(this, style()->effectiveZoom()).width(); + h = image->imageSize(this, style()->effectiveZoom()).height(); + } + + return IntSize(max(1, w), max(1, h)); } - - return IntSize(max(1, w), max(1, h)); - } else - return bg->imageSize(this, style()->effectiveZoom()); + case Contain: + case Cover: { + IntSize imageIntrinsicSize = image->imageSize(this, 1); + float horizontalScaleFactor = static_cast<float>(positioningAreaSize.width()) / imageIntrinsicSize.width(); + float verticalScaleFactor = static_cast<float>(positioningAreaSize.height()) / imageIntrinsicSize.height(); + float scaleFactor = type == Contain ? min(horizontalScaleFactor, verticalScaleFactor) : max(horizontalScaleFactor, verticalScaleFactor); + + return IntSize(max<int>(1, imageIntrinsicSize.width() * scaleFactor), max<int>(1, imageIntrinsicSize.height() * scaleFactor)); + } + case SizeNone: + break; + } + return image->imageSize(this, style()->effectiveZoom()); } -void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* bgLayer, int tx, int ty, int w, int h, +void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* fillLayer, int tx, int ty, int w, int h, IntRect& destRect, IntPoint& phase, IntSize& tileSize) { - int pw; - int ph; int left = 0; - int right = 0; int top = 0; - int bottom = 0; - int cx; - int cy; - int rw = 0; - int rh = 0; - - // CSS2 chapter 14.2.1 - bool fixedAttachment = bgLayer->attachment() == FixedBackgroundAttachment; + IntSize positioningAreaSize; + + // Determine the background positioning area and set destRect to the background painting area. + // destRect will be adjusted later if the background is non-repeating. + bool fixedAttachment = fillLayer->attachment() == FixedBackgroundAttachment; if (!fixedAttachment) { - // Scroll and Local - if (bgLayer->origin() != BorderFillBox) { + destRect = IntRect(tx, ty, w, h); + + int right = 0; + int bottom = 0; + // Scroll and Local. + if (fillLayer->origin() != BorderFillBox) { left = borderLeft(); right = borderRight(); top = borderTop(); bottom = borderBottom(); - if (bgLayer->origin() == ContentFillBox) { + if (fillLayer->origin() == ContentFillBox) { left += paddingLeft(); right += paddingRight(); top += paddingTop(); bottom += paddingBottom(); } } - + // The background of the box generated by the root element covers the entire canvas including - // its margins. Since those were added in already, we have to factor them out when computing the - // box used by background-origin/size/position. + // its margins. Since those were added in already, we have to factor them out when computing + // the background positioning area. if (isRoot()) { - rw = toRenderBox(this)->width() - left - right; - rh = toRenderBox(this)->height() - top - bottom; + positioningAreaSize = IntSize(toRenderBox(this)->width() - left - right, toRenderBox(this)->height() - top - bottom); left += marginLeft(); - right += marginRight(); top += marginTop(); - bottom += marginBottom(); - } - cx = tx; - cy = ty; - pw = w - left - right; - ph = h - top - bottom; + } else + positioningAreaSize = IntSize(w - left - right, h - top - bottom); } else { - // Fixed background attachment. - IntRect vr = viewRect(); - cx = vr.x(); - cy = vr.y(); - pw = vr.width(); - ph = vr.height(); + destRect = viewRect(); + positioningAreaSize = destRect.size(); } - int sx = 0; - int sy = 0; - int cw; - int ch; + tileSize = calculateFillTileSize(fillLayer, positioningAreaSize); - IntSize scaledImageSize; - if (isRoot() && !fixedAttachment) - scaledImageSize = calculateBackgroundSize(bgLayer, rw, rh); - else - scaledImageSize = calculateBackgroundSize(bgLayer, pw, ph); - - int scaledImageWidth = scaledImageSize.width(); - int scaledImageHeight = scaledImageSize.height(); + EFillRepeat backgroundRepeatX = fillLayer->repeatX(); + EFillRepeat backgroundRepeatY = fillLayer->repeatY(); - EFillRepeat backgroundRepeat = bgLayer->repeat(); - - int xPosition; - if (isRoot() && !fixedAttachment) - xPosition = bgLayer->xPosition().calcMinValue(rw - scaledImageWidth, true); - else - xPosition = bgLayer->xPosition().calcMinValue(pw - scaledImageWidth, true); - if (backgroundRepeat == RepeatFill || backgroundRepeat == RepeatXFill) { - cw = pw + left + right; - sx = scaledImageWidth ? scaledImageWidth - (xPosition + left) % scaledImageWidth : 0; - } else { - cx += max(xPosition + left, 0); - sx = -min(xPosition + left, 0); - cw = scaledImageWidth + min(xPosition + left, 0); - } - - int yPosition; - if (isRoot() && !fixedAttachment) - yPosition = bgLayer->yPosition().calcMinValue(rh - scaledImageHeight, true); - else - yPosition = bgLayer->yPosition().calcMinValue(ph - scaledImageHeight, true); - if (backgroundRepeat == RepeatFill || backgroundRepeat == RepeatYFill) { - ch = ph + top + bottom; - sy = scaledImageHeight ? scaledImageHeight - (yPosition + top) % scaledImageHeight : 0; - } else { - cy += max(yPosition + top, 0); - sy = -min(yPosition + top, 0); - ch = scaledImageHeight + min(yPosition + top, 0); + int xPosition = fillLayer->xPosition().calcMinValue(positioningAreaSize.width() - tileSize.width(), true); + if (backgroundRepeatX == RepeatFill) + phase.setX(tileSize.width() ? tileSize.width() - (xPosition + left) % tileSize.width() : 0); + else { + destRect.move(max(xPosition + left, 0), 0); + phase.setX(-min(xPosition + left, 0)); + destRect.setWidth(tileSize.width() + min(xPosition + left, 0)); } - if (fixedAttachment) { - sx += max(tx - cx, 0); - sy += max(ty - cy, 0); + int yPosition = fillLayer->yPosition().calcMinValue(positioningAreaSize.height() - tileSize.height(), true); + if (backgroundRepeatY == RepeatFill) + phase.setY(tileSize.height() ? tileSize.height() - (yPosition + top) % tileSize.height() : 0); + else { + destRect.move(0, max(yPosition + top, 0)); + phase.setY(-min(yPosition + top, 0)); + destRect.setHeight(tileSize.height() + min(yPosition + top, 0)); } - destRect = IntRect(cx, cy, cw, ch); + if (fixedAttachment) + phase.move(max(tx - destRect.x(), 0), max(ty - destRect.y(), 0)); + destRect.intersect(IntRect(tx, ty, w, h)); - phase = IntPoint(sx, sy); - tileSize = IntSize(scaledImageWidth, scaledImageHeight); } int RenderBoxModelObject::verticalPosition(bool firstLine) const diff --git a/WebCore/rendering/RenderBoxModelObject.h b/WebCore/rendering/RenderBoxModelObject.h index baa5ecb..c9a4a0a 100644 --- a/WebCore/rendering/RenderBoxModelObject.h +++ b/WebCore/rendering/RenderBoxModelObject.h @@ -100,10 +100,12 @@ public: protected: void calculateBackgroundImageGeometry(const FillLayer*, int tx, int ty, int w, int h, IntRect& destRect, IntPoint& phase, IntSize& tileSize); - IntSize calculateBackgroundSize(const FillLayer*, int scaledWidth, int scaledHeight) const; private: virtual bool isBoxModelObject() const { return true; } + + IntSize calculateFillTileSize(const FillLayer*, IntSize scaledSize) const; + friend class RenderView; RenderLayer* m_layer; diff --git a/WebCore/rendering/RenderButton.cpp b/WebCore/rendering/RenderButton.cpp index 6d36a0f..f3ae558 100644 --- a/WebCore/rendering/RenderButton.cpp +++ b/WebCore/rendering/RenderButton.cpp @@ -52,7 +52,8 @@ void RenderButton::addChild(RenderObject* newChild, RenderObject* beforeChild) if (!m_inner) { // Create an anonymous block. ASSERT(!firstChild()); - m_inner = createAnonymousBlock(); + bool isFlexibleBox = style()->display() == BOX || style()->display() == INLINE_BOX; + m_inner = createAnonymousBlock(isFlexibleBox); setupInnerStyle(m_inner->style()); RenderFlexibleBox::addChild(m_inner); } @@ -108,6 +109,7 @@ void RenderButton::setupInnerStyle(RenderStyle* innerStyle) // RenderBlock::createAnonymousBlock creates a new RenderStyle, so this is // safe to modify. innerStyle->setBoxFlex(1.0f); + innerStyle->setBoxOrient(style()->boxOrient()); innerStyle->setPaddingTop(Length(theme()->buttonInternalPaddingTop(), Fixed)); innerStyle->setPaddingRight(Length(theme()->buttonInternalPaddingRight(), Fixed)); diff --git a/WebCore/rendering/RenderCounter.cpp b/WebCore/rendering/RenderCounter.cpp index 67e5cba..17c6dad 100644 --- a/WebCore/rendering/RenderCounter.cpp +++ b/WebCore/rendering/RenderCounter.cpp @@ -143,13 +143,19 @@ static bool findPlaceForCounter(RenderObject* object, const AtomicString& counte RenderObject* resetCandidate = isReset ? object->parent() : previousSiblingOrParent(object); RenderObject* prevCounterCandidate = object; CounterNode* candidateCounter = 0; + // When a reset counter is chosen as candidateCounter, we'll + // decide the new node should be a child of the reset node or a + // sibling or the reset node. This flag controls it. + bool createChildForReset = true; while ((prevCounterCandidate = prevCounterCandidate->previousInPreOrder())) { CounterNode* c = counter(prevCounterCandidate, counterName, false); if (prevCounterCandidate == resetCandidate) { - if (!candidateCounter) + if (!candidateCounter) { candidateCounter = c; + createChildForReset = true; + } if (candidateCounter) { - if (candidateCounter->isReset()) { + if (createChildForReset && candidateCounter->isReset()) { parent = candidateCounter; previousSibling = 0; } else { @@ -160,10 +166,19 @@ static bool findPlaceForCounter(RenderObject* object, const AtomicString& counte } resetCandidate = previousSiblingOrParent(resetCandidate); } else if (c) { - if (c->isReset()) - candidateCounter = 0; - else if (!candidateCounter) + if (c->isReset()) { + if (c->parent()) { + // The new node may be the next sibling of this reset node. + createChildForReset = false; + candidateCounter = c; + } else { + createChildForReset = true; + candidateCounter = 0; + } + } else if (!candidateCounter) { + createChildForReset = true; candidateCounter = c; + } } } diff --git a/WebCore/rendering/RenderFieldset.cpp b/WebCore/rendering/RenderFieldset.cpp index 437991a..8618d11 100644 --- a/WebCore/rendering/RenderFieldset.cpp +++ b/WebCore/rendering/RenderFieldset.cpp @@ -108,10 +108,11 @@ RenderBox* RenderFieldset::findLegend() const { for (RenderObject* legend = firstChild(); legend; legend = legend->nextSibling()) { if (!legend->isFloatingOrPositioned() && legend->node() && - legend->node()->hasTagName(legendTag) + (legend->node()->hasTagName(legendTag) #if ENABLE(WML) || legend->node()->hasTagName(WMLNames::insertedLegendTag) #endif + ) ) return toRenderBox(legend); } diff --git a/WebCore/rendering/RenderFlexibleBox.cpp b/WebCore/rendering/RenderFlexibleBox.cpp index 84c94e4..531477e 100644 --- a/WebCore/rendering/RenderFlexibleBox.cpp +++ b/WebCore/rendering/RenderFlexibleBox.cpp @@ -225,7 +225,8 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren) calcWidth(); calcHeight(); - m_overflowWidth = width(); + + m_overflow.clear(); if (previousWidth != width() || previousHeight != height() || (parent()->isFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL && @@ -241,7 +242,10 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren) #endif setHeight(0); +<<<<<<< HEAD:WebCore/rendering/RenderFlexibleBox.cpp m_overflowHeight = 0; +======= +>>>>>>> webkit.org at 49305:WebCore/rendering/RenderFlexibleBox.cpp m_flexingChildren = m_stretchingChildren = false; initMaxMarginValues(); @@ -259,15 +263,8 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren) else layoutVerticalBox(relayoutChildren); - int oldHeight = height(); calcHeight(); - if (oldHeight != height()) { - // If the block got expanded in size, then increase our overflowheight to match. - if (m_overflowHeight > height()) - m_overflowHeight -= (borderBottom() + paddingBottom() + horizontalScrollbarHeight()); - if (m_overflowHeight < height()) - m_overflowHeight = height(); - } + if (previousHeight != height()) relayoutChildren = true; @@ -290,31 +287,14 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren) setMaxTopMargins(pos, neg); setMaxBottomMargins(0, 0); } + + // Add in the overflow from children. + FlexBoxIterator iterator(this); + for (RenderBox* child = iterator.first(); child; child = iterator.next()) + addOverflowFromChild(child); - // Always ensure our overflow width is at least as large as our width. - if (m_overflowWidth < width()) - m_overflowWidth = width(); - - if (!hasOverflowClip()) { - int shadowLeft; - int shadowRight; - int shadowTop; - int shadowBottom; - style()->getBoxShadowExtent(shadowTop, shadowRight, shadowBottom, shadowLeft); - - m_overflowLeft = min(m_overflowLeft, shadowLeft); - m_overflowWidth = max(m_overflowWidth, width() + shadowRight); - m_overflowTop = min(m_overflowTop, shadowTop); - m_overflowHeight = max(m_overflowHeight, height() + shadowBottom); - - if (hasReflection()) { - IntRect reflection(reflectionBox()); - m_overflowTop = min(m_overflowTop, reflection.y()); - m_overflowHeight = max(m_overflowHeight, reflection.bottom()); - m_overflowLeft = min(m_overflowLeft, reflection.x()); - m_overflowHeight = max(m_overflowWidth, reflection.right()); - } - } + // Add visual overflow from box-shadow and reflections. + addShadowOverflow(); statePusher.pop(); @@ -363,7 +343,7 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren) int oldHeight = 0; int remainingSpace = 0; - m_overflowHeight = height(); + FlexBoxIterator iterator(this); unsigned int highestFlexGroup = 0; @@ -380,7 +360,7 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren) do { // Reset our height. setHeight(yPos); - m_overflowHeight = height(); + xPos = borderLeft() + paddingLeft(); // Our first pass is done without flexing. We simply lay the children @@ -431,10 +411,6 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren) setHeight(height() + lineHeight(true, true)); setHeight(height() + toAdd); - - // Always make sure our overflowheight is at least our height. - if (m_overflowHeight < height()) - m_overflowHeight = height(); oldHeight = height(); calcHeight(); @@ -493,12 +469,6 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren) } placeChild(child, xPos, childY); - - if (child->isRenderBlock()) - toRenderBlock(child)->addVisualOverflow(toRenderBlock(child)->floatRect()); - - m_overflowHeight = max(m_overflowHeight, childY + child->overflowHeight(false)); - m_overflowTop = min(m_overflowTop, child->y() + child->overflowTop(false)); xPos += child->width() + child->marginRight(); @@ -662,22 +632,6 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren) } } - child = iterator.first(); - while (child && child->isPositioned()) { - child = iterator.next(); - } - - if (child) { - m_overflowLeft = min(child->x() + child->overflowLeft(false), m_overflowLeft); - - RenderBox* lastChild = child; - while ((child = iterator.next())) { - if (!child->isPositioned()) - lastChild = child; - } - m_overflowWidth = max(lastChild->x() + lastChild->overflowWidth(false), m_overflowWidth); - } - // So that the calcHeight in layoutBlock() knows to relayout positioned objects because of // a height change, we revert our height back to the intrinsic height before returning. if (heightSpecified) @@ -820,7 +774,6 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren) do { setHeight(borderTop() + paddingTop()); int minHeight = height() + toAdd; - m_overflowHeight = height(); child = iterator.first(); while (child) { @@ -828,8 +781,7 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren) if (!haveLineClamp && (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent())))) child->setChildNeedsLayout(true, false); - if (child->isPositioned()) - { + if (child->isPositioned()) { child->containingBlock()->insertPositionedObject(child); if (child->style()->hasStaticX()) { if (style()->direction() == LTR) @@ -876,14 +828,7 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren) // Place the child. placeChild(child, childX, height()); setHeight(height() + child->height() + child->marginBottom()); - - if (child->isRenderBlock()) - toRenderBlock(child)->addVisualOverflow(toRenderBlock(child)->floatRect()); - // See if this child has made our overflow need to grow. - m_overflowWidth = max(child->x() + child->overflowWidth(false), m_overflowWidth); - m_overflowLeft = min(child->x() + child->overflowLeft(false), m_overflowLeft); - child = iterator.next(); } @@ -899,10 +844,6 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren) if (height() < minHeight) setHeight(minHeight); - // Always make sure our overflowheight is at least our height. - if (m_overflowHeight < height()) - m_overflowHeight = height(); - // Now we have to calc our height, so we know how much space we have remaining. oldHeight = height(); calcHeight(); @@ -1060,22 +1001,6 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren) } } } - - child = iterator.first(); - while (child && child->isPositioned()) { - child = iterator.next(); - } - - if (child) { - m_overflowTop = min(child->y() + child->overflowTop(false), m_overflowTop); - - RenderBox* lastChild = child; - while ((child = iterator.next())) { - if (!child->isPositioned()) - lastChild = child; - } - m_overflowHeight = max(lastChild->y() + lastChild->overflowHeight(false), m_overflowHeight); - } // So that the calcHeight in layoutBlock() knows to relayout positioned objects because of // a height change, we revert our height back to the intrinsic height before returning. @@ -1161,6 +1086,8 @@ const char *RenderFlexibleBox::renderName() const return "RenderFlexibleBox (floating)"; if (isPositioned()) return "RenderFlexibleBox (positioned)"; + if (isAnonymous()) + return "RenderFlexibleBox (generated)"; if (isRelPositioned()) return "RenderFlexibleBox (relative positioned)"; return "RenderFlexibleBox"; diff --git a/WebCore/rendering/RenderForeignObject.h b/WebCore/rendering/RenderForeignObject.h index 8fdb816..e014f22 100644 --- a/WebCore/rendering/RenderForeignObject.h +++ b/WebCore/rendering/RenderForeignObject.h @@ -49,6 +49,7 @@ public: virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction); virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); + virtual bool isSVGForeignObject() const { return true; } private: TransformationMatrix translationForAttributes() const; diff --git a/WebCore/rendering/RenderHTMLCanvas.cpp b/WebCore/rendering/RenderHTMLCanvas.cpp index 1fc07f0..8c17a0e 100644 --- a/WebCore/rendering/RenderHTMLCanvas.cpp +++ b/WebCore/rendering/RenderHTMLCanvas.cpp @@ -43,6 +43,19 @@ RenderHTMLCanvas::RenderHTMLCanvas(HTMLCanvasElement* element) view()->frameView()->setIsVisuallyNonEmpty(); } +bool RenderHTMLCanvas::requiresLayer() const +{ + if (RenderReplaced::requiresLayer()) + return true; + +#if ENABLE(3D_CANVAS) + HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(node()); + return canvas && canvas->is3D(); +#else + return false; +#endif +} + void RenderHTMLCanvas::paintReplaced(PaintInfo& paintInfo, int tx, int ty) { IntRect rect = contentBoxRect(); @@ -55,10 +68,13 @@ void RenderHTMLCanvas::canvasSizeChanged() IntSize canvasSize = static_cast<HTMLCanvasElement*>(node())->size(); IntSize zoomedSize(canvasSize.width() * style()->effectiveZoom(), canvasSize.height() * style()->effectiveZoom()); - if (canvasSize == intrinsicSize()) + if (zoomedSize == intrinsicSize()) return; - setIntrinsicSize(canvasSize); + setIntrinsicSize(zoomedSize); + + if (!parent()) + return; if (!prefWidthsDirty()) setPrefWidthsDirty(true); diff --git a/WebCore/rendering/RenderHTMLCanvas.h b/WebCore/rendering/RenderHTMLCanvas.h index e82cf9a..473dad5 100644 --- a/WebCore/rendering/RenderHTMLCanvas.h +++ b/WebCore/rendering/RenderHTMLCanvas.h @@ -36,6 +36,9 @@ class RenderHTMLCanvas : public RenderReplaced { public: RenderHTMLCanvas(HTMLCanvasElement*); + virtual bool isCanvas() const { return true; } + virtual bool requiresLayer() const; + void canvasSizeChanged(); private: diff --git a/WebCore/rendering/RenderImage.cpp b/WebCore/rendering/RenderImage.cpp index 91200bc..ec2a4d3 100644 --- a/WebCore/rendering/RenderImage.cpp +++ b/WebCore/rendering/RenderImage.cpp @@ -446,7 +446,7 @@ int RenderImage::minimumReplacedHeight() const HTMLMapElement* RenderImage::imageMap() { HTMLImageElement* i = node() && node()->hasTagName(imgTag) ? static_cast<HTMLImageElement*>(node()) : 0; - return i ? i->document()->getImageMap(i->useMap()) : 0; + return i ? i->document()->getImageMap(i->getAttribute(usemapAttr)) : 0; } bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction) diff --git a/WebCore/rendering/RenderInline.cpp b/WebCore/rendering/RenderInline.cpp index 53962d2..05d29d0 100644 --- a/WebCore/rendering/RenderInline.cpp +++ b/WebCore/rendering/RenderInline.cpp @@ -131,18 +131,6 @@ void RenderInline::styleDidChange(StyleDifference diff, const RenderStyle* oldSt } } -static inline bool isAfterContent(RenderObject* child) -{ - if (!child) - return false; - if (child->style()->styleType() != AFTER) - return false; - // Text nodes don't have their own styles, so ignore the style on a text node. - if (child->isText() && !child->isBR()) - return false; - return true; -} - void RenderInline::addChild(RenderObject* newChild, RenderObject* beforeChild) { if (continuation()) @@ -556,6 +544,23 @@ IntRect RenderInline::linesBoundingBox() const return result; } +IntRect RenderInline::linesVisibleOverflowBoundingBox() const +{ + if (!firstLineBox() || !lastLineBox()) + return IntRect(); + + // Return the width of the minimal left side and the maximal right side. + int leftSide = numeric_limits<int>::max(); + int rightSide = numeric_limits<int>::min(); + for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextFlowBox()) { + leftSide = min(leftSide, curr->leftVisibleOverflow()); + rightSide = max(rightSide, curr->rightVisibleOverflow()); + } + + return IntRect(leftSide, firstLineBox()->topVisibleOverflow(), rightSide - leftSide, + lastLineBox()->bottomVisibleOverflow() - firstLineBox()->topVisibleOverflow()); +} + IntRect RenderInline::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) { // Only run-ins are allowed in here during layout. @@ -565,7 +570,7 @@ IntRect RenderInline::clippedOverflowRectForRepaint(RenderBoxModelObject* repain return IntRect(); // Find our leftmost position. - IntRect boundingBox(linesBoundingBox()); + IntRect boundingBox(linesVisibleOverflowBoundingBox()); int left = boundingBox.x(); int top = boundingBox.y(); @@ -647,7 +652,8 @@ void RenderInline::computeRectForRepaint(RenderBoxModelObject* repaintContainer, if (repaintContainer == this) return; - RenderObject* o = container(); + bool containerSkipped; + RenderObject* o = container(repaintContainer, &containerSkipped); if (!o) return; @@ -688,6 +694,13 @@ void RenderInline::computeRectForRepaint(RenderBoxModelObject* repaintContainer, return; } else rect.setLocation(topLeft); + + if (containerSkipped) { + // If the repaintContainer is below o, then we need to map the rect into repaintContainer's coordinates. + IntSize containerOffset = repaintContainer->offsetFromAncestorContainer(o); + rect.move(-containerOffset); + return; + } o->computeRectForRepaint(repaintContainer, rect, fixed); } @@ -830,8 +843,12 @@ void RenderInline::imageChanged(WrappedImagePtr, const IntRect*) void RenderInline::addFocusRingRects(GraphicsContext* graphicsContext, int tx, int ty) { - for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) - graphicsContext->addFocusRingRect(IntRect(tx + curr->x(), ty + curr->y(), curr->width(), curr->height())); + for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { + RootInlineBox* root = curr->root(); + int top = max(root->lineTop(), curr->y()); + int bottom = min(root->lineBottom(), curr->y() + curr->height()); + graphicsContext->addFocusRingRect(IntRect(tx + curr->x(), ty + top, curr->width(), bottom - top)); + } for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) { if (!curr->isText() && !curr->isListMarker()) { @@ -883,9 +900,12 @@ void RenderInline::paintOutline(GraphicsContext* graphicsContext, int tx, int ty Vector<IntRect> rects; rects.append(IntRect()); - for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) - rects.append(IntRect(curr->x(), curr->y(), curr->width(), curr->height())); - + for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { + RootInlineBox* root = curr->root(); + int top = max(root->lineTop(), curr->y()); + int bottom = min(root->lineBottom(), curr->y() + curr->height()); + rects.append(IntRect(curr->x(), top, curr->width(), bottom - top)); + } rects.append(IntRect()); for (unsigned i = 1; i < rects.size() - 1; i++) diff --git a/WebCore/rendering/RenderInline.h b/WebCore/rendering/RenderInline.h index 14d76ca..8e0064e 100644 --- a/WebCore/rendering/RenderInline.h +++ b/WebCore/rendering/RenderInline.h @@ -45,6 +45,7 @@ public: virtual void absoluteQuads(Vector<FloatQuad>&); IntRect linesBoundingBox() const; + IntRect linesVisibleOverflowBoundingBox() const; InlineFlowBox* createAndAppendInlineFlowBox(); diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp index ab78f40..7a8b428 100644 --- a/WebCore/rendering/RenderLayer.cpp +++ b/WebCore/rendering/RenderLayer.cpp @@ -207,12 +207,8 @@ RenderLayer::~RenderLayer() // Make sure we have no lingering clip rects. ASSERT(!m_clipRects); - if (m_reflection) { - if (!m_reflection->documentBeingDestroyed()) - m_reflection->removeLayers(this); - m_reflection->setParent(0); - m_reflection->destroy(); - } + if (m_reflection) + removeReflection(); if (m_scrollCorner) m_scrollCorner->destroy(); @@ -584,10 +580,10 @@ void RenderLayer::updateLayerPosition() setHeight(box->height()); if (!box->hasOverflowClip()) { - if (box->overflowWidth() > box->width()) - setWidth(box->overflowWidth()); - if (box->overflowHeight() > box->height()) - setHeight(box->overflowHeight()); + if (box->rightLayoutOverflow() > box->width()) + setWidth(box->rightLayoutOverflow()); + if (box->bottomLayoutOverflow() > box->height()) + setHeight(box->bottomLayoutOverflow()); } } } @@ -642,37 +638,44 @@ RenderLayer* RenderLayer::stackingContext() const return layer; } +static inline bool isPositionedContainer(RenderLayer* layer) +{ + RenderObject* o = layer->renderer(); + return o->isRenderView() || o->isPositioned() || o->isRelPositioned() || layer->hasTransform(); +} + RenderLayer* RenderLayer::enclosingPositionedAncestor() const { RenderLayer* curr = parent(); - for ( ; curr && !curr->renderer()->isRenderView() && !curr->renderer()->isPositioned() && !curr->renderer()->isRelPositioned() && !curr->hasTransform(); - curr = curr->parent()) { } + while (curr && !isPositionedContainer(curr)) + curr = curr->parent(); + return curr; } RenderLayer* RenderLayer::enclosingTransformedAncestor() const { RenderLayer* curr = parent(); - for ( ; curr && !curr->renderer()->isRenderView() && !curr->transform(); curr = curr->parent()) - { } + while (curr && !curr->renderer()->isRenderView() && !curr->transform()) + curr = curr->parent(); + return curr; } +static inline const RenderLayer* compositingContainer(const RenderLayer* layer) +{ + return layer->isNormalFlowOnly() ? layer->parent() : layer->stackingContext(); +} + #if USE(ACCELERATED_COMPOSITING) RenderLayer* RenderLayer::enclosingCompositingLayer(bool includeSelf) const { if (includeSelf && isComposited()) return const_cast<RenderLayer*>(this); - // Compositing layers are parented according to stacking order and overflow list, - // so we have to check whether the parent is a stacking context, or whether - // the child is overflow-only. - bool inNormalFlowList = isNormalFlowOnly(); - for (RenderLayer* curr = parent(); curr; curr = curr->parent()) { - if (curr->isComposited() && (inNormalFlowList || curr->isStackingContext())) - return curr; - - inNormalFlowList = curr->isNormalFlowOnly(); + for (const RenderLayer* curr = compositingContainer(this); curr; curr = compositingContainer(curr)) { + if (curr->isComposited()) + return const_cast<RenderLayer*>(curr); } return 0; @@ -760,6 +763,19 @@ static IntRect transparencyClipBox(const TransformationMatrix& enclosingTransfor } } + // If we have a reflection, then we need to account for that when we push the clip. Reflect our entire + // current transparencyClipBox to catch all child layers. + // FIXME: Accelerated compositing will eventually want to do something smart here to avoid incorporating this + // size into the parent layer. + if (l->renderer()->hasReflection()) { + int deltaX = 0; + int deltaY = 0; + l->convertToLayerCoords(rootLayer, deltaX, deltaY); + clipRect.move(-deltaX, -deltaY); + clipRect.unite(l->renderBox()->reflectedRect(clipRect)); + clipRect.move(deltaX, deltaY); + } + // Now map the clipRect via the enclosing transform return enclosingTransform.mapRect(clipRect); } @@ -946,12 +962,44 @@ RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& xPos, i } RenderLayer* parentLayer; - if (renderer()->style()->position() == AbsolutePosition) - parentLayer = enclosingPositionedAncestor(); - else + if (renderer()->style()->position() == AbsolutePosition) { + // Do what enclosingPositionedAncestor() does, but check for ancestorLayer along the way + parentLayer = parent(); + bool foundAncestorFirst = false; + while (parentLayer) { + if (isPositionedContainer(parentLayer)) + break; + + if (parentLayer == ancestorLayer) { + foundAncestorFirst = true; + break; + } + + parentLayer = parentLayer->parent(); + } + + if (foundAncestorFirst) { + // Found ancestorLayer before the abs. positioned container, so compute offset of both relative + // to enclosingPositionedAncestor and subtract. + RenderLayer* positionedAncestor = parentLayer->enclosingPositionedAncestor(); + + int thisX = 0; + int thisY = 0; + convertToLayerCoords(positionedAncestor, thisX, thisY); + + int ancestorX = 0; + int ancestorY = 0; + ancestorLayer->convertToLayerCoords(positionedAncestor, ancestorX, ancestorY); + + xPos += (thisX - ancestorX); + yPos += (thisY - ancestorY); + return; + } + } else parentLayer = parent(); - if (!parentLayer) return; + if (!parentLayer) + return; parentLayer->convertToLayerCoords(ancestorLayer, xPos, yPos); @@ -959,12 +1007,22 @@ RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& xPos, i yPos += y(); } +static inline int adjustedScrollDelta(int beginningDelta) { + // This implemention matches Firefox's. + // http://mxr.mozilla.org/firefox/source/toolkit/content/widgets/browser.xml#856. + const int speedReducer = 12; + + int adjustedDelta = beginningDelta / speedReducer; + if (adjustedDelta > 1) + adjustedDelta = static_cast<int>(adjustedDelta * sqrt(static_cast<double>(adjustedDelta))) - 1; + else if (adjustedDelta < -1) + adjustedDelta = static_cast<int>(adjustedDelta * sqrt(static_cast<double>(-adjustedDelta))) + 1; + + return adjustedDelta; +} + void RenderLayer::panScrollFromPoint(const IntPoint& sourcePoint) { - // We want to reduce the speed if we're close from the original point to improve the handleability of the scroll - const int shortDistanceLimit = 100; // We delimit a 200 pixels long square enclosing the original point - const int speedReducer = 2; // Within this square we divide the scrolling speed by 2 - Frame* frame = renderer()->document()->frame(); if (!frame) return; @@ -981,22 +1039,19 @@ void RenderLayer::panScrollFromPoint(const IntPoint& sourcePoint) int xDelta = currentMousePosition.x() - sourcePoint.x(); int yDelta = currentMousePosition.y() - sourcePoint.y(); - if (abs(xDelta) < ScrollView::noPanScrollRadius) // at the center we let the space for the icon + if (abs(xDelta) <= ScrollView::noPanScrollRadius) // at the center we let the space for the icon xDelta = 0; - if (abs(yDelta) < ScrollView::noPanScrollRadius) + if (abs(yDelta) <= ScrollView::noPanScrollRadius) yDelta = 0; - // Let's attenuate the speed for the short distances - if (abs(xDelta) < shortDistanceLimit) - xDelta /= speedReducer; - if (abs(yDelta) < shortDistanceLimit) - yDelta /= speedReducer; - - scrollByRecursively(xDelta, yDelta); + scrollByRecursively(adjustedScrollDelta(xDelta), adjustedScrollDelta(yDelta)); } void RenderLayer::scrollByRecursively(int xDelta, int yDelta) { + if (!xDelta && !yDelta) + return; + bool restrictedByLineClamp = false; if (renderer()->parent()) restrictedByLineClamp = renderer()->parent()->style()->lineClamp() >= 0; @@ -1006,17 +1061,30 @@ void RenderLayer::scrollByRecursively(int xDelta, int yDelta) int newOffsetY = scrollYOffset() + yDelta; scrollToOffset(newOffsetX, newOffsetY); - // If this layer can't do the scroll we ask its parent + // If this layer can't do the scroll we ask the next layer up that can scroll to try int leftToScrollX = newOffsetX - scrollXOffset(); int leftToScrollY = newOffsetY - scrollYOffset(); if ((leftToScrollX || leftToScrollY) && renderer()->parent()) { - renderer()->parent()->enclosingLayer()->scrollByRecursively(leftToScrollX, leftToScrollY); + RenderObject* nextRenderer = renderer()->parent(); + while (nextRenderer) { + if (nextRenderer->isBox() && toRenderBox(nextRenderer)->canBeScrolledAndHasScrollableArea()) { + nextRenderer->enclosingLayer()->scrollByRecursively(leftToScrollX, leftToScrollY); + break; + } + nextRenderer = nextRenderer->parent(); + } + Frame* frame = renderer()->document()->frame(); if (frame) frame->eventHandler()->updateAutoscrollRenderer(); } - } else if (renderer()->view()->frameView()) + } else if (renderer()->view()->frameView()) { + // If we are here, we were called on a renderer that can be programatically scrolled, but doesn't + // have an overflow clip. Which means that it is a document node that can be scrolled. renderer()->view()->frameView()->scrollBy(IntSize(xDelta, yDelta)); + // FIXME: If we didn't scroll the whole way, do we want to try looking at the frames ownerElement? + // https://bugs.webkit.org/show_bug.cgi?id=28237 + } } @@ -1275,7 +1343,9 @@ void RenderLayer::autoscroll() if (!frameView) return; +#if ENABLE(DRAG_SUPPORT) frame->eventHandler()->updateSelectionForMouseDrag(); +#endif IntPoint currentDocumentPosition = frameView->windowToContents(frame->eventHandler()->currentMousePosition()); scrollRectToVisible(IntRect(currentDocumentPosition, IntSize(1, 1)), false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded); @@ -2056,9 +2126,7 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, // Make sure the parent's clip rects have been calculated. IntRect clipRect = paintDirtyRect; if (parent()) { - ClipRects parentRects; - parentClipRects(rootLayer, parentRects, paintFlags & PaintLayerTemporaryClipRects); - clipRect = parentRects.overflowClipRect(); + clipRect = backgroundClipRect(rootLayer, paintFlags & PaintLayerTemporaryClipRects); clipRect.intersect(paintDirtyRect); } @@ -2368,9 +2436,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont if (transform() && !appliedTransform) { // Make sure the parent's clip rects have been calculated. if (parent()) { - ClipRects parentRects; - parentClipRects(rootLayer, parentRects, useTemporaryClipRects); - IntRect clipRect = parentRects.overflowClipRect(); + IntRect clipRect = backgroundClipRect(rootLayer, useTemporaryClipRects); // Go ahead and test the enclosing clip now. if (!clipRect.contains(hitTestPoint)) return 0; @@ -2668,10 +2734,10 @@ void RenderLayer::parentClipRects(const RenderLayer* rootLayer, ClipRects& clipR clipRects = *parent()->clipRects(); } -void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& paintDirtyRect, IntRect& layerBounds, - IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect, bool temporaryClipRects) const +IntRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, bool temporaryClipRects) const { - if (rootLayer != this && parent()) { + IntRect backgroundRect; + if (parent()) { ClipRects parentRects; parentClipRects(rootLayer, parentRects, temporaryClipRects); backgroundRect = renderer()->style()->position() == FixedPosition ? parentRects.fixedClipRect() : @@ -2681,7 +2747,15 @@ void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& pa ASSERT(view); if (view && parentRects.fixed() && rootLayer->renderer() == view) backgroundRect.move(view->frameView()->scrollX(), view->frameView()->scrollY()); + } + return backgroundRect; +} +void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& paintDirtyRect, IntRect& layerBounds, + IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect, bool temporaryClipRects) const +{ + if (rootLayer != this && parent()) { + backgroundRect = backgroundClipRect(rootLayer, temporaryClipRects); backgroundRect.intersect(paintDirtyRect); } else backgroundRect = paintDirtyRect; @@ -2771,7 +2845,7 @@ IntRect RenderLayer::localBoundingBox() const { // There are three special cases we need to consider. // (1) Inline Flows. For inline flows we will create a bounding box that fully encompasses all of the lines occupied by the - // inline. In other words, if some <span> wraps to three lines, we'll create a bounding box that fully encloses the root + // inline. In other words, if some <span> wraps to three lines, we'll create a bounding box that fully encloses the // line boxes of all three lines (including overflow on those lines). // (2) Left/Top Overflow. The width/height of layers already includes right/bottom overflow. However, in the case of left/top // overflow, we have to create a bounding box that will extend to include this overflow. @@ -2785,8 +2859,8 @@ IntRect RenderLayer::localBoundingBox() const InlineFlowBox* firstBox = inlineFlow->firstLineBox(); if (!firstBox) return result; - int top = firstBox->root()->topOverflow(); - int bottom = inlineFlow->lastLineBox()->root()->bottomOverflow(); + int top = firstBox->topVisibleOverflow(); + int bottom = inlineFlow->lastLineBox()->bottomVisibleOverflow(); int left = firstBox->x(); for (InlineRunBox* curr = firstBox->nextLineBox(); curr; curr = curr->nextLineBox()) left = min(left, curr->x()); @@ -2797,7 +2871,7 @@ IntRect RenderLayer::localBoundingBox() const if (child->isTableCell()) { IntRect bbox = toRenderBox(child)->borderBoxRect(); result.unite(bbox); - IntRect overflowRect = renderBox()->overflowRect(false); + IntRect overflowRect = renderBox()->visibleOverflowRect(); if (bbox != overflowRect) result.unite(overflowRect); } @@ -2810,7 +2884,7 @@ IntRect RenderLayer::localBoundingBox() const else { IntRect bbox = box->borderBoxRect(); result = bbox; - IntRect overflowRect = box->overflowRect(false); + IntRect overflowRect = box->visibleOverflowRect(); if (bbox != overflowRect) result.unite(overflowRect); } @@ -2873,6 +2947,11 @@ void RenderLayer::clearBacking() { m_backing.clear(); } + +bool RenderLayer::hasCompositedMask() const +{ + return m_backing && m_backing->hasMaskLayer(); +} #endif void RenderLayer::setParent(RenderLayer* parent) @@ -3183,10 +3262,9 @@ void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle*) m_marquee = 0; } - if (!hasReflection() && m_reflection) { - m_reflection->destroy(); - m_reflection = 0; - } else if (hasReflection()) { + if (!hasReflection() && m_reflection) + removeReflection(); + else if (hasReflection()) { if (!m_reflection) createReflection(); updateReflectionStyle(); @@ -3260,6 +3338,16 @@ void RenderLayer::createReflection() m_reflection->setParent(renderer()); // We create a 1-way connection. } +void RenderLayer::removeReflection() +{ + if (!m_reflection->documentBeingDestroyed()) + m_reflection->removeLayers(this); + + m_reflection->setParent(0); + m_reflection->destroy(); + m_reflection = 0; +} + void RenderLayer::updateReflectionStyle() { RefPtr<RenderStyle> newStyle = RenderStyle::create(); diff --git a/WebCore/rendering/RenderLayer.h b/WebCore/rendering/RenderLayer.h index 1772c66..9d2212b 100644 --- a/WebCore/rendering/RenderLayer.h +++ b/WebCore/rendering/RenderLayer.h @@ -415,11 +415,13 @@ public: #if USE(ACCELERATED_COMPOSITING) bool isComposited() const { return m_backing != 0; } + bool hasCompositedMask() const; RenderLayerBacking* backing() const { return m_backing.get(); } RenderLayerBacking* ensureBacking(); void clearBacking(); #else bool isComposited() const { return false; } + bool hasCompositedMask() const { return false; } #endif bool paintsWithTransparency() const @@ -507,11 +509,14 @@ private: Node* enclosingElement() const; void createReflection(); + void removeReflection(); + void updateReflectionStyle(); bool paintingInsideReflection() const { return m_paintingInsideReflection; } void setPaintingInsideReflection(bool b) { m_paintingInsideReflection = b; } void parentClipRects(const RenderLayer* rootLayer, ClipRects&, bool temporaryClipRects = false) const; + IntRect backgroundClipRect(const RenderLayer* rootLayer, bool temporaryClipRects) const; RenderLayer* enclosingTransformedAncestor() const; diff --git a/WebCore/rendering/RenderLayerBacking.cpp b/WebCore/rendering/RenderLayerBacking.cpp index e98c458..941817c 100644 --- a/WebCore/rendering/RenderLayerBacking.cpp +++ b/WebCore/rendering/RenderLayerBacking.cpp @@ -28,11 +28,13 @@ #if USE(ACCELERATED_COMPOSITING) #include "AnimationController.h" +#include "CanvasRenderingContext3D.h" #include "CSSPropertyNames.h" #include "CSSStyleSelector.h" #include "FrameView.h" #include "GraphicsContext.h" #include "GraphicsLayer.h" +#include "HTMLCanvasElement.h" #include "HTMLElement.h" #include "HTMLNames.h" #include "RenderBox.h" @@ -47,17 +49,16 @@ using namespace std; namespace WebCore { +using namespace HTMLNames; + static bool hasBorderOutlineOrShadow(const RenderStyle*); static bool hasBoxDecorations(const RenderStyle*); static bool hasBoxDecorationsWithBackgroundImage(const RenderStyle*); RenderLayerBacking::RenderLayerBacking(RenderLayer* layer) : m_owningLayer(layer) - , m_ancestorClippingLayer(0) - , m_graphicsLayer(0) - , m_foregroundLayer(0) - , m_clippingLayer(0) , m_hasDirectlyCompositedContent(false) + , m_artificiallyInflatedBounds(false) { createGraphicsLayer(); } @@ -66,12 +67,13 @@ RenderLayerBacking::~RenderLayerBacking() { updateClippingLayers(false, false); updateForegroundLayer(false); + updateMaskLayer(false); destroyGraphicsLayer(); } void RenderLayerBacking::createGraphicsLayer() { - m_graphicsLayer = GraphicsLayer::createGraphicsLayer(this); + m_graphicsLayer = GraphicsLayer::create(this); #ifndef NDEBUG if (renderer()->node()) { @@ -79,7 +81,7 @@ void RenderLayerBacking::createGraphicsLayer() m_graphicsLayer->setName("Document Node"); else { if (renderer()->node()->isHTMLElement() && renderer()->node()->hasID()) - m_graphicsLayer->setName(renderer()->renderName() + String(" ") + static_cast<HTMLElement*>(renderer()->node())->id()); + m_graphicsLayer->setName(renderer()->renderName() + String(" ") + static_cast<HTMLElement*>(renderer()->node())->getAttribute(idAttr)); else m_graphicsLayer->setName(renderer()->renderName()); } @@ -96,14 +98,10 @@ void RenderLayerBacking::destroyGraphicsLayer() if (m_graphicsLayer) m_graphicsLayer->removeFromParent(); - delete m_graphicsLayer; m_graphicsLayer = 0; - - delete m_foregroundLayer; m_foregroundLayer = 0; - - delete m_clippingLayer; m_clippingLayer = 0; + m_maskLayer = 0; } void RenderLayerBacking::updateLayerOpacity() @@ -126,6 +124,30 @@ void RenderLayerBacking::updateLayerTransform() m_graphicsLayer->setTransform(t); } +static bool hasNonZeroTransformOrigin(const RenderObject* renderer) +{ + RenderStyle* style = renderer->style(); + return (style->transformOriginX().type() == Fixed && style->transformOriginX().value()) + || (style->transformOriginY().type() == Fixed && style->transformOriginY().value()); +} + +void RenderLayerBacking::updateCompositedBounds() +{ + IntRect layerBounds = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer); + + // If the element has a transform-origin that has fixed lengths, and the renderer has zero size, + // then we need to ensure that the compositing layer has non-zero size so that we can apply + // the transform-origin via the GraphicsLayer anchorPoint (which is expressed as a fractional value). + if (layerBounds.isEmpty() && hasNonZeroTransformOrigin(renderer())) { + layerBounds.setWidth(1); + layerBounds.setHeight(1); + m_artificiallyInflatedBounds = true; + } else + m_artificiallyInflatedBounds = false; + + setCompositedBounds(layerBounds); +} + void RenderLayerBacking::updateAfterLayout(UpdateDepth updateDepth) { RenderLayerCompositor* layerCompositor = compositor(); @@ -137,7 +159,7 @@ void RenderLayerBacking::updateAfterLayout(UpdateDepth updateDepth) // // The solution is to update compositing children of this layer here, // via updateCompositingChildrenGeometry(). - setCompositedBounds(layerCompositor->calculateCompositedBounds(m_owningLayer, m_owningLayer)); + updateCompositedBounds(); layerCompositor->updateCompositingDescendantGeometry(m_owningLayer, m_owningLayer, updateDepth); if (!m_owningLayer->parent()) { @@ -158,6 +180,9 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration() if (updateClippingLayers(compositor->clippedByAncestor(m_owningLayer), compositor->clipsCompositingDescendants(m_owningLayer))) layerConfigChanged = true; + if (updateMaskLayer(m_owningLayer->renderer()->hasMask())) + m_graphicsLayer->setMaskLayer(m_maskLayer.get()); + m_hasDirectlyCompositedContent = false; if (canUseDirectCompositing()) { if (renderer()->isImage()) { @@ -165,6 +190,16 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration() m_hasDirectlyCompositedContent = true; m_graphicsLayer->setDrawsContent(false); } +#if ENABLE(3D_CANVAS) + else if (renderer()->isCanvas()) { + HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer()->node()); + if (canvas->is3D()) { + CanvasRenderingContext3D* context = static_cast<CanvasRenderingContext3D*>(canvas->renderingContext()); + if (context->graphicsContext3D()->platformGraphicsContext3D()) + m_graphicsLayer->setContentsToGraphicsContext3D(context->graphicsContext3D()); + } + } +#endif if (rendererHasBackground()) m_graphicsLayer->setBackgroundColor(rendererBackgroundColor()); @@ -222,10 +257,7 @@ void RenderLayerBacking::updateGraphicsLayerGeometry() // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects // for a compositing layer, rootLayer is the layer itself. - ClipRects parentRects; - m_owningLayer->parentClipRects(compAncestor, parentRects, true); - IntRect parentClipRect = parentRects.overflowClipRect(); - + IntRect parentClipRect = m_owningLayer->backgroundClipRect(compAncestor, true); m_ancestorClippingLayer->setPosition(FloatPoint() + (parentClipRect.location() - graphicsLayerParentLocation)); m_ancestorClippingLayer->setSize(parentClipRect.size()); @@ -251,13 +283,19 @@ void RenderLayerBacking::updateGraphicsLayerGeometry() } // If we have a layer that clips children, position it. + IntRect clippingBox; if (m_clippingLayer) { - IntRect clippingBox = toRenderBox(renderer())->overflowClipRect(0, 0); + clippingBox = toRenderBox(renderer())->overflowClipRect(0, 0); m_clippingLayer->setPosition(FloatPoint() + (clippingBox.location() - localCompositingBounds.location())); m_clippingLayer->setSize(clippingBox.size()); m_clippingLayer->setOffsetFromRenderer(clippingBox.location() - IntPoint()); } + if (m_maskLayer) { + m_maskLayer->setSize(m_graphicsLayer->size()); + m_maskLayer->setPosition(FloatPoint()); + } + if (m_owningLayer->hasTransform()) { const IntRect borderBox = toRenderBox(renderer())->borderBoxRect(); @@ -293,15 +331,25 @@ void RenderLayerBacking::updateGraphicsLayerGeometry() } if (m_foregroundLayer) { - // The contents layer is always coincidental with the graphicsLayer for now. - m_foregroundLayer->setPosition(IntPoint(0, 0)); - m_foregroundLayer->setSize(newSize); - m_foregroundLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer()); + FloatPoint foregroundPosition; + FloatSize foregroundSize = newSize; + IntSize foregroundOffset = m_graphicsLayer->offsetFromRenderer(); + // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it, + // so that it gets correctly sorted with children. In that case, position relative to the clipping layer. + if (m_clippingLayer) { + foregroundPosition = FloatPoint() + (localCompositingBounds.location() - clippingBox.location()); + foregroundSize = FloatSize(clippingBox.size()); + foregroundOffset = clippingBox.location() - IntPoint(); + } + + m_foregroundLayer->setPosition(foregroundPosition); + m_foregroundLayer->setSize(foregroundSize); + m_foregroundLayer->setOffsetFromRenderer(foregroundOffset); } m_graphicsLayer->setContentsRect(contentsBox()); if (!m_hasDirectlyCompositedContent) - m_graphicsLayer->setDrawsContent(!isSimpleContainerCompositingLayer() && !paintingGoesToWindow()); + m_graphicsLayer->setDrawsContent(!isSimpleContainerCompositingLayer() && !paintingGoesToWindow() && !m_artificiallyInflatedBounds); } void RenderLayerBacking::updateInternalHierarchy() @@ -311,12 +359,12 @@ void RenderLayerBacking::updateInternalHierarchy() if (m_ancestorClippingLayer) { m_ancestorClippingLayer->removeAllChildren(); m_graphicsLayer->removeFromParent(); - m_ancestorClippingLayer->addChild(m_graphicsLayer); + m_ancestorClippingLayer->addChild(m_graphicsLayer.get()); } if (m_clippingLayer) { m_clippingLayer->removeFromParent(); - m_graphicsLayer->addChild(m_clippingLayer); + m_graphicsLayer->addChild(m_clippingLayer.get()); } } @@ -327,7 +375,7 @@ bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needs if (needsAncestorClip) { if (!m_ancestorClippingLayer) { - m_ancestorClippingLayer = GraphicsLayer::createGraphicsLayer(this); + m_ancestorClippingLayer = GraphicsLayer::create(this); #ifndef NDEBUG m_ancestorClippingLayer->setName("Ancestor clipping Layer"); #endif @@ -336,14 +384,13 @@ bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needs } } else if (m_ancestorClippingLayer) { m_ancestorClippingLayer->removeFromParent(); - delete m_ancestorClippingLayer; m_ancestorClippingLayer = 0; layersChanged = true; } if (needsDescendantClip) { if (!m_clippingLayer) { - m_clippingLayer = GraphicsLayer::createGraphicsLayer(0); + m_clippingLayer = GraphicsLayer::create(0); #ifndef NDEBUG m_clippingLayer->setName("Child clipping Layer"); #endif @@ -352,7 +399,6 @@ bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needs } } else if (m_clippingLayer) { m_clippingLayer->removeFromParent(); - delete m_clippingLayer; m_clippingLayer = 0; layersChanged = true; } @@ -368,25 +414,61 @@ bool RenderLayerBacking::updateForegroundLayer(bool needsForegroundLayer) bool layerChanged = false; if (needsForegroundLayer) { if (!m_foregroundLayer) { - m_foregroundLayer = GraphicsLayer::createGraphicsLayer(this); + m_foregroundLayer = GraphicsLayer::create(this); #ifndef NDEBUG - m_foregroundLayer->setName("Contents"); + m_foregroundLayer->setName("Foreground"); #endif m_foregroundLayer->setDrawsContent(true); - m_foregroundLayer->setDrawingPhase(GraphicsLayerPaintForegroundMask); - m_graphicsLayer->setDrawingPhase(GraphicsLayerPaintBackgroundMask); + m_foregroundLayer->setPaintingPhase(GraphicsLayerPaintForeground); layerChanged = true; } } else if (m_foregroundLayer) { m_foregroundLayer->removeFromParent(); - delete m_foregroundLayer; m_foregroundLayer = 0; - m_graphicsLayer->setDrawingPhase(GraphicsLayerPaintAllMask); layerChanged = true; } + + if (layerChanged) + m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer()); + + return layerChanged; +} + +bool RenderLayerBacking::updateMaskLayer(bool needsMaskLayer) +{ + bool layerChanged = false; + if (needsMaskLayer) { + if (!m_maskLayer) { + m_maskLayer = GraphicsLayer::create(this); +#ifndef NDEBUG + m_maskLayer->setName("Mask"); +#endif + m_maskLayer->setDrawsContent(true); + m_maskLayer->setPaintingPhase(GraphicsLayerPaintMask); + layerChanged = true; + } + } else if (m_maskLayer) { + m_maskLayer = 0; + layerChanged = true; + } + + if (layerChanged) + m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer()); + return layerChanged; } +GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() const +{ + unsigned phase = GraphicsLayerPaintBackground; + if (!m_foregroundLayer) + phase |= GraphicsLayerPaintForeground; + if (!m_maskLayer) + phase |= GraphicsLayerPaintMask; + + return static_cast<GraphicsLayerPaintingPhase>(phase); +} + float RenderLayerBacking::compositingOpacity(float rendererOpacity) const { float finalOpacity = rendererOpacity; @@ -500,7 +582,7 @@ bool RenderLayerBacking::isSimpleContainerCompositingLayer() const // Now look at the body's renderer. HTMLElement* body = renderObject->document()->body(); - RenderObject* bodyObject = (body && body->hasLocalName(HTMLNames::bodyTag)) ? body->renderer() : 0; + RenderObject* bodyObject = (body && body->hasLocalName(bodyTag)) ? body->renderer() : 0; if (!bodyObject) return false; @@ -582,6 +664,14 @@ bool RenderLayerBacking::canUseDirectCompositing() const { RenderObject* renderObject = renderer(); + // Canvas3D is always direct composited +#if ENABLE(3D_CANVAS) + if (renderer()->isCanvas()) { + HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer()->node()); + return canvas->is3D(); + } +#endif + // Reject anything that isn't an image if (!renderObject->isImage() && !renderObject->isVideo()) return false; @@ -600,8 +690,19 @@ bool RenderLayerBacking::canUseDirectCompositing() const void RenderLayerBacking::rendererContentChanged() { - if (canUseDirectCompositing() && renderer()->isImage()) - updateImageContents(); + if (canUseDirectCompositing()) { + if (renderer()->isImage()) + updateImageContents(); + else { +#if ENABLE(3D_CANVAS) + if (renderer()->isCanvas()) { + HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer()->node()); + if (canvas->is3D()) + m_graphicsLayer->setGraphicsContext3DNeedsDisplay(); + } +#endif + } + } } void RenderLayerBacking::updateImageContents() @@ -705,13 +806,16 @@ void RenderLayerBacking::setContentsNeedDisplay() if (m_foregroundLayer && m_foregroundLayer->drawsContent()) m_foregroundLayer->setNeedsDisplay(); + + if (m_maskLayer && m_maskLayer->drawsContent()) + m_maskLayer->setNeedsDisplay(); } // r is in the coordinate space of the layer's render object void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r) { if (m_graphicsLayer && m_graphicsLayer->drawsContent()) { - FloatPoint dirtyOrigin = contentsToGraphicsLayerCoordinates(m_graphicsLayer, FloatPoint(r.x(), r.y())); + FloatPoint dirtyOrigin = contentsToGraphicsLayerCoordinates(m_graphicsLayer.get(), FloatPoint(r.x(), r.y())); FloatRect dirtyRect(dirtyOrigin, r.size()); FloatRect bounds(FloatPoint(), m_graphicsLayer->size()); if (bounds.intersects(dirtyRect)) @@ -722,6 +826,11 @@ void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r) // FIXME: do incremental repaint m_foregroundLayer->setNeedsDisplay(); } + + if (m_maskLayer && m_maskLayer->drawsContent()) { + // FIXME: do incremental repaint + m_maskLayer->setNeedsDisplay(); + } } static void setClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect) @@ -779,7 +888,7 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* bool shouldPaint = m_owningLayer->hasVisibleContent() && m_owningLayer->isSelfPaintingLayer(); - if (shouldPaint && (paintingPhase & GraphicsLayerPaintBackgroundMask)) { + if (shouldPaint && (paintingPhase & GraphicsLayerPaintBackground)) { // If this is the root then we need to send in a bigger bounding box // because we'll be painting the background as well (see RenderBox::paintRootBoxDecorations()). IntRect paintBox = clipRectToApply; @@ -823,7 +932,10 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* restoreClip(context, paintDirtyRect, damageRect); } - if (shouldPaint && (paintingPhase & GraphicsLayerPaintForegroundMask)) { + bool forceBlackText = paintRestriction == PaintRestrictionSelectionOnlyBlackText; + bool selectionOnly = paintRestriction == PaintRestrictionSelectionOnly || paintRestriction == PaintRestrictionSelectionOnlyBlackText; + + if (shouldPaint && (paintingPhase & GraphicsLayerPaintForeground)) { // Now walk the sorted list of children with negative z-indices. Only RenderLayers without compositing layers will paint. // FIXME: should these be painted as background? Vector<RenderLayer*>* negZOrderList = m_owningLayer->negZOrderList(); @@ -832,9 +944,6 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* it[0]->paintLayer(rootLayer, context, paintDirtyRect, paintRestriction, paintingRoot); } - bool forceBlackText = paintRestriction == PaintRestrictionSelectionOnlyBlackText; - bool selectionOnly = paintRestriction == PaintRestrictionSelectionOnly || paintRestriction == PaintRestrictionSelectionOnlyBlackText; - // Set up the clip used when painting our children. setClip(context, paintDirtyRect, clipRectToApply); RenderObject::PaintInfo paintInfo(context, clipRectToApply, @@ -877,7 +986,9 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* for (Vector<RenderLayer*>::iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) it[0]->paintLayer(rootLayer, context, paintDirtyRect, paintRestriction, paintingRoot); } - + } + + if (shouldPaint && (paintingPhase & GraphicsLayerPaintMask)) { if (renderer()->hasMask() && !selectionOnly && !damageRect.isEmpty()) { setClip(context, paintDirtyRect, damageRect); @@ -894,7 +1005,7 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* } // Up-call from compositing layer drawing callback. -void RenderLayerBacking::paintContents(const GraphicsLayer*, GraphicsContext& context, GraphicsLayerPaintingPhase drawingPhase, const IntRect& clip) +void RenderLayerBacking::paintContents(const GraphicsLayer*, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const IntRect& clip) { // We have to use the same root as for hit testing, because both methods // can compute and cache clipRects. @@ -912,7 +1023,7 @@ void RenderLayerBacking::paintContents(const GraphicsLayer*, GraphicsContext& co IntRect dirtyRect = enclosingBBox; dirtyRect.intersect(clipRect); - paintIntoLayer(m_owningLayer, &context, dirtyRect, PaintRestrictionNone, drawingPhase, renderer()); + paintIntoLayer(m_owningLayer, &context, dirtyRect, PaintRestrictionNone, paintingPhase, renderer()); } bool RenderLayerBacking::startAnimation(double beginTime, const Animation* anim, const KeyframeList& keyframes) @@ -970,7 +1081,8 @@ bool RenderLayerBacking::startTransition(double beginTime, int property, const R KeyframeValueList opacityVector(AnimatedPropertyOpacity); opacityVector.insert(new FloatAnimationValue(0, compositingOpacity(fromStyle->opacity()))); opacityVector.insert(new FloatAnimationValue(1, compositingOpacity(toStyle->opacity()))); - if (m_graphicsLayer->addAnimation(opacityVector, toRenderBox(renderer())->borderBoxRect().size(), opacityAnim, String(), beginTime)) + // The boxSize param is only used for transform animations (which can only run on RenderBoxes), so we pass an empty size here. + if (m_graphicsLayer->addAnimation(opacityVector, IntSize(), opacityAnim, String(), beginTime)) didAnimate = true; } } diff --git a/WebCore/rendering/RenderLayerBacking.h b/WebCore/rendering/RenderLayerBacking.h index b027685..e12aa58 100644 --- a/WebCore/rendering/RenderLayerBacking.h +++ b/WebCore/rendering/RenderLayerBacking.h @@ -63,21 +63,23 @@ public: // Update contents and clipping structure. void updateInternalHierarchy(); // make private - GraphicsLayer* graphicsLayer() const { return m_graphicsLayer; } + GraphicsLayer* graphicsLayer() const { return m_graphicsLayer.get(); } // Layer to clip children bool hasClippingLayer() const { return m_clippingLayer != 0; } - GraphicsLayer* clippingLayer() const { return m_clippingLayer; } + GraphicsLayer* clippingLayer() const { return m_clippingLayer.get(); } // Layer to get clipped by ancestor bool hasAncestorClippingLayer() const { return m_ancestorClippingLayer != 0; } - GraphicsLayer* ancestorClippingLayer() const { return m_ancestorClippingLayer; } + GraphicsLayer* ancestorClippingLayer() const { return m_ancestorClippingLayer.get(); } bool hasContentsLayer() const { return m_foregroundLayer != 0; } - GraphicsLayer* foregroundLayer() const { return m_foregroundLayer; } + GraphicsLayer* foregroundLayer() const { return m_foregroundLayer.get(); } - GraphicsLayer* parentForSublayers() const { return m_clippingLayer ? m_clippingLayer : m_graphicsLayer; } - GraphicsLayer* childForSuperlayers() const { return m_ancestorClippingLayer ? m_ancestorClippingLayer : m_graphicsLayer; } + bool hasMaskLayer() const { return m_maskLayer != 0; } + + GraphicsLayer* parentForSublayers() const { return m_clippingLayer ? m_clippingLayer.get() : m_graphicsLayer.get(); } + GraphicsLayer* childForSuperlayers() const { return m_ancestorClippingLayer ? m_ancestorClippingLayer.get() : m_graphicsLayer.get(); } // RenderLayers with backing normally short-circuit paintLayer() because // their content is rendered via callbacks from GraphicsLayer. However, the document @@ -106,6 +108,7 @@ public: IntRect compositedBounds() const; void setCompositedBounds(const IntRect&); + void updateCompositedBounds(); FloatPoint graphicsLayerToContentsCoordinates(const GraphicsLayer*, const FloatPoint&); FloatPoint contentsToGraphicsLayerCoordinates(const GraphicsLayer*, const FloatPoint&); @@ -127,7 +130,10 @@ private: bool updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip); bool updateForegroundLayer(bool needsForegroundLayer); + bool updateMaskLayer(bool needsMaskLayer); + GraphicsLayerPaintingPhase paintingPhaseForPrimaryLayer() const; + IntSize contentOffsetInCompostingLayer() const; // Result is transform origin in pixels. FloatPoint3D computeTransformOrigin(const IntRect& borderBox) const; @@ -162,14 +168,16 @@ private: private: RenderLayer* m_owningLayer; - GraphicsLayer* m_ancestorClippingLayer; // only used if we are clipped by an ancestor which is not a stacking context - GraphicsLayer* m_graphicsLayer; - GraphicsLayer* m_foregroundLayer; // only used in cases where we need to draw the foreground separately - GraphicsLayer* m_clippingLayer; // only used if we have clipping on a stacking context, with compositing children + OwnPtr<GraphicsLayer> m_ancestorClippingLayer; // only used if we are clipped by an ancestor which is not a stacking context + OwnPtr<GraphicsLayer> m_graphicsLayer; + OwnPtr<GraphicsLayer> m_foregroundLayer; // only used in cases where we need to draw the foreground separately + OwnPtr<GraphicsLayer> m_clippingLayer; // only used if we have clipping on a stacking context, with compositing children + OwnPtr<GraphicsLayer> m_maskLayer; // only used if we have a mask IntRect m_compositedBounds; bool m_hasDirectlyCompositedContent; + bool m_artificiallyInflatedBounds; // bounds had to be made non-zero to make transform-origin work }; } // namespace WebCore diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp index fb15800..5201287 100644 --- a/WebCore/rendering/RenderLayerCompositor.cpp +++ b/WebCore/rendering/RenderLayerCompositor.cpp @@ -34,8 +34,8 @@ #include "Frame.h" #include "FrameView.h" #include "GraphicsLayer.h" -#include "HitTestRequest.h" #include "HitTestResult.h" +#include "HTMLCanvasElement.h" #include "Page.h" #include "RenderLayerBacking.h" #include "RenderVideo.h" @@ -92,7 +92,6 @@ RenderLayerCompositor::RenderLayerCompositor(RenderView* renderView) RenderLayerCompositor::~RenderLayerCompositor() { ASSERT(!m_rootLayerAttached); - delete m_rootPlatformLayer; } void RenderLayerCompositor::enableCompositingMode(bool enable /* = true */) @@ -287,6 +286,13 @@ IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* laye return boundingBoxRect; } + if (RenderLayer* reflection = layer->reflectionLayer()) { + if (!reflection->isComposited()) { + IntRect childUnionBounds = calculateCompositedBounds(reflection, layer); + unionBounds.unite(childUnionBounds); + } + } + ASSERT(layer->isStackingContext() || (!layer->m_posZOrderList || layer->m_posZOrderList->size() == 0)); if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) { @@ -425,11 +431,11 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O bool haveComputedBounds = false; IntRect absBounds; - if (overlapMap && mustOverlapCompositedLayers) { + if (overlapMap && !overlapMap->isEmpty()) { // If we're testing for overlap, we only need to composite if we overlap something that is already composited. absBounds = layer->renderer()->localToAbsoluteQuad(FloatRect(layer->localBoundingBox())).enclosingBoundingBox(); haveComputedBounds = true; - mustOverlapCompositedLayers &= overlapsCompositedLayers(*overlapMap, absBounds); + mustOverlapCompositedLayers = overlapsCompositedLayers(*overlapMap, absBounds); } layer->setMustOverlapCompositedLayers(mustOverlapCompositedLayers); @@ -503,8 +509,7 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O // If we have a software transform, and we have layers under us, we need to also // be composited. Also, if we have opacity < 1, then we need to be a layer so that // the child layers are opaque, then rendered with opacity on this layer. - if (childState.m_subtreeIsCompositing && - (layer->renderer()->hasTransform() || layer->renderer()->style()->opacity() < 1)) { + if (childState.m_subtreeIsCompositing && requiresCompositingWhenDescendantsAreCompositing(layer->renderer())) { layer->setMustOverlapCompositedLayers(true); if (overlapMap) addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds); @@ -530,6 +535,7 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O void RenderLayerCompositor::setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer) { + ASSERT(!parentLayer || childLayer->ancestorCompositingLayer() == parentLayer); ASSERT(childLayer->isComposited()); // It's possible to be called with a parent that isn't yet composited when we're doing @@ -573,7 +579,7 @@ bool RenderLayerCompositor::canAccelerateVideoRendering(RenderVideo* o) const { // FIXME: ideally we need to look at all ancestors for mask or video. But for now, // just bail on the obvious cases. - if (o->hasMask() || o->hasReflection() || !m_hasAcceleratedCompositing) + if (o->hasReflection() || !m_hasAcceleratedCompositing) return false; return o->supportsAcceleratedRendering(); @@ -589,8 +595,7 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, stru if (layerBacking) { // The compositing state of all our children has been updated already, so now // we can compute and cache the composited bounds for this layer. - layerBacking->setCompositedBounds(calculateCompositedBounds(layer, layer)); - + layerBacking->updateCompositedBounds(); layerBacking->updateGraphicsLayerConfiguration(); layerBacking->updateGraphicsLayerGeometry(); @@ -632,10 +637,10 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, stru } if (updateHierarchy && layerBacking && layerBacking->foregroundLayer()) { - // we only have a contents layer if we have an m_layer layerBacking->foregroundLayer()->removeFromParent(); - - GraphicsLayer* hostingLayer = layerBacking->clippingLayer() ? layerBacking->clippingLayer() : layerBacking->graphicsLayer(); + + // The foreground layer has to be correctly sorted with child layers, so needs to become a child of the clipping layer. + GraphicsLayer* hostingLayer = layerBacking->parentForSublayers(); hostingLayer->addChild(layerBacking->foregroundLayer()); } } @@ -670,7 +675,7 @@ void RenderLayerCompositor::updateCompositingDescendantGeometry(RenderLayer* com { if (layer != compositingAncestor) { if (RenderLayerBacking* layerBacking = layer->backing()) { - layerBacking->setCompositedBounds(calculateCompositedBounds(layer, layer)); + layerBacking->updateCompositedBounds(); layerBacking->updateGraphicsLayerGeometry(); if (updateDepth == RenderLayerBacking::CompositingChildren) return; @@ -759,7 +764,7 @@ RenderLayer* RenderLayerCompositor::rootRenderLayer() const GraphicsLayer* RenderLayerCompositor::rootPlatformLayer() const { - return m_rootPlatformLayer; + return m_rootPlatformLayer.get(); } void RenderLayerCompositor::didMoveOnscreen() @@ -772,7 +777,7 @@ void RenderLayerCompositor::didMoveOnscreen() if (!page) return; - page->chrome()->client()->attachRootGraphicsLayer(frame, m_rootPlatformLayer); + page->chrome()->client()->attachRootGraphicsLayer(frame, m_rootPlatformLayer.get()); m_rootLayerAttached = true; } @@ -793,7 +798,7 @@ void RenderLayerCompositor::willMoveOffscreen() void RenderLayerCompositor::updateRootLayerPosition() { if (m_rootPlatformLayer) - m_rootPlatformLayer->setSize(FloatSize(m_renderView->overflowWidth(), m_renderView->overflowHeight())); + m_rootPlatformLayer->setSize(FloatSize(m_renderView->rightLayoutOverflow(), m_renderView->bottomLayoutOverflow())); } void RenderLayerCompositor::didStartAcceleratedAnimation() @@ -821,11 +826,12 @@ bool RenderLayerCompositor::needsToBeComposited(const RenderLayer* layer) const // Use needsToBeComposited() to determine if a RL actually needs a compositing layer. // static bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) const -{ +{ // The root layer always has a compositing layer, but it may not have backing. return (inCompositingMode() && layer->isRootLayer()) || requiresCompositingForTransform(layer->renderer()) || requiresCompositingForVideo(layer->renderer()) || + requiresCompositingForCanvas(layer->renderer()) || layer->renderer()->style()->backfaceVisibility() == BackfaceVisibilityHidden || clipsCompositingDescendants(layer) || requiresCompositingForAnimation(layer->renderer()); @@ -862,10 +868,8 @@ bool RenderLayerCompositor::clippedByAncestor(RenderLayer* layer) const if (!computeClipRoot || computeClipRoot == layer) return false; - ClipRects parentRects; - layer->parentClipRects(computeClipRoot, parentRects, true); - - return parentRects.overflowClipRect() != ClipRects::infiniteRect(); + IntRect backgroundRect = layer->backgroundClipRect(computeClipRoot, true); + return backgroundRect != ClipRects::infiniteRect(); } // Return true if the given layer is a stacking context and has compositing child @@ -897,6 +901,19 @@ bool RenderLayerCompositor::requiresCompositingForVideo(RenderObject* renderer) return false; } +bool RenderLayerCompositor::requiresCompositingForCanvas(RenderObject* renderer) const +{ +#if ENABLE(3D_CANVAS) + if (renderer->isCanvas()) { + HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer->node()); + return canvas->is3D(); + } +#else + UNUSED_PARAM(renderer); +#endif + return false; +} + bool RenderLayerCompositor::requiresCompositingForAnimation(RenderObject* renderer) const { if (AnimationController* animController = renderer->animation()) { @@ -906,6 +923,11 @@ bool RenderLayerCompositor::requiresCompositingForAnimation(RenderObject* render return false; } +bool RenderLayerCompositor::requiresCompositingWhenDescendantsAreCompositing(RenderObject* renderer) const +{ + return renderer->hasTransform() || renderer->isTransparent() || renderer->hasMask(); +} + // If an element has negative z-index children, those children render in front of the // layer background, so we need an extra 'contents' layer for the foreground of the layer // object. @@ -919,8 +941,8 @@ void RenderLayerCompositor::ensureRootPlatformLayer() if (m_rootPlatformLayer) return; - m_rootPlatformLayer = GraphicsLayer::createGraphicsLayer(0); - m_rootPlatformLayer->setSize(FloatSize(m_renderView->overflowWidth(), m_renderView->overflowHeight())); + m_rootPlatformLayer = GraphicsLayer::create(0); + m_rootPlatformLayer->setSize(FloatSize(m_renderView->rightLayoutOverflow(), m_renderView->bottomLayoutOverflow())); m_rootPlatformLayer->setPosition(FloatPoint(0, 0)); // The root layer does flipping if we need it on this platform. m_rootPlatformLayer->setGeometryOrientation(GraphicsLayer::compositingCoordinatesOrientation()); @@ -937,7 +959,6 @@ void RenderLayerCompositor::destroyRootPlatformLayer() return; willMoveOffscreen(); - delete m_rootPlatformLayer; m_rootPlatformLayer = 0; } diff --git a/WebCore/rendering/RenderLayerCompositor.h b/WebCore/rendering/RenderLayerCompositor.h index 02929dc..a809a70 100644 --- a/WebCore/rendering/RenderLayerCompositor.h +++ b/WebCore/rendering/RenderLayerCompositor.h @@ -164,10 +164,12 @@ private: bool requiresCompositingForAnimation(RenderObject*) const; bool requiresCompositingForTransform(RenderObject*) const; bool requiresCompositingForVideo(RenderObject*) const; + bool requiresCompositingForCanvas(RenderObject*) const; + bool requiresCompositingWhenDescendantsAreCompositing(RenderObject*) const; private: RenderView* m_renderView; - GraphicsLayer* m_rootPlatformLayer; + OwnPtr<GraphicsLayer> m_rootPlatformLayer; bool m_hasAcceleratedCompositing; bool m_compositingConsultsOverlap; bool m_compositing; diff --git a/WebCore/rendering/RenderLineBoxList.cpp b/WebCore/rendering/RenderLineBoxList.cpp index 00566b8..76a2e2f 100644 --- a/WebCore/rendering/RenderLineBoxList.cpp +++ b/WebCore/rendering/RenderLineBoxList.cpp @@ -162,8 +162,8 @@ void RenderLineBoxList::paint(RenderBoxModelObject* renderer, RenderObject::Pain // intersect. This is a quick short-circuit that we can take to avoid walking any lines. // FIXME: This check is flawed in the following extremely obscure way: // if some line in the middle has a huge overflow, it might actually extend below the last line. - int yPos = firstLineBox()->root()->topOverflow() - renderer->maximalOutlineSize(paintInfo.phase); - int h = renderer->maximalOutlineSize(paintInfo.phase) + lastLineBox()->root()->bottomOverflow() - yPos; + int yPos = firstLineBox()->topVisibleOverflow() - renderer->maximalOutlineSize(paintInfo.phase); + int h = renderer->maximalOutlineSize(paintInfo.phase) + lastLineBox()->bottomVisibleOverflow() - yPos; yPos += ty; if (yPos >= paintInfo.rect.bottom() || yPos + h <= paintInfo.rect.y()) return; @@ -184,19 +184,19 @@ void RenderLineBoxList::paint(RenderBoxModelObject* renderer, RenderObject::Pain // The whole way objects break across pages needs to be redone. // Try to avoid splitting a line vertically, but only if it's less than the height // of the entire page. - if (curr->root()->bottomOverflow() - curr->root()->topOverflow() <= v->printRect().height()) { - if (ty + curr->root()->bottomOverflow() > v->printRect().bottom()) { - if (ty + curr->root()->topOverflow() < v->truncatedAt()) - v->setBestTruncatedAt(ty + curr->root()->topOverflow(), renderer); + if (curr->bottomVisibleOverflow() - curr->topVisibleOverflow() <= v->printRect().height()) { + if (ty + curr->bottomVisibleOverflow() > v->printRect().bottom()) { + if (ty + curr->topVisibleOverflow() < v->truncatedAt()) + v->setBestTruncatedAt(ty + curr->root()->topVisibleOverflow(), renderer); // If we were able to truncate, don't paint. - if (ty + curr->root()->topOverflow() >= v->truncatedAt()) + if (ty + curr->topVisibleOverflow() >= v->truncatedAt()) break; } } } - int top = min(curr->root()->topOverflow(), curr->root()->selectionTop()) - renderer->maximalOutlineSize(info.phase); - int bottom = curr->root()->bottomOverflow() + renderer->maximalOutlineSize(info.phase); + int top = min(curr->topVisibleOverflow(), curr->root()->selectionTop()) - renderer->maximalOutlineSize(info.phase); + int bottom = curr->bottomVisibleOverflow() + renderer->maximalOutlineSize(info.phase); h = bottom - top; yPos = ty + top; if (yPos < info.rect.bottom() && yPos + h > info.rect.y()) @@ -229,14 +229,14 @@ bool RenderLineBoxList::hitTest(RenderBoxModelObject* renderer, const HitTestReq // contain the point. This is a quick short-circuit that we can take to avoid walking any lines. // FIXME: This check is flawed in the following extremely obscure way: // if some line in the middle has a huge overflow, it might actually extend below the last line. - if ((y >= ty + lastLineBox()->root()->bottomOverflow()) || (y < ty + firstLineBox()->root()->topOverflow())) + if ((y >= ty + lastLineBox()->root()->bottomVisibleOverflow()) || (y < ty + firstLineBox()->root()->topVisibleOverflow())) return false; // See if our root lines contain the point. If so, then we hit test // them further. Note that boxes can easily overlap, so we can't make any assumptions // based off positions of our first line box or our last line box. for (InlineFlowBox* curr = lastLineBox(); curr; curr = curr->prevFlowBox()) { - if (y >= ty + curr->root()->topOverflow() && y < ty + curr->root()->bottomOverflow()) { + if (y >= ty + curr->root()->topVisibleOverflow() && y < ty + curr->root()->bottomVisibleOverflow()) { bool inside = curr->nodeAtPoint(request, result, x, y, tx, ty); if (inside) { renderer->updateHitTestResult(result, IntPoint(x - tx, y - ty)); diff --git a/WebCore/rendering/RenderListBox.cpp b/WebCore/rendering/RenderListBox.cpp index e6c28f7..0edfdef 100644 --- a/WebCore/rendering/RenderListBox.cpp +++ b/WebCore/rendering/RenderListBox.cpp @@ -508,7 +508,7 @@ bool RenderListBox::listIndexIsVisible(int index) return index >= m_indexOffset && index < m_indexOffset + numVisibleItems(); } -bool RenderListBox::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier) +bool RenderListBox::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier, Node**) { return m_vBar && m_vBar->scroll(direction, granularity, multiplier); } @@ -527,8 +527,7 @@ void RenderListBox::valueChanged(Scrollbar*) if (newOffset != m_indexOffset) { m_indexOffset = newOffset; repaint(); - // Fire the scroll DOM event. - node()->dispatchEvent(eventNames().scrollEvent, false, false); + node()->dispatchEvent(Event::create(eventNames().scrollEvent, false, false)); } } diff --git a/WebCore/rendering/RenderListBox.h b/WebCore/rendering/RenderListBox.h index e5454e5..aafb87e 100644 --- a/WebCore/rendering/RenderListBox.h +++ b/WebCore/rendering/RenderListBox.h @@ -68,7 +68,7 @@ private: virtual bool isPointInOverflowControl(HitTestResult&, int x, int y, int tx, int ty); - virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1.0f); + virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1.0f, Node** stopNode = 0); virtual void calcPrefWidths(); virtual int baselinePosition(bool firstLine, bool isRootLineBox) const; diff --git a/WebCore/rendering/RenderListItem.cpp b/WebCore/rendering/RenderListItem.cpp index 374ef66..e487c60 100644 --- a/WebCore/rendering/RenderListItem.cpp +++ b/WebCore/rendering/RenderListItem.cpp @@ -247,21 +247,30 @@ void RenderListItem::positionListMarker() int markerXPos; RootInlineBox* root = m_marker->inlineBoxWrapper()->root(); + // FIXME: Inline flows in the line box hierarchy that have self-painting layers should act as cutoff points + // and really shouldn't keep propagating overflow up. This won't really break anything other than repainting + // not being as tight as it could be though. if (style()->direction() == LTR) { int leftLineOffset = leftRelOffset(yOffset, leftOffset(yOffset, false), false); markerXPos = leftLineOffset - xOffset - paddingLeft() - borderLeft() + m_marker->marginLeft(); m_marker->inlineBoxWrapper()->adjustPosition(markerXPos - markerOldX, 0); - if (markerXPos < root->leftOverflow()) { - root->setHorizontalOverflowPositions(markerXPos, root->rightOverflow()); - adjustOverflow = true; + for (InlineFlowBox* box = m_marker->inlineBoxWrapper()->parent(); box; box = box->parent()) { + if (markerXPos < box->leftLayoutOverflow()) { + box->setHorizontalOverflowPositions(markerXPos, box->rightLayoutOverflow(), box->leftVisualOverflow(), box->rightVisualOverflow()); + if (box == root) + adjustOverflow = true; + } } } else { int rightLineOffset = rightRelOffset(yOffset, rightOffset(yOffset, false), false); markerXPos = rightLineOffset - xOffset + paddingRight() + borderRight() + m_marker->marginLeft(); m_marker->inlineBoxWrapper()->adjustPosition(markerXPos - markerOldX, 0); - if (markerXPos + m_marker->width() > root->rightOverflow()) { - root->setHorizontalOverflowPositions(root->leftOverflow(), markerXPos + m_marker->width()); - adjustOverflow = true; + for (InlineFlowBox* box = m_marker->inlineBoxWrapper()->parent(); box; box = box->parent()) { + if (markerXPos + m_marker->width() > box->rightLayoutOverflow()) { + box->setHorizontalOverflowPositions(box->leftLayoutOverflow(), markerXPos + m_marker->width(), box->leftVisualOverflow(), box->rightVisualOverflow()); + if (box == root) + adjustOverflow = true; + } } } @@ -271,9 +280,9 @@ void RenderListItem::positionListMarker() do { o = o->parentBox(); if (o->isRenderBlock()) - toRenderBlock(o)->addVisualOverflow(markerRect); + toRenderBlock(o)->addLayoutOverflow(markerRect); markerRect.move(-o->x(), -o->y()); - } while (o != this); + } while (o != this && !o->hasSelfPaintingLayer()); } } } diff --git a/WebCore/rendering/RenderListItem.h b/WebCore/rendering/RenderListItem.h index 21544f9..c4c41dc 100644 --- a/WebCore/rendering/RenderListItem.h +++ b/WebCore/rendering/RenderListItem.h @@ -44,6 +44,8 @@ public: void setNotInList(bool notInList) { m_notInList = notInList; } bool notInList() const { return m_notInList; } + const String& markerText() const; + private: virtual const char* renderName() const { return "RenderListItem"; } @@ -59,8 +61,6 @@ private: virtual void positionListMarker(); - const String& markerText() const; - virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); void updateMarkerLocation(); diff --git a/WebCore/rendering/RenderMarquee.cpp b/WebCore/rendering/RenderMarquee.cpp index 31a8305..bb917f8 100644 --- a/WebCore/rendering/RenderMarquee.cpp +++ b/WebCore/rendering/RenderMarquee.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * * Portions are Copyright (C) 1998 Netscape Communications Corporation. * @@ -152,7 +153,11 @@ int RenderMarquee::computePosition(EMarqueeDirection dir, bool stopAtContentEdge void RenderMarquee::start() { - if (m_timer.isActive() || m_layer->renderer()->style()->marqueeIncrement().isZero()) + if (m_timer.isActive() || m_layer->renderer()->style()->marqueeIncrement().isZero() +#if ENABLE(WCSS) && ENABLE(XHTMLMP) + || (m_layer->renderer()->document()->isXHTMLMPDocument() && !m_layer->renderer()->style()->marqueeLoopCount()) +#endif + ) return; // We may end up propagating a scroll event. It is important that we suspend events until diff --git a/WebCore/rendering/RenderMedia.cpp b/WebCore/rendering/RenderMedia.cpp index b87e99d..1da2628 100644 --- a/WebCore/rendering/RenderMedia.cpp +++ b/WebCore/rendering/RenderMedia.cpp @@ -33,6 +33,7 @@ #include "HTMLNames.h" #include "MediaControlElements.h" #include "MouseEvent.h" +#include "RenderTheme.h" #include <wtf/CurrentTime.h> #include <wtf/MathExtras.h> @@ -132,6 +133,10 @@ void RenderMedia::styleDidChange(StyleDifference diff, const RenderStyle* oldSty m_currentTimeDisplay->updateStyle(); if (m_timeRemainingDisplay) m_timeRemainingDisplay->updateStyle(); + if (m_volumeSliderContainer) + m_volumeSliderContainer->updateStyle(); + if (m_volumeSlider) + m_volumeSlider->updateStyle(); } } @@ -240,6 +245,22 @@ void RenderMedia::createTimeline() m_timeline->attachToParent(m_timelineContainer.get()); } +void RenderMedia::createVolumeSliderContainer() +{ + ASSERT(!m_volumeSliderContainer); + m_volumeSliderContainer = new MediaControlVolumeSliderContainerElement(document(), mediaElement()); + m_volumeSliderContainer->attachToParent(m_panel.get()); +} + +void RenderMedia::createVolumeSlider() +{ + ASSERT(!m_volumeSlider); + m_volumeSlider = new MediaControlVolumeSliderElement(document(), mediaElement()); + m_volumeSlider->setAttribute(precisionAttr, "float"); + m_volumeSlider->setAttribute(maxAttr, "1"); + m_volumeSlider->attachToParent(m_volumeSliderContainer.get()); +} + void RenderMedia::createCurrentTimeDisplay() { ASSERT(!m_currentTimeDisplay); @@ -285,6 +306,8 @@ void RenderMedia::updateControls() m_currentTimeDisplay = 0; m_timeRemainingDisplay = 0; m_fullscreenButton = 0; + m_volumeSliderContainer = 0; + m_volumeSlider = 0; m_controlsShadowRoot = 0; } m_opacityAnimationTo = 1.0f; @@ -298,19 +321,22 @@ void RenderMedia::updateControls() createPanel(); if (m_panel) { createRewindButton(); - createMuteButton(); createPlayButton(); createReturnToRealtimeButton(); createStatusDisplay(); createTimelineContainer(); - createSeekBackButton(); - createSeekForwardButton(); - createFullscreenButton(); if (m_timelineContainer) { createCurrentTimeDisplay(); createTimeline(); createTimeRemainingDisplay(); } + createSeekBackButton(); + createSeekForwardButton(); + createFullscreenButton(); + createMuteButton(); + createVolumeSliderContainer(); + if (m_volumeSliderContainer) + createVolumeSlider(); m_panel->attach(); } } @@ -336,6 +362,8 @@ void RenderMedia::updateControls() m_playButton->update(); if (m_timelineContainer) m_timelineContainer->update(); + if (m_volumeSliderContainer) + m_volumeSliderContainer->update(); if (m_timeline) m_timeline->update(); if (m_currentTimeDisplay) @@ -354,6 +382,8 @@ void RenderMedia::updateControls() m_statusDisplay->update(); if (m_fullscreenButton) m_fullscreenButton->update(); + if (m_volumeSlider) + m_volumeSlider->update(); updateTimeDisplay(); updateControlVisibility(); @@ -366,24 +396,6 @@ void RenderMedia::timeUpdateTimerFired(Timer<RenderMedia>*) updateTimeDisplay(); } -String RenderMedia::formatTime(float time) -{ - if (!isfinite(time)) - time = 0; - int seconds = (int)fabsf(time); - int hours = seconds / (60 * 60); - int minutes = (seconds / 60) % 60; - seconds %= 60; - if (hours) { - if (hours > 9) - return String::format("%s%02d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds); - else - return String::format("%s%01d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds); - } - else - return String::format("%s%02d:%02d", (time < 0 ? "-" : ""), minutes, seconds); -} - void RenderMedia::updateTimeDisplay() { if (!m_currentTimeDisplay || !m_currentTimeDisplay->renderer() || m_currentTimeDisplay->renderer()->style()->display() == NONE || style()->visibility() != VISIBLE) @@ -391,12 +403,8 @@ void RenderMedia::updateTimeDisplay() float now = mediaElement()->currentTime(); float duration = mediaElement()->duration(); - String timeString = formatTime(now); - ExceptionCode ec; - m_currentTimeDisplay->setInnerText(timeString, ec); - - timeString = formatTime(now - duration); - m_timeRemainingDisplay->setInnerText(timeString, ec); + m_currentTimeDisplay->setCurrentValue(now); + m_timeRemainingDisplay->setCurrentValue(now - duration); } void RenderMedia::updateControlVisibility() @@ -463,13 +471,53 @@ void RenderMedia::opacityAnimationTimerFired(Timer<RenderMedia>*) changeOpacity(m_panel.get(), opacity); } +void RenderMedia::updateVolumeSliderContainer(bool visible) +{ + if (!mediaElement()->hasAudio() || !m_volumeSliderContainer || !m_volumeSlider) + return; + + if (visible && !m_volumeSliderContainer->isVisible()) { + if (!m_muteButton || !m_muteButton->renderer() || !m_muteButton->renderBox()) + return; + + RefPtr<RenderStyle> s = m_volumeSliderContainer->styleForElement(); + int height = s->height().isPercent() ? 0 : s->height().value(); + int x = m_muteButton->renderBox()->offsetLeft(); + int y = m_muteButton->renderBox()->offsetTop() - height; + FloatPoint absPoint = m_muteButton->renderer()->localToAbsolute(FloatPoint(x, y), true, true); + if (absPoint.y() < 0) + y = m_muteButton->renderBox()->offsetTop() + m_muteButton->renderBox()->height(); + m_volumeSliderContainer->setVisible(true); + m_volumeSliderContainer->setPosition(x, y); + m_volumeSliderContainer->update(); + m_volumeSlider->update(); + } else if (!visible && m_volumeSliderContainer->isVisible()) { + m_volumeSliderContainer->setVisible(false); + m_volumeSliderContainer->updateStyle(); + } +} + void RenderMedia::forwardEvent(Event* event) { if (event->isMouseEvent() && m_controlsShadowRoot) { MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); IntPoint point(mouseEvent->absoluteLocation()); - if (m_muteButton && m_muteButton->hitTest(point)) + bool showVolumeSlider = false; + if (m_muteButton && m_muteButton->hitTest(point)) { m_muteButton->defaultEventHandler(event); + if (event->type() != eventNames().mouseoutEvent) + showVolumeSlider = true; + } + + if (m_volumeSliderContainer && m_volumeSliderContainer->hitTest(point)) + showVolumeSlider = true; + + if (m_volumeSlider && m_volumeSlider->hitTest(point)) { + m_volumeSlider->defaultEventHandler(event); + showVolumeSlider = true; + } + + updateVolumeSliderContainer(showVolumeSlider); if (m_playButton && m_playButton->hitTest(point)) m_playButton->defaultEventHandler(event); diff --git a/WebCore/rendering/RenderMedia.h b/WebCore/rendering/RenderMedia.h index 5697bda..602cd26 100644 --- a/WebCore/rendering/RenderMedia.h +++ b/WebCore/rendering/RenderMedia.h @@ -41,10 +41,12 @@ class MediaControlSeekButtonElement; class MediaControlRewindButtonElement; class MediaControlReturnToRealtimeButtonElement; class MediaControlTimelineElement; +class MediaControlVolumeSliderElement; class MediaControlFullscreenButtonElement; class MediaControlTimeDisplayElement; class MediaControlStatusDisplayElement; class MediaControlTimelineContainerElement; +class MediaControlVolumeSliderContainerElement; class MediaControlElement; class MediaPlayer; @@ -60,8 +62,6 @@ public: HTMLMediaElement* mediaElement() const; MediaPlayer* player() const; - static String formatTime(float time); - bool shouldShowTimeDisplayControls() const; void updateFromElement(); @@ -99,6 +99,8 @@ private: void createStatusDisplay(); void createTimelineContainer(); void createTimeline(); + void createVolumeSliderContainer(); + void createVolumeSlider(); void createCurrentTimeDisplay(); void createTimeRemainingDisplay(); void createFullscreenButton(); @@ -109,6 +111,8 @@ private: void changeOpacity(HTMLElement*, float opacity); void opacityAnimationTimerFired(Timer<RenderMedia>*); + void updateVolumeSliderContainer(bool visible); + virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); RefPtr<HTMLElement> m_controlsShadowRoot; @@ -120,8 +124,10 @@ private: RefPtr<MediaControlRewindButtonElement> m_rewindButton; RefPtr<MediaControlReturnToRealtimeButtonElement> m_returnToRealtimeButton; RefPtr<MediaControlTimelineElement> m_timeline; + RefPtr<MediaControlVolumeSliderElement> m_volumeSlider; RefPtr<MediaControlFullscreenButtonElement> m_fullscreenButton; RefPtr<MediaControlTimelineContainerElement> m_timelineContainer; + RefPtr<MediaControlVolumeSliderContainerElement> m_volumeSliderContainer; RefPtr<MediaControlTimeDisplayElement> m_currentTimeDisplay; RefPtr<MediaControlTimeDisplayElement> m_timeRemainingDisplay; RefPtr<MediaControlStatusDisplayElement> m_statusDisplay; diff --git a/WebCore/rendering/RenderMediaControls.cpp b/WebCore/rendering/RenderMediaControls.cpp index 06d901a..4303aaa 100644 --- a/WebCore/rendering/RenderMediaControls.cpp +++ b/WebCore/rendering/RenderMediaControls.cpp @@ -82,16 +82,6 @@ void RenderMediaControls::adjustMediaSliderThumbSize(RenderObject* o) o->style()->setHeight(Length(static_cast<int>(mediaSliderThumbHeight * zoomLevel), Fixed)); } -static HTMLMediaElement* parentMediaElement(RenderObject* o) -{ - Node* node = o->node(); - Node* mediaNode = node ? node->shadowAncestorNode() : 0; - if (!mediaNode || (!mediaNode->hasTagName(HTMLNames::videoTag) && !mediaNode->hasTagName(HTMLNames::audioTag))) - return 0; - - return static_cast<HTMLMediaElement*>(mediaNode); -} - bool RenderMediaControls::paintMediaControlsPart(MediaControlElementType part, RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { ASSERT(SafariThemeLibrary()); @@ -110,8 +100,8 @@ bool RenderMediaControls::paintMediaControlsPart(MediaControlElementType part, R case MediaPauseButton: case MediaPlayButton: if (MediaControlPlayButtonElement* btn = static_cast<MediaControlPlayButtonElement*>(o->node())) { - bool currentlyPlaying = btn->displayType() == MediaPlayButton; - paintThemePart(currentlyPlaying ? SafariTheme::MediaPauseButtonPart : SafariTheme::MediaPlayButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o)); + bool canPlay = btn->displayType() == MediaPlayButton; + paintThemePart(canPlay ? SafariTheme::MediaPlayButtonPart : SafariTheme::MediaPauseButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o)); } break; case MediaSeekBackButton: @@ -121,13 +111,25 @@ bool RenderMediaControls::paintMediaControlsPart(MediaControlElementType part, R paintThemePart(SafariTheme::MediaSeekForwardButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o)); break; case MediaSlider: { - if (HTMLMediaElement* mediaElement = parentMediaElement(o)) + if (HTMLMediaElement* mediaElement = toParentMediaElement(o)) STPaintProgressIndicator(SafariTheme::MediaType, paintInfo.context->platformContext(), r, NSRegularControlSize, 0, mediaElement->percentLoaded()); break; } case MediaSliderThumb: paintThemePart(SafariTheme::MediaSliderThumbPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o)); break; + case MediaVolumeSliderContainer: + // FIXME: Implement volume slider. + ASSERT_NOT_REACHED(); + break; + case MediaVolumeSlider: + // FIXME: Implement volume slider. + ASSERT_NOT_REACHED(); + break; + case MediaVolumeSliderThumb: + // FIXME: Implement volume slider. + ASSERT_NOT_REACHED(); + break; case MediaTimelineContainer: ASSERT_NOT_REACHED(); break; @@ -147,4 +149,3 @@ bool RenderMediaControls::paintMediaControlsPart(MediaControlElementType part, R #endif // #if ENABLE(VIDEO) } // namespace WebCore - diff --git a/WebCore/rendering/RenderMediaControlsChromium.cpp b/WebCore/rendering/RenderMediaControlsChromium.cpp new file mode 100644 index 0000000..bba2fa2 --- /dev/null +++ b/WebCore/rendering/RenderMediaControlsChromium.cpp @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2009 Apple Inc. + * Copyright (C) 2009 Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "RenderMediaControlsChromium.h" + +#include "Gradient.h" +#include "GraphicsContext.h" +#include "HTMLMediaElement.h" +#include "HTMLNames.h" + +namespace WebCore { + +#if ENABLE(VIDEO) + +typedef WTF::HashMap<const char*, Image*> MediaControlImageMap; +static MediaControlImageMap* gMediaControlImageMap = 0; + +static Image* platformResource(const char* name) +{ + if (!gMediaControlImageMap) + gMediaControlImageMap = new MediaControlImageMap(); + if (Image* image = gMediaControlImageMap->get(name)) + return image; + if (Image* image = Image::loadPlatformResource(name).releaseRef()) { + gMediaControlImageMap->set(name, image); + return image; + } + ASSERT_NOT_REACHED(); + return 0; +} + +static bool paintMediaButton(GraphicsContext* context, const IntRect& rect, Image* image) +{ + // Create a destination rectangle for the image that is centered in the drawing rectangle, rounded left, and down. + IntRect imageRect = image->rect(); + imageRect.setY(rect.y() + (rect.height() - image->height() + 1) / 2); + imageRect.setX(rect.x() + (rect.width() - image->width() + 1) / 2); + + context->drawImage(image, imageRect); + return true; +} + +static bool paintMediaMuteButton(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) +{ + HTMLMediaElement* mediaElement = toParentMediaElement(object); + if (!mediaElement) + return false; + + static Image* soundFull = platformResource("mediaSoundFull"); + static Image* soundNone = platformResource("mediaSoundNone"); + static Image* soundDisabled = platformResource("mediaSoundDisabled"); + + if (mediaElement->networkState() == HTMLMediaElement::NETWORK_NO_SOURCE || !mediaElement->hasAudio()) + return paintMediaButton(paintInfo.context, rect, soundDisabled); + + return paintMediaButton(paintInfo.context, rect, mediaElement->muted() ? soundNone: soundFull); +} + +static bool paintMediaPlayButton(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) +{ + HTMLMediaElement* mediaElement = toParentMediaElement(object); + if (!mediaElement) + return false; + + static Image* mediaPlay = platformResource("mediaPlay"); + static Image* mediaPause = platformResource("mediaPause"); + static Image* mediaPlayDisabled = platformResource("mediaPlayDisabled"); + + if (mediaElement->networkState() == HTMLMediaElement::NETWORK_NO_SOURCE) + return paintMediaButton(paintInfo.context, rect, mediaPlayDisabled); + + return paintMediaButton(paintInfo.context, rect, mediaElement->paused() ? mediaPlay : mediaPause); +} + +static bool paintMediaSlider(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) +{ + HTMLMediaElement* mediaElement = toParentMediaElement(object); + if (!mediaElement) + return false; + + RenderStyle* style = object->style(); + GraphicsContext* context = paintInfo.context; + + // Draw the border of the time bar. + // FIXME: this should be a rounded rect but need to fix GraphicsContextSkia first. + // https://bugs.webkit.org/show_bug.cgi?id=30143 + context->save(); + context->setStrokeStyle(SolidStroke); + context->setStrokeColor(style->borderLeftColor()); + context->setStrokeThickness(style->borderLeftWidth()); + context->setFillColor(style->backgroundColor()); + context->drawRect(rect); + context->restore(); + + // Draw the buffered ranges. + // FIXME: Draw multiple ranges if there are multiple buffered ranges. + // FIXME: percentLoaded() doesn't always hit 1.0 so we're using round(). + IntRect bufferedRect = rect; + bufferedRect.inflate(-style->borderLeftWidth()); + bufferedRect.setWidth(round((bufferedRect.width() * mediaElement->percentLoaded()))); + + // Don't bother drawing an empty area. + if (!bufferedRect.isEmpty()) { + IntPoint sliderTopLeft = bufferedRect.location(); + IntPoint sliderTopRight = sliderTopLeft; + sliderTopRight.move(0, bufferedRect.height()); + + RefPtr<Gradient> gradient = Gradient::create(sliderTopLeft, sliderTopRight); + Color startColor = object->style()->color(); + gradient->addColorStop(0.0, startColor); + gradient->addColorStop(1.0, Color(startColor.red() / 2, startColor.green() / 2, startColor.blue() / 2, startColor.alpha())); + + context->save(); + context->setStrokeStyle(NoStroke); + context->setFillGradient(gradient); + context->drawRect(bufferedRect); + context->restore(); + } + + return true; +} + +static bool paintMediaSliderThumb(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) +{ + if (!object->parent()->isSlider()) + return false; + + static Image* mediaSliderThumb = platformResource("mediaSliderThumb"); + return paintMediaButton(paintInfo.context, rect, mediaSliderThumb); +} + +static bool paintMediaVolumeSlider(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) +{ + HTMLMediaElement* mediaElement = toParentMediaElement(object); + if (!mediaElement) + return false; + + GraphicsContext* context = paintInfo.context; + Color originalColor = context->strokeColor(); + if (originalColor != Color::white) + context->setStrokeColor(Color::white); + + int x = rect.x() + rect.width() / 2; + context->drawLine(IntPoint(x, rect.y()), IntPoint(x, rect.y() + rect.height())); + + if (originalColor != Color::white) + context->setStrokeColor(originalColor); + return true; +} + +static bool paintMediaVolumeSliderThumb(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) +{ + if (!object->parent()->isSlider()) + return false; + + static Image* mediaVolumeSliderThumb = platformResource("mediaVolumeSliderThumb"); + return paintMediaButton(paintInfo.context, rect, mediaVolumeSliderThumb); +} + +static bool paintMediaTimelineContainer(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) +{ + HTMLMediaElement* mediaElement = toParentMediaElement(object); + if (!mediaElement) + return false; + + if (!rect.isEmpty()) { + GraphicsContext* context = paintInfo.context; + Color originalColor = context->strokeColor(); + float originalThickness = context->strokeThickness(); + StrokeStyle originalStyle = context->strokeStyle(); + + context->setStrokeStyle(SolidStroke); + + // Draw the left border using CSS defined width and color. + context->setStrokeThickness(object->style()->borderLeftWidth()); + context->setStrokeColor(object->style()->borderLeftColor().rgb()); + context->drawLine(IntPoint(rect.x() + 1, rect.y()), + IntPoint(rect.x() + 1, rect.y() + rect.height())); + + // Draw the right border using CSS defined width and color. + context->setStrokeThickness(object->style()->borderRightWidth()); + context->setStrokeColor(object->style()->borderRightColor().rgb()); + context->drawLine(IntPoint(rect.x() + rect.width() - 1, rect.y()), + IntPoint(rect.x() + rect.width() - 1, rect.y() + rect.height())); + + context->setStrokeColor(originalColor); + context->setStrokeThickness(originalThickness); + context->setStrokeStyle(originalStyle); + } + return true; +} + +bool RenderMediaControlsChromium::shouldRenderMediaControlPart(ControlPart part, Element* e) +{ + UNUSED_PARAM(e); + + switch (part) { + case MediaMuteButtonPart: + case MediaPlayButtonPart: + case MediaSliderPart: + case MediaSliderThumbPart: + case MediaVolumeSliderContainerPart: + case MediaVolumeSliderPart: + case MediaVolumeSliderThumbPart: + case MediaControlsBackgroundPart: + case MediaCurrentTimePart: + case MediaTimeRemainingPart: + return true; + } + return false; +} + +bool RenderMediaControlsChromium::paintMediaControlsPart(MediaControlElementType part, RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) +{ + switch (part) { + case MediaMuteButton: + case MediaUnMuteButton: + return paintMediaMuteButton(object, paintInfo, rect); + case MediaPauseButton: + case MediaPlayButton: + return paintMediaPlayButton(object, paintInfo, rect); + case MediaSlider: + return paintMediaSlider(object, paintInfo, rect); + case MediaSliderThumb: + return paintMediaSliderThumb(object, paintInfo, rect); + case MediaVolumeSlider: + return paintMediaVolumeSlider(object, paintInfo, rect); + case MediaVolumeSliderThumb: + return paintMediaVolumeSliderThumb(object, paintInfo, rect); + case MediaTimelineContainer: + return paintMediaTimelineContainer(object, paintInfo, rect); + case MediaFullscreenButton: + case MediaSeekBackButton: + case MediaSeekForwardButton: + case MediaVolumeSliderContainer: + case MediaCurrentTimeDisplay: + case MediaTimeRemainingDisplay: + case MediaControlsPanel: + ASSERT_NOT_REACHED(); + break; + } + return false; +} + +void RenderMediaControlsChromium::adjustMediaSliderThumbSize(RenderObject* object) +{ + static Image* mediaSliderThumb = platformResource("mediaSliderThumb"); + static Image* mediaVolumeSliderThumb = platformResource("mediaVolumeSliderThumb"); + + Image* thumbImage = 0; + if (object->style()->appearance() == MediaSliderThumbPart) + thumbImage = mediaSliderThumb; + else if (object->style()->appearance() == MediaVolumeSliderThumbPart) + thumbImage = mediaVolumeSliderThumb; + + if (thumbImage) { + object->style()->setWidth(Length(thumbImage->width(), Fixed)); + object->style()->setHeight(Length(thumbImage->height(), Fixed)); + } +} + +#endif // #if ENABLE(VIDEO) + +} // namespace WebCore diff --git a/WebCore/rendering/RenderMediaControlsChromium.h b/WebCore/rendering/RenderMediaControlsChromium.h new file mode 100644 index 0000000..d6d986c --- /dev/null +++ b/WebCore/rendering/RenderMediaControlsChromium.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2009 Apple Inc. + * Copyright (C) 2009 Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RenderMediaControlsChromium_h +#define RenderMediaControlsChromium_h + +#include "RenderObject.h" +#include "MediaControlElements.h" + +namespace WebCore { + +class HTMLMediaElement; +class RenderMediaControlsChromium { +public: + static bool shouldRenderMediaControlPart(ControlPart, Element*); + static bool paintMediaControlsPart(MediaControlElementType, RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + static void adjustMediaSliderThumbSize(RenderObject*); +}; + +} // namespace WebCore + +#endif // RenderMediaControlsChromium_h diff --git a/WebCore/rendering/RenderMenuList.cpp b/WebCore/rendering/RenderMenuList.cpp index 9d2e7e0..cbbc7cb 100644 --- a/WebCore/rendering/RenderMenuList.cpp +++ b/WebCore/rendering/RenderMenuList.cpp @@ -292,7 +292,6 @@ void RenderMenuList::hidePopup() { if (m_popup) m_popup->hide(); - m_popupIsVisible = false; } void RenderMenuList::valueChanged(unsigned listIndex, bool fireOnChange) @@ -428,6 +427,11 @@ int RenderMenuList::selectedIndex() const return select->optionToListIndex(select->selectedIndex()); } +void RenderMenuList::popupDidHide() +{ + m_popupIsVisible = false; +} + bool RenderMenuList::itemIsSeparator(unsigned listIndex) const { SelectElement* select = toSelectElement(static_cast<Element*>(node())); diff --git a/WebCore/rendering/RenderMenuList.h b/WebCore/rendering/RenderMenuList.h index 5c18e9e..2d617c1 100644 --- a/WebCore/rendering/RenderMenuList.h +++ b/WebCore/rendering/RenderMenuList.h @@ -82,6 +82,7 @@ private: virtual int clientPaddingRight() const; virtual int listSize() const; virtual int selectedIndex() const; + virtual void popupDidHide(); virtual bool itemIsSeparator(unsigned listIndex) const; virtual bool itemIsLabel(unsigned listIndex) const; virtual bool itemIsSelected(unsigned listIndex) const; diff --git a/WebCore/rendering/RenderObject.cpp b/WebCore/rendering/RenderObject.cpp index 5137338..d83e4d0 100644 --- a/WebCore/rendering/RenderObject.cpp +++ b/WebCore/rendering/RenderObject.cpp @@ -4,6 +4,7 @@ * (C) 2000 Dirk Mueller (mueller@kde.org) * (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com) * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -46,6 +47,7 @@ #include "RenderTheme.h" #include "RenderView.h" #include "TransformState.h" +#include "htmlediting.h" #include <algorithm> #ifdef ANDROID_LAYOUT #include "Settings.h" @@ -145,6 +147,12 @@ RenderObject* RenderObject::createObject(Node* node, RenderStyle* style) o = new (arena) RenderTableCell(node); break; case TABLE_CAPTION: +#if ENABLE(WCSS) + // As per the section 17.1 of the spec WAP-239-WCSS-20011026-a.pdf, + // the marquee box inherits and extends the characteristics of the + // principal block box ([CSS2] section 9.2.1). + case WAP_MARQUEE: +#endif o = new (arena) RenderBlock(node); break; case BOX: @@ -200,7 +208,6 @@ RenderObject::RenderObject(Node* node) , m_selectionState(SelectionNone) , m_hasColumns(false) , m_cellWidthChanged(false) - , m_replacedHasOverflow(false) { #ifndef NDEBUG renderObjectCounter.increment(); @@ -621,6 +628,11 @@ RenderBlock* RenderObject::containingBlock() const // inline directly. if (o->style()->position() == RelativePosition && o->isInline() && !o->isReplaced()) return o->containingBlock(); +#if ENABLE(SVG) + if (o->isSVGForeignObject()) //foreignObject is the containing block for contents inside it + break; +#endif + o = o->parent(); } } else { @@ -653,10 +665,10 @@ static bool mustRepaintFillLayers(const RenderObject* renderer, const FillLayer* if (!layer->xPosition().isZero() || !layer->yPosition().isZero()) return true; - if (layer->isSizeSet()) { - if (layer->size().width().isPercent() || layer->size().height().isPercent()) + if (layer->size().type == SizeLength) { + if (layer->size().size.width().isPercent() || layer->size().size.height().isPercent()) return true; - } else if (img->usesImageContainerSize()) + } else if (layer->size().type == Contain || layer->size().type == Cover || img->usesImageContainerSize()) return true; return false; @@ -1365,6 +1377,7 @@ Color RenderObject::selectionForegroundColor() const return color; } +#if ENABLE(DRAG_SUPPORT) Node* RenderObject::draggableNode(bool dhtmlOK, bool uaOK, int x, int y, bool& dhtmlWillDrag) const { if (!dhtmlOK && !uaOK) @@ -1399,6 +1412,7 @@ Node* RenderObject::draggableNode(bool dhtmlOK, bool uaOK, int x, int y, bool& d } return 0; } +#endif // ENABLE(DRAG_SUPPORT) void RenderObject::selectionStartEnd(int& spos, int& epos) const { @@ -1612,15 +1626,20 @@ void RenderObject::styleDidChange(StyleDifference diff, const RenderStyle*) void RenderObject::updateFillImages(const FillLayer* oldLayers, const FillLayer* newLayers) { - // FIXME: This will be slow when a large number of images is used. Fix by using a dict. - for (const FillLayer* currOld = oldLayers; currOld; currOld = currOld->next()) { - if (currOld->image() && (!newLayers || !newLayers->containsImage(currOld->image()))) - currOld->image()->removeClient(this); - } + // Optimize the common case + if (oldLayers && !oldLayers->next() && newLayers && !newLayers->next() && (oldLayers->image() == newLayers->image())) + return; + + // Go through the new layers and addClients first, to avoid removing all clients of an image. for (const FillLayer* currNew = newLayers; currNew; currNew = currNew->next()) { - if (currNew->image() && (!oldLayers || !oldLayers->containsImage(currNew->image()))) + if (currNew->image()) currNew->image()->addClient(this); } + + for (const FillLayer* currOld = oldLayers; currOld; currOld = currOld->next()) { + if (currOld->image()) + currOld->image()->removeClient(this); + } } void RenderObject::updateImage(StyleImage* oldImage, StyleImage* newImage) @@ -1739,6 +1758,23 @@ IntSize RenderObject::offsetFromContainer(RenderObject* o) const return offset; } +IntSize RenderObject::offsetFromAncestorContainer(RenderObject* container) const +{ + IntSize offset; + const RenderObject* currContainer = this; + do { + RenderObject* nextContainer = currContainer->container(); + ASSERT(nextContainer); // This means we reached the top without finding container. + if (!nextContainer) + break; + ASSERT(!currContainer->hasTransform()); + offset += currContainer->offsetFromContainer(nextContainer); + currContainer = nextContainer; + } while (currContainer != container); + + return offset; +} + IntRect RenderObject::localCaretRect(InlineBox*, int, int* extraWidthToEndOfLine) { if (extraWidthToEndOfLine) @@ -1772,8 +1808,11 @@ bool RenderObject::hasOutlineAnnotation() const return node() && node()->isLink() && document()->printing(); } -RenderObject* RenderObject::container() const +RenderObject* RenderObject::container(RenderBoxModelObject* repaintContainer, bool* repaintContainerSkipped) const { + if (repaintContainerSkipped) + *repaintContainerSkipped = false; + // This method is extremely similar to containingBlock(), but with a few notable // exceptions. // (1) It can be used on orphaned subtrees, i.e., it can be called safely even when @@ -1798,14 +1837,20 @@ RenderObject* RenderObject::container() const // we'll just return 0). // FIXME: The definition of view() has changed to not crawl up the render tree. It might // be safe now to use it. - while (o && o->parent() && !(o->hasTransform() && o->isRenderBlock())) + while (o && o->parent() && !(o->hasTransform() && o->isRenderBlock())) { + if (repaintContainerSkipped && o == repaintContainer) + *repaintContainerSkipped = true; o = o->parent(); + } } else if (pos == AbsolutePosition) { // Same goes here. We technically just want our containing block, but // we may not have one if we're part of an uninstalled subtree. We'll // climb as high as we can though. - while (o && o->style()->position() == StaticPosition && !o->isRenderView() && !(o->hasTransform() && o->isRenderBlock())) + while (o && o->style()->position() == StaticPosition && !o->isRenderView() && !(o->hasTransform() && o->isRenderBlock())) { + if (repaintContainerSkipped && o == repaintContainer) + *repaintContainerSkipped = true; o = o->parent(); + } } return o; @@ -1825,7 +1870,12 @@ void RenderObject::destroy() children->destroyLeftoverChildren(); // If this renderer is being autoscrolled, stop the autoscroll timer - if (document()->frame()->eventHandler()->autoscrollRenderer() == this) + + // FIXME: RenderObject::destroy should not get called with a renderar whose document + // has a null frame, so we assert this. However, we don't want release builds to crash which is why we + // check that the frame is not null. + ASSERT(document()->frame()); + if (document()->frame() && document()->frame()->eventHandler()->autoscrollRenderer() == this) document()->frame()->eventHandler()->stopAutoscrollTimer(true); if (m_hasCounterNodeMap) diff --git a/WebCore/rendering/RenderObject.h b/WebCore/rendering/RenderObject.h index 911169d..e358c98 100644 --- a/WebCore/rendering/RenderObject.h +++ b/WebCore/rendering/RenderObject.h @@ -278,6 +278,7 @@ public: virtual bool isTextField() const { return false; } virtual bool isVideo() const { return false; } virtual bool isWidget() const { return false; } + virtual bool isCanvas() const { return false; } bool isRoot() const { return document()->documentElement() == m_node; } bool isBody() const; @@ -285,6 +286,9 @@ public: bool isHTMLMarquee() const; + inline bool isAfterContent() const; + static inline bool isAfterContent(const RenderObject* obj) { return obj && obj->isAfterContent(); } + bool childrenInline() const { return m_childrenInline; } void setChildrenInline(bool b = true) { m_childrenInline = b; } bool hasColumns() const { return m_hasColumns; } @@ -301,6 +305,7 @@ public: virtual bool isRenderPath() const { return false; } virtual bool isSVGText() const { return false; } virtual bool isSVGImage() const { return false; } + virtual bool isSVGForeignObject() const { return false; } // Per SVG 1.1 objectBoundingBox ignores clipping, masking, filter effects, opacity and stroke-width. // This is used for all computation of objectBoundingBox relative units and by SVGLocateable::getBBox(). @@ -398,11 +403,11 @@ public: bool hasOutlineAnnotation() const; bool hasOutline() const { return style()->hasOutline() || hasOutlineAnnotation(); } - /** - * returns the object containing this one. can be different from parent for - * positioned elements - */ - RenderObject* container() const; + // Returns the object containing this one. Can be different from parent for positioned elements. + // If repaintContainer and repaintContainerSkipped are not null, on return *repaintContainerSkipped + // is true if the renderer returned is an ancestor of repaintContainer. + RenderObject* container(RenderBoxModelObject* repaintContainer = 0, bool* repaintContainerSkipped = 0) const; + virtual RenderObject* hoverAncestor() const { return parent(); } // IE Extension that can be called on any RenderObject. See the implementation for the details. @@ -536,6 +541,8 @@ public: // Return the offset from the container() renderer (excluding transforms) virtual IntSize offsetFromContainer(RenderObject*) const; + // Return the offset from an object up the container() chain. Asserts that none of the intermediate objects have transforms. + IntSize offsetFromAncestorContainer(RenderObject*) const; virtual void absoluteRects(Vector<IntRect>&, int, int) { } // FIXME: useTransforms should go away eventually @@ -658,7 +665,9 @@ public: // Whether or not a given block needs to paint selection gaps. virtual bool shouldPaintSelectionGaps() const { return false; } +#if ENABLE(DRAG_SUPPORT) Node* draggableNode(bool dhtmlOK, bool uaOK, int x, int y, bool& dhtmlWillDrag) const; +#endif /** * Returns the local coordinates of the caret within this render object. @@ -734,9 +743,6 @@ public: return outlineBoundsForRepaint(0); } - bool replacedHasOverflow() const { return m_replacedHasOverflow; } - void setReplacedHasOverflow(bool b = true) { m_replacedHasOverflow = b; } - protected: // Overrides should call the superclass at the end virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle); @@ -845,9 +851,6 @@ private: // from RenderTableCell bool m_cellWidthChanged : 1; - // from RenderReplaced - bool m_replacedHasOverflow : 1; - private: // Store state between styleWillChange and styleDidChange static bool s_affectsParentBlock; @@ -858,6 +861,16 @@ inline bool RenderObject::documentBeingDestroyed() const return !document()->renderer(); } +inline bool RenderObject::isAfterContent() const +{ + if (style()->styleType() != AFTER) + return false; + // Text nodes don't have their own styles, so ignore the style on a text node. + if (isText() && !isBR()) + return false; + return true; +} + inline void RenderObject::setNeedsLayout(bool b, bool markParents) { bool alreadyNeededLayout = m_needsLayout; @@ -974,6 +987,42 @@ inline void makeMatrixRenderable(TransformationMatrix& matrix, bool has3DRenderi #endif } +inline int adjustForAbsoluteZoom(int value, RenderObject* renderer) +{ + float zoomFactor = renderer->style()->effectiveZoom(); + if (zoomFactor == 1) + return value; + // Needed because computeLengthInt truncates (rather than rounds) when scaling up. + if (zoomFactor > 1) + value++; + return static_cast<int>(value / zoomFactor); +} + +inline void adjustIntRectForAbsoluteZoom(IntRect& rect, RenderObject* renderer) +{ + rect.setX(adjustForAbsoluteZoom(rect.x(), renderer)); + rect.setY(adjustForAbsoluteZoom(rect.y(), renderer)); + rect.setWidth(adjustForAbsoluteZoom(rect.width(), renderer)); + rect.setHeight(adjustForAbsoluteZoom(rect.height(), renderer)); +} + +inline FloatPoint adjustFloatPointForAbsoluteZoom(const FloatPoint& point, RenderObject* renderer) +{ + // The result here is in floats, so we don't need the truncation hack from the integer version above. + float zoomFactor = renderer->style()->effectiveZoom(); + if (zoomFactor == 1) + return point; + return FloatPoint(point.x() / zoomFactor, point.y() / zoomFactor); +} + +inline void adjustFloatQuadForAbsoluteZoom(FloatQuad& quad, RenderObject* renderer) +{ + quad.setP1(adjustFloatPointForAbsoluteZoom(quad.p1(), renderer)); + quad.setP2(adjustFloatPointForAbsoluteZoom(quad.p2(), renderer)); + quad.setP3(adjustFloatPointForAbsoluteZoom(quad.p3(), renderer)); + quad.setP4(adjustFloatPointForAbsoluteZoom(quad.p4(), renderer)); +} + } // namespace WebCore #ifndef NDEBUG diff --git a/WebCore/rendering/RenderOverflow.h b/WebCore/rendering/RenderOverflow.h new file mode 100644 index 0000000..ed8976a --- /dev/null +++ b/WebCore/rendering/RenderOverflow.h @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef RenderOverflow_h +#define RenderOverflow_h + +#include "IntRect.h" + +namespace WebCore +{ +// RenderOverflow is a class for tracking content that spills out of a box. This class is used by RenderBox and +// InlineFlowBox. +// +// There are two types of overflow: layout overflow (which is expected to be reachable via scrolling mechanisms) and +// visual overflow (which is not expected to be reachable via scrolling mechanisms). +// +// Layout overflow examples include other boxes that spill out of our box, For example, in the inline case a tall image +// could spill out of a line box. + +// Examples of visual overflow are shadows, text stroke (and eventually outline and border-image). + +// This object is allocated only when some of these fields have non-default values in the owning box. +class RenderOverflow { +public: + RenderOverflow(const IntRect& defaultRect = IntRect()) + : m_topLayoutOverflow(defaultRect.y()) + , m_bottomLayoutOverflow(defaultRect.bottom()) + , m_leftLayoutOverflow(defaultRect.x()) + , m_rightLayoutOverflow(defaultRect.right()) + , m_topVisualOverflow(defaultRect.y()) + , m_bottomVisualOverflow(defaultRect.bottom()) + , m_leftVisualOverflow(defaultRect.x()) + , m_rightVisualOverflow(defaultRect.right()) + { + } + + int topLayoutOverflow() const { return m_topLayoutOverflow; } + int bottomLayoutOverflow() const { return m_bottomLayoutOverflow; } + int leftLayoutOverflow() const { return m_leftLayoutOverflow; } + int rightLayoutOverflow() const { return m_rightLayoutOverflow; } + IntRect layoutOverflowRect() const; + + int topVisualOverflow() const { return m_topVisualOverflow; } + int bottomVisualOverflow() const { return m_bottomVisualOverflow; } + int leftVisualOverflow() const { return m_leftVisualOverflow; } + int rightVisualOverflow() const { return m_rightVisualOverflow; } + IntRect visualOverflowRect() const; + + IntRect visibleOverflowRect() const; + + void setTopLayoutOverflow(int overflow) { m_topLayoutOverflow = overflow; } + void setBottomLayoutOverflow(int overflow) { m_bottomLayoutOverflow = overflow; } + void setLeftLayoutOverflow(int overflow) { m_leftLayoutOverflow = overflow; } + void setRightLayoutOverflow(int overflow) { m_rightLayoutOverflow = overflow; } + + void setTopVisualOverflow(int overflow) { m_topVisualOverflow = overflow; } + void setBottomVisualOverflow(int overflow) { m_bottomVisualOverflow = overflow; } + void setLeftVisualOverflow(int overflow) { m_leftVisualOverflow = overflow; } + void setRightVisualOverflow(int overflow) { m_rightVisualOverflow = overflow; } + + void move(int dx, int dy); + + void addLayoutOverflow(const IntRect&); + void addVisualOverflow(const IntRect&); + + void resetLayoutOverflow(const IntRect& defaultRect); + +private: + int m_topLayoutOverflow; + int m_bottomLayoutOverflow; + int m_leftLayoutOverflow; + int m_rightLayoutOverflow; + + int m_topVisualOverflow; + int m_bottomVisualOverflow; + int m_leftVisualOverflow; + int m_rightVisualOverflow; +}; + +inline IntRect RenderOverflow::layoutOverflowRect() const +{ + return IntRect(m_leftLayoutOverflow, m_topLayoutOverflow, m_rightLayoutOverflow - m_leftLayoutOverflow, m_bottomLayoutOverflow - m_topLayoutOverflow); +} + +inline IntRect RenderOverflow::visualOverflowRect() const +{ + return IntRect(m_leftVisualOverflow, m_topVisualOverflow, m_rightVisualOverflow - m_leftVisualOverflow, m_bottomVisualOverflow - m_topVisualOverflow); +} + +inline IntRect RenderOverflow::visibleOverflowRect() const +{ + IntRect combinedRect(layoutOverflowRect()); + combinedRect.unite(visualOverflowRect()); + return combinedRect; +} + +inline void RenderOverflow::move(int dx, int dy) +{ + m_topLayoutOverflow += dy; + m_bottomLayoutOverflow += dy; + m_leftLayoutOverflow += dx; + m_rightLayoutOverflow += dx; + + m_topVisualOverflow += dy; + m_bottomVisualOverflow += dy; + m_leftVisualOverflow += dx; + m_rightVisualOverflow += dx; +} + +inline void RenderOverflow::addLayoutOverflow(const IntRect& rect) +{ + m_topLayoutOverflow = std::min(rect.y(), m_topLayoutOverflow); + m_bottomLayoutOverflow = std::max(rect.bottom(), m_bottomLayoutOverflow); + m_leftLayoutOverflow = std::min(rect.x(), m_leftLayoutOverflow); + m_rightLayoutOverflow = std::max(rect.right(), m_rightLayoutOverflow); +} + +inline void RenderOverflow::addVisualOverflow(const IntRect& rect) +{ + m_topVisualOverflow = std::min(rect.y(), m_topVisualOverflow); + m_bottomVisualOverflow = std::max(rect.bottom(), m_bottomVisualOverflow); + m_leftVisualOverflow = std::min(rect.x(), m_leftVisualOverflow); + m_rightVisualOverflow = std::max(rect.right(), m_rightVisualOverflow); +} + +inline void RenderOverflow::resetLayoutOverflow(const IntRect& rect) +{ + m_topLayoutOverflow = rect.y(); + m_bottomLayoutOverflow = rect.bottom(); + m_leftLayoutOverflow = rect.x(); + m_rightLayoutOverflow = rect.right(); +} + +} // namespace WebCore + +#endif // RenderOverflow_h diff --git a/WebCore/rendering/RenderPartObject.cpp b/WebCore/rendering/RenderPartObject.cpp index 72298c6..cba341b 100644 --- a/WebCore/rendering/RenderPartObject.cpp +++ b/WebCore/rendering/RenderPartObject.cpp @@ -33,8 +33,8 @@ #include "HTMLParamElement.h" #include "MIMETypeRegistry.h" #include "Page.h" -#include "PluginData.h" #include "RenderView.h" +#include "RenderWidgetProtector.h" #include "Text.h" #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) @@ -90,25 +90,12 @@ static ClassIdToTypeMap* createClassIdToTypeMap() map->add("clsid:CFCDAA03-8BE4-11CF-B84B-0020AFBBCCFA", "audio/x-pn-realaudio-plugin"); map->add("clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B", "video/quicktime"); map->add("clsid:166B1BCA-3F9C-11CF-8075-444553540000", "application/x-director"); -#if ENABLE(ACTIVEX_TYPE_CONVERSION_WMPLAYER) map->add("clsid:6BF52A52-394A-11D3-B153-00C04F79FAA6", "application/x-mplayer2"); map->add("clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95", "application/x-mplayer2"); -#endif return map; } -static const String& activeXType() -{ - DEFINE_STATIC_LOCAL(String, activeXType, ("application/x-oleobject")); - return activeXType; -} - -static inline bool havePlugin(const PluginData* pluginData, const String& type) -{ - return pluginData && !type.isEmpty() && pluginData->supportsMimeType(type); -} - -static String serviceTypeForClassId(const String& classId, const PluginData* pluginData) +static String serviceTypeForClassId(const String& classId) { // Return early if classId is empty (since we won't do anything below). // Furthermore, if classId is null, calling get() below will crash. @@ -116,30 +103,7 @@ static String serviceTypeForClassId(const String& classId, const PluginData* plu return String(); static ClassIdToTypeMap* map = createClassIdToTypeMap(); - String type = map->get(classId); - - // If we do have a plug-in that supports generic ActiveX content and don't have a plug-in - // for the MIME type we came up with, ignore the MIME type we came up with and just use - // the ActiveX type. - if (havePlugin(pluginData, activeXType()) && !havePlugin(pluginData, type)) - return activeXType(); - - return type; -} - -static inline bool shouldUseEmbedDescendant(HTMLObjectElement* objectElement, const PluginData* pluginData) -{ -#if PLATFORM(MAC) - UNUSED_PARAM(objectElement); - UNUSED_PARAM(pluginData); - // On Mac, we always want to use the embed descendant. - return true; -#else - // If we have both an <object> and <embed>, we always want to use the <embed> except when we have - // an ActiveX plug-in and plan to use it. - return !(havePlugin(pluginData, activeXType()) - && serviceTypeForClassId(objectElement->classId(), pluginData) == activeXType()); -#endif + return map->get(classId); } static void mapDataParamToSrc(Vector<String>* paramNames, Vector<String>* paramValues) @@ -168,6 +132,12 @@ void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins) Vector<String> paramValues; Frame* frame = frameView()->frame(); + // The calls to FrameLoader::requestObject within this function can result in a plug-in being initialized. + // This can run cause arbitrary JavaScript to run and may result in this RenderObject being detached from + // the render tree and destroyed, causing a crash like <rdar://problem/6954546>. By extending our lifetime + // artifically to ensure that we remain alive for the duration of plug-in initialization. + RenderWidgetProtector protector(this); + if (node()->hasTagName(objectTag)) { HTMLObjectElement* o = static_cast<HTMLObjectElement*>(node()); @@ -177,17 +147,14 @@ void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins) // Check for a child EMBED tag. HTMLEmbedElement* embed = 0; - const PluginData* pluginData = frame->page()->pluginData(); - if (shouldUseEmbedDescendant(o, pluginData)) { - for (Node* child = o->firstChild(); child; ) { - if (child->hasTagName(embedTag)) { - embed = static_cast<HTMLEmbedElement*>(child); - break; - } else if (child->hasTagName(objectTag)) - child = child->nextSibling(); // Don't descend into nested OBJECT tags - else - child = child->traverseNextNode(o); // Otherwise descend (EMBEDs may be inside COMMENT tags) - } + for (Node* child = o->firstChild(); child; ) { + if (child->hasTagName(embedTag)) { + embed = static_cast<HTMLEmbedElement*>(child); + break; + } else if (child->hasTagName(objectTag)) + child = child->nextSibling(); // Don't descend into nested OBJECT tags + else + child = child->traverseNextNode(o); // Otherwise descend (EMBEDs may be inside COMMENT tags) } // Use the attributes from the EMBED tag instead of the OBJECT tag including WIDTH and HEIGHT. @@ -260,7 +227,7 @@ void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins) // If we still don't have a type, try to map from a specific CLASSID to a type. if (serviceType.isEmpty()) - serviceType = serviceTypeForClassId(o->classId(), pluginData); + serviceType = serviceTypeForClassId(o->classId()); if (!isURLAllowed(document(), url)) return; @@ -282,7 +249,8 @@ void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins) return; } - bool success = frame->loader()->requestObject(this, url, AtomicString(o->name()), serviceType, paramNames, paramValues); + bool success = o->dispatchBeforeLoadEvent(url) && + frame->loader()->requestObject(this, url, o->getAttribute(nameAttr), serviceType, paramNames, paramValues); if (!success && m_hasFallbackContent) o->renderFallbackContent(); } else if (node()->hasTagName(embedTag)) { @@ -316,7 +284,8 @@ void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins) } - frame->loader()->requestObject(this, url, o->getAttribute(nameAttr), serviceType, paramNames, paramValues); + if (o->dispatchBeforeLoadEvent(url)) + frame->loader()->requestObject(this, url, o->getAttribute(nameAttr), serviceType, paramNames, paramValues); } #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) else if (node()->hasTagName(videoTag) || node()->hasTagName(audioTag)) { @@ -339,7 +308,9 @@ void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins) } serviceType = "application/x-media-element-proxy-plugin"; - frame->loader()->requestObject(this, url, nullAtom, serviceType, paramNames, paramValues); + + if (o->dispatchBeforeLoadEvent(url)) + frame->loader()->requestObject(this, url, nullAtom, serviceType, paramNames, paramValues); } #endif } @@ -425,12 +396,18 @@ void RenderPartObject::layout() #else calcWidth(); calcHeight(); +<<<<<<< HEAD:WebCore/rendering/RenderPartObject.cpp #endif adjustOverflowForBoxShadowAndReflect(); +======= +>>>>>>> webkit.org at 49305:WebCore/rendering/RenderPartObject.cpp RenderPart::layout(); + m_overflow.clear(); + addShadowOverflow(); + if (!widget() && frameView()) frameView()->addWidgetToUpdate(this); diff --git a/WebCore/rendering/RenderReplaced.cpp b/WebCore/rendering/RenderReplaced.cpp index 692a66e..27d2e72 100644 --- a/WebCore/rendering/RenderReplaced.cpp +++ b/WebCore/rendering/RenderReplaced.cpp @@ -34,9 +34,6 @@ using namespace std; namespace WebCore { -typedef WTF::HashMap<const RenderReplaced*, IntRect> OverflowRectMap; -static OverflowRectMap* gOverflowRectMap = 0; - const int cDefaultWidth = 300; const int cDefaultHeight = 150; @@ -56,8 +53,6 @@ RenderReplaced::RenderReplaced(Node* node, const IntSize& intrinsicSize) RenderReplaced::~RenderReplaced() { - if (replacedHasOverflow()) - gOverflowRectMap->remove(this); } void RenderReplaced::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) @@ -66,7 +61,7 @@ void RenderReplaced::styleDidChange(StyleDifference diff, const RenderStyle* old bool hadStyle = (oldStyle != 0); float oldZoom = hadStyle ? oldStyle->effectiveZoom() : RenderStyle::initialZoom(); - if (hadStyle && style() && style()->effectiveZoom() != oldZoom) + if (style() && style()->effectiveZoom() != oldZoom) intrinsicSizeChanged(); } @@ -77,10 +72,12 @@ void RenderReplaced::layout() LayoutRepainter repainter(*this, checkForRepaintDuringLayout()); setHeight(minimumReplacedHeight()); - + calcWidth(); calcHeight(); - adjustOverflowForBoxShadowAndReflect(); + + m_overflow.clear(); + addShadowOverflow(); repainter.repaintAfterLayout(); @@ -127,21 +124,29 @@ void RenderReplaced::paint(PaintInfo& paintInfo, int tx, int ty) drawSelectionTint = false; } + bool completelyClippedOut = false; if (style()->hasBorderRadius()) { - // Push a clip if we have a border radius, since we want to round the foreground content that gets painted. - paintInfo.context->save(); - - IntSize topLeft, topRight, bottomLeft, bottomRight; IntRect borderRect = IntRect(tx, ty, width(), height()); - style()->getBorderRadiiForRect(borderRect, topLeft, topRight, bottomLeft, bottomRight); - paintInfo.context->addRoundedRectClip(borderRect, topLeft, topRight, bottomLeft, bottomRight); + if (borderRect.isEmpty()) + completelyClippedOut = true; + else { + // Push a clip if we have a border radius, since we want to round the foreground content that gets painted. + paintInfo.context->save(); + + IntSize topLeft, topRight, bottomLeft, bottomRight; + style()->getBorderRadiiForRect(borderRect, topLeft, topRight, bottomLeft, bottomRight); + + paintInfo.context->addRoundedRectClip(borderRect, topLeft, topRight, bottomLeft, bottomRight); + } } - paintReplaced(paintInfo, tx, ty); + if (!completelyClippedOut) { + paintReplaced(paintInfo, tx, ty); - if (style()->hasBorderRadius()) - paintInfo.context->restore(); + if (style()->hasBorderRadius()) + paintInfo.context->restore(); + } // The selection tint never gets clipped by border-radius rounding, since we want it to run right up to the edges of // surrounding content. @@ -169,8 +174,8 @@ bool RenderReplaced::shouldPaint(PaintInfo& paintInfo, int& tx, int& ty) int currentTY = ty + y(); // Early exit if the element touches the edges. - int top = currentTY + overflowTop(); - int bottom = currentTY + overflowHeight(); + int top = currentTY + topVisibleOverflow(); + int bottom = currentTY + bottomVisibleOverflow(); if (isSelected() && m_inlineBoxWrapper) { int selTop = ty + m_inlineBoxWrapper->root()->selectionTop(); int selBottom = ty + selTop + m_inlineBoxWrapper->root()->selectionHeight(); @@ -179,7 +184,7 @@ bool RenderReplaced::shouldPaint(PaintInfo& paintInfo, int& tx, int& ty) } int os = 2 * maximalOutlineSize(paintInfo.phase); - if (currentTX + overflowLeft() >= paintInfo.rect.right() + os || currentTX + overflowWidth() <= paintInfo.rect.x() - os) + if (currentTX + leftVisibleOverflow() >= paintInfo.rect.right() + os || currentTX + rightVisibleOverflow() <= paintInfo.rect.x() - os) return false; if (top >= paintInfo.rect.bottom() + os || bottom <= paintInfo.rect.y() - os) return false; @@ -231,8 +236,8 @@ VisiblePosition RenderReplaced::positionForPoint(const IntPoint& point) RootInlineBox* root = box->root(); - int top = root->topOverflow(); - int bottom = root->nextRootBox() ? root->nextRootBox()->topOverflow() : root->bottomOverflow(); + int top = root->lineTop(); + int bottom = root->nextRootBox() ? root->nextRootBox()->lineTop() : root->lineBottom(); if (point.y() + y() < top) return createVisiblePosition(caretMinOffset(), DOWNSTREAM); // coordinates are above @@ -327,82 +332,6 @@ void RenderReplaced::setIntrinsicSize(const IntSize& size) m_intrinsicSize = size; } -void RenderReplaced::adjustOverflowForBoxShadowAndReflect() -{ - IntRect overflow; - for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next) { - if (boxShadow->style == Inset) - continue; - IntRect shadow = borderBoxRect(); - shadow.move(boxShadow->x, boxShadow->y); - shadow.inflate(boxShadow->blur + boxShadow->spread); - overflow.unite(shadow); - } - - // Now that we have an overflow rect including shadow, let's make sure that - // the reflection (which can also include the shadow) is also included. - if (hasReflection()) { - if (overflow.isEmpty()) - overflow = borderBoxRect(); - overflow.unite(reflectedRect(overflow)); - } - - if (!overflow.isEmpty()) { - if (!gOverflowRectMap) - gOverflowRectMap = new OverflowRectMap(); - overflow.unite(borderBoxRect()); - gOverflowRectMap->set(this, overflow); - setReplacedHasOverflow(true); - } else if (replacedHasOverflow()) { - gOverflowRectMap->remove(this); - setReplacedHasOverflow(false); - } -} - -int RenderReplaced::overflowHeight(bool) const -{ - if (replacedHasOverflow()) { - IntRect *r = &gOverflowRectMap->find(this)->second; - return r->height() + r->y(); - } - - return height(); -} - -int RenderReplaced::overflowWidth(bool) const -{ - if (replacedHasOverflow()) { - IntRect *r = &gOverflowRectMap->find(this)->second; - return r->width() + r->x(); - } - - return width(); -} - -int RenderReplaced::overflowLeft(bool) const -{ - if (replacedHasOverflow()) - return gOverflowRectMap->get(this).x(); - - return 0; -} - -int RenderReplaced::overflowTop(bool) const -{ - if (replacedHasOverflow()) - return gOverflowRectMap->get(this).y(); - - return 0; -} - -IntRect RenderReplaced::overflowRect(bool) const -{ - if (replacedHasOverflow()) - return gOverflowRectMap->find(this)->second; - - return borderBoxRect(); -} - IntRect RenderReplaced::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) { if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent()) @@ -410,7 +339,7 @@ IntRect RenderReplaced::clippedOverflowRectForRepaint(RenderBoxModelObject* repa // The selectionRect can project outside of the overflowRect, so take their union // for repainting to avoid selection painting glitches. - IntRect r = unionRect(localSelectionRect(false), overflowRect(false)); + IntRect r = unionRect(localSelectionRect(false), visibleOverflowRect()); RenderView* v = view(); if (v) { diff --git a/WebCore/rendering/RenderReplaced.h b/WebCore/rendering/RenderReplaced.h index 70ad4f2..0ba6b8a 100644 --- a/WebCore/rendering/RenderReplaced.h +++ b/WebCore/rendering/RenderReplaced.h @@ -65,12 +65,6 @@ private: virtual void paint(PaintInfo&, int tx, int ty); virtual void paintReplaced(PaintInfo&, int /*tx*/, int /*ty*/) { } - virtual int overflowHeight(bool includeInterior = true) const; - virtual int overflowWidth(bool includeInterior = true) const; - virtual int overflowLeft(bool includeInterior = true) const; - virtual int overflowTop(bool includeInterior = true) const; - virtual IntRect overflowRect(bool includeInterior = true) const; - virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer); virtual unsigned caretMaxRenderedOffset() const; diff --git a/WebCore/rendering/RenderScrollbar.cpp b/WebCore/rendering/RenderScrollbar.cpp index b3c5369..63fce8d 100644 --- a/WebCore/rendering/RenderScrollbar.cpp +++ b/WebCore/rendering/RenderScrollbar.cpp @@ -40,6 +40,16 @@ RenderScrollbar::RenderScrollbar(ScrollbarClient* client, ScrollbarOrientation o : Scrollbar(client, orientation, RegularScrollbar, RenderScrollbarTheme::renderScrollbarTheme()) , m_owner(renderer) { + // FIXME: We need to do this because RenderScrollbar::styleChanged is called as soon as the scrollbar is created. + + // Update the scrollbar size. + updateScrollbarPart(ScrollbarBGPart); + RenderScrollbarPart* part = m_parts.get(ScrollbarBGPart); + if (!part) + return; + + part->layout(); + setFrameRect(IntRect(0, 0, part->width(), part->height())); } RenderScrollbar::~RenderScrollbar() diff --git a/WebCore/rendering/RenderScrollbarPart.cpp b/WebCore/rendering/RenderScrollbarPart.cpp index 0f29aeb..c83248a 100644 --- a/WebCore/rendering/RenderScrollbarPart.cpp +++ b/WebCore/rendering/RenderScrollbarPart.cpp @@ -27,6 +27,7 @@ #include "RenderScrollbarPart.h" #include "RenderScrollbar.h" #include "RenderScrollbarTheme.h" +#include "RenderView.h" using namespace std; @@ -51,9 +52,6 @@ void RenderScrollbarPart::layout() else layoutVerticalPart(); - m_overflowWidth = max(width(), m_overflowWidth); - m_overflowHeight = max(height(), m_overflowHeight); - setNeedsLayout(false); } @@ -143,8 +141,16 @@ void RenderScrollbarPart::imageChanged(WrappedImagePtr image, const IntRect* rec { if (m_scrollbar && m_part != NoPart) m_scrollbar->theme()->invalidatePart(m_scrollbar, m_part); - else + else { + if (FrameView* frameView = view()->frameView()) { + if (frameView->isFrameViewScrollCorner(this)) { + frameView->invalidateScrollCorner(); + return; + } + } + RenderBlock::imageChanged(image, rect); + } } void RenderScrollbarPart::paintIntoRect(GraphicsContext* graphicsContext, int tx, int ty, const IntRect& rect) @@ -153,8 +159,6 @@ void RenderScrollbarPart::paintIntoRect(GraphicsContext* graphicsContext, int tx setLocation(rect.x() - tx, rect.y() - ty); setWidth(rect.width()); setHeight(rect.height()); - setOverflowWidth(max(rect.width(), overflowWidth())); - setOverflowHeight(max(rect.height(), overflowHeight())); if (graphicsContext->paintingDisabled()) return; diff --git a/WebCore/rendering/RenderSlider.cpp b/WebCore/rendering/RenderSlider.cpp index 8a19d97..c8b60fd 100644 --- a/WebCore/rendering/RenderSlider.cpp +++ b/WebCore/rendering/RenderSlider.cpp @@ -54,7 +54,7 @@ static const int defaultTrackLength = 129; struct SliderRange { bool isIntegral; double minimum; - double maximum; + double maximum; // maximum must be >= minimum. explicit SliderRange(HTMLInputElement*); double clampValue(double value); @@ -84,12 +84,8 @@ SliderRange::SliderRange(HTMLInputElement* element) isIntegral = !equalIgnoringCase(element->getAttribute(precisionAttr), "float"); - // FIXME: This treats maximum strings that can't be parsed as 0, but perhaps 100 would be more appropriate. - const AtomicString& maxString = element->getAttribute(maxAttr); - maximum = maxString.isNull() ? 100.0 : maxString.toDouble(); - - // If the maximum is smaller, use it as the minimum. - minimum = min(element->getAttribute(minAttr).toDouble(), maximum); + maximum = element->rangeMaximum(); + minimum = element->rangeMinimum(); } double SliderRange::clampValue(double value) @@ -100,12 +96,14 @@ double SliderRange::clampValue(double value) double SliderRange::valueFromElement(HTMLInputElement* element, bool* wasClamped) { - String valueString = element->value(); - double oldValue = valueString.isNull() ? (minimum + maximum) / 2 : valueString.toDouble(); + double oldValue; + bool parseSuccess = HTMLInputElement::formStringToDouble(element->value(), &oldValue); + if (!parseSuccess) + oldValue = (minimum + maximum) / 2; double newValue = clampValue(oldValue); if (wasClamped) - *wasClamped = valueString.isNull() || newValue != oldValue; + *wasClamped = !parseSuccess || newValue != oldValue; return newValue; } @@ -285,6 +283,8 @@ PassRefPtr<RenderStyle> RenderSlider::createThumbStyle(const RenderStyle* parent style->setAppearance(SliderThumbHorizontalPart); else if (parentStyle->appearance() == MediaSliderPart) style->setAppearance(MediaSliderThumbPart); + else if (parentStyle->appearance() == MediaVolumeSliderPart) + style->setAppearance(MediaVolumeSliderThumbPart); return style.release(); } @@ -302,7 +302,7 @@ IntRect RenderSlider::thumbRect() double fraction = sliderPosition(static_cast<HTMLInputElement*>(node())); IntRect contentRect = contentBoxRect(); - if (style()->appearance() == SliderVerticalPart) { + if (style()->appearance() == SliderVerticalPart || style()->appearance() == MediaVolumeSliderPart) { thumbRect.setX(contentRect.x() + (contentRect.width() - thumbRect.width()) / 2); thumbRect.setY(contentRect.y() + static_cast<int>(nextafter((contentRect.height() - thumbRect.height()) + 1, 0) * (1 - fraction))); } else { @@ -340,8 +340,6 @@ void RenderSlider::layout() calcWidth(); calcHeight(); - IntRect overflowRect(IntPoint(), size()); - if (thumb) { if (oldSize != size()) thumb->setChildNeedsLayout(true, false); @@ -358,18 +356,9 @@ void RenderSlider::layout() thumb->repaintDuringLayoutIfMoved(oldThumbRect); statePusher.pop(); - - IntRect thumbOverflowRect = thumb->overflowRect(); - thumbOverflowRect.move(thumb->x(), thumb->y()); - overflowRect.unite(thumbOverflowRect); } - // FIXME: m_overflowWidth and m_overflowHeight should be renamed - // m_overflowRight and m_overflowBottom. - m_overflowLeft = overflowRect.x(); - m_overflowTop = overflowRect.y(); - m_overflowWidth = overflowRect.right(); - m_overflowHeight = overflowRect.bottom(); + addOverflowFromChild(thumb); repainter.repaintAfterLayout(); @@ -406,7 +395,7 @@ bool RenderSlider::mouseEventIsInThumb(MouseEvent* evt) return false; #if ENABLE(VIDEO) - if (style()->appearance() == MediaSliderPart) { + if (style()->appearance() == MediaSliderPart || style()->appearance() == MediaVolumeSliderPart) { MediaControlInputElement *sliderThumb = static_cast<MediaControlInputElement*>(m_thumb->renderer()->node()); return sliderThumb->hitTest(evt->absoluteLocation()); } @@ -438,7 +427,7 @@ void RenderSlider::setValueForPosition(int position) // Calculate the new value based on the position, and send it to the element. SliderRange range(element); double fraction = static_cast<double>(position) / trackSize(); - if (style()->appearance() == SliderVerticalPart) + if (style()->appearance() == SliderVerticalPart || style()->appearance() == MediaVolumeSliderPart) fraction = 1 - fraction; double value = range.clampValue(range.valueFromProportion(fraction)); element->setValueFromRenderer(String::number(value)); @@ -459,7 +448,7 @@ int RenderSlider::positionForOffset(const IntPoint& p) return 0; int position; - if (style()->appearance() == SliderVerticalPart) + if (style()->appearance() == SliderVerticalPart || style()->appearance() == MediaVolumeSliderPart) position = p.y() - m_thumb->renderBox()->height() / 2; else position = p.x() - m_thumb->renderBox()->width() / 2; @@ -472,7 +461,7 @@ int RenderSlider::currentPosition() ASSERT(m_thumb); ASSERT(m_thumb->renderer()); - if (style()->appearance() == SliderVerticalPart) + if (style()->appearance() == SliderVerticalPart || style()->appearance() == MediaVolumeSliderPart) return toRenderBox(m_thumb->renderer())->y() - contentBoxRect().y(); return toRenderBox(m_thumb->renderer())->x() - contentBoxRect().x(); } @@ -482,7 +471,7 @@ int RenderSlider::trackSize() ASSERT(m_thumb); ASSERT(m_thumb->renderer()); - if (style()->appearance() == SliderVerticalPart) + if (style()->appearance() == SliderVerticalPart || style()->appearance() == MediaVolumeSliderPart) return contentHeight() - m_thumb->renderBox()->height(); return contentWidth() - m_thumb->renderBox()->width(); } diff --git a/WebCore/rendering/RenderTable.cpp b/WebCore/rendering/RenderTable.cpp index 7599999..0acaa43 100644 --- a/WebCore/rendering/RenderTable.cpp +++ b/WebCore/rendering/RenderTable.cpp @@ -265,8 +265,8 @@ void RenderTable::layout() LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y())); setHeight(0); - m_overflowHeight = 0; - m_overflowTop = 0; + m_overflow.clear(); + initMaxMarginValues(); #ifdef ANDROID_LAYOUT @@ -354,9 +354,6 @@ void RenderTable::layout() if (m_caption) m_caption->layoutIfNeeded(); - m_overflowWidth = width() + (collapsing ? outerBorderRight() - borderRight() : 0); - m_overflowLeft = collapsing ? borderLeft() - outerBorderLeft() : 0; - // If any table section moved vertically, we will just repaint everything from that // section down (it is quite unlikely that any of the following sections // did not shift). @@ -372,10 +369,6 @@ void RenderTable::layout() m_caption->repaintDuringLayoutIfMoved(captionRect); setHeight(height() + m_caption->height() + m_caption->marginTop() + m_caption->marginBottom()); - m_overflowLeft = min(m_overflowLeft, m_caption->x() + m_caption->overflowLeft(false)); - m_overflowWidth = max(m_overflowWidth, m_caption->x() + m_caption->overflowWidth(false)); - m_overflowTop = min(m_overflowTop, m_caption->y() + m_caption->overflowTop(false)); - m_overflowHeight = max(m_overflowHeight, m_caption->y() + m_caption->overflowHeight(false)); if (height() != oldTableTop) { sectionMoved = true; @@ -421,15 +414,11 @@ void RenderTable::layout() while (section) { if (!sectionMoved && section->y() != height()) { sectionMoved = true; - movedSectionTop = min(height(), section->y()) + section->overflowTop(false); + movedSectionTop = min(height(), section->y()) + section->topVisibleOverflow(); } section->setLocation(bl, height()); setHeight(height() + section->height()); - m_overflowLeft = min(m_overflowLeft, section->x() + section->overflowLeft(false)); - m_overflowWidth = max(m_overflowWidth, section->x() + section->overflowWidth(false)); - m_overflowTop = min(m_overflowTop, section->y() + section->overflowTop(false)); - m_overflowHeight = max(m_overflowHeight, section->y() + section->overflowHeight(false)); section = sectionBelow(section); } @@ -443,37 +432,34 @@ void RenderTable::layout() m_caption->repaintDuringLayoutIfMoved(captionRect); setHeight(height() + m_caption->height() + m_caption->marginTop() + m_caption->marginBottom()); - m_overflowLeft = min(m_overflowLeft, m_caption->x() + m_caption->overflowLeft(false)); - m_overflowWidth = max(m_overflowWidth, m_caption->x() + m_caption->overflowWidth(false)); } if (isPositioned()) calcHeight(); - m_overflowHeight = max(m_overflowHeight, height()); - // table can be containing block of positioned elements. // FIXME: Only pass true if width or height changed. layoutPositionedObjects(true); - if (!hasOverflowClip()) { - int shadowLeft; - int shadowRight; - int shadowTop; - int shadowBottom; - style()->getBoxShadowExtent(shadowTop, shadowRight, shadowBottom, shadowLeft); - - m_overflowLeft = min(m_overflowLeft, shadowLeft); - m_overflowWidth = max(m_overflowWidth, width() + shadowRight); - m_overflowTop = min(m_overflowTop, shadowTop); - m_overflowHeight = max(m_overflowHeight, height() + shadowBottom); - - if (hasReflection()) { - IntRect reflection(reflectionBox()); - m_overflowTop = min(m_overflowTop, reflection.y()); - m_overflowHeight = max(m_overflowHeight, reflection.bottom()); - m_overflowLeft = min(m_overflowLeft, reflection.x()); - m_overflowHeight = max(m_overflowWidth, reflection.right()); + // Add overflow from borders. + int rightBorderOverflow = width() + (collapsing ? outerBorderRight() - borderRight() : 0); + int leftBorderOverflow = collapsing ? borderLeft() - outerBorderLeft() : 0; + int bottomBorderOverflow = height() + (collapsing ? outerBorderBottom() - borderBottom() : 0); + int topBorderOverflow = collapsing ? borderTop() - outerBorderTop() : 0; + addLayoutOverflow(IntRect(leftBorderOverflow, topBorderOverflow, rightBorderOverflow - leftBorderOverflow, bottomBorderOverflow - topBorderOverflow)); + + // Add visual overflow from box-shadow and reflections. + addShadowOverflow(); + + // Add overflow from our caption. + if (m_caption) + addOverflowFromChild(m_caption); + + // Add overflow from our sections. + for (RenderObject* child = firstChild(); child; child = child->nextSibling()) { + if (child->isTableSection()) { + RenderTableSection* section = toRenderTableSection(child); + addOverflowFromChild(section); } } @@ -482,7 +468,7 @@ void RenderTable::layout() bool didFullRepaint = repainter.repaintAfterLayout(); // Repaint with our new bounds if they are different from our old bounds. if (!didFullRepaint && sectionMoved) - repaintRectangle(IntRect(m_overflowLeft, movedSectionTop, m_overflowWidth - m_overflowLeft, m_overflowHeight - movedSectionTop)); + repaintRectangle(IntRect(leftVisibleOverflow(), movedSectionTop, rightVisibleOverflow() - leftVisibleOverflow(), bottomVisibleOverflow() - movedSectionTop)); setNeedsLayout(false); } @@ -503,9 +489,9 @@ void RenderTable::paint(PaintInfo& paintInfo, int tx, int ty) PaintPhase paintPhase = paintInfo.phase; int os = 2 * maximalOutlineSize(paintPhase); - if (ty + overflowTop(false) >= paintInfo.rect.bottom() + os || ty + overflowHeight(false) <= paintInfo.rect.y() - os) + if (ty + topVisibleOverflow() >= paintInfo.rect.bottom() + os || ty + bottomVisibleOverflow() <= paintInfo.rect.y() - os) return; - if (tx + overflowLeft(false) >= paintInfo.rect.right() + os || tx + overflowWidth(false) <= paintInfo.rect.x() - os) + if (tx + leftVisibleOverflow() >= paintInfo.rect.right() + os || tx + rightVisibleOverflow() <= paintInfo.rect.x() - os) return; bool pushedClip = pushContentsClip(paintInfo, tx, ty); diff --git a/WebCore/rendering/RenderTableCell.cpp b/WebCore/rendering/RenderTableCell.cpp index 8b7a068..8e0b613 100644 --- a/WebCore/rendering/RenderTableCell.cpp +++ b/WebCore/rendering/RenderTableCell.cpp @@ -207,9 +207,9 @@ IntRect RenderTableCell::clippedOverflowRectForRepaint(RenderBoxModelObject* rep right = max(right, below->borderHalfRight(true)); } } - left = max(left, -overflowLeft(false)); - top = max(top, -overflowTop(false)); - IntRect r(-left, - top, left + max(width() + right, overflowWidth(false)), top + max(height() + bottom, overflowHeight(false))); + left = max(left, -leftVisibleOverflow()); + top = max(top, -topVisibleOverflow()); + IntRect r(-left, - top, left + max(width() + right, rightVisibleOverflow()), top + max(height() + bottom, bottomVisibleOverflow())); if (RenderView* v = view()) { // FIXME: layoutDelta needs to be applied in parts before/after transforms and diff --git a/WebCore/rendering/RenderTableSection.cpp b/WebCore/rendering/RenderTableSection.cpp index 5d47357..1e087f6 100644 --- a/WebCore/rendering/RenderTableSection.cpp +++ b/WebCore/rendering/RenderTableSection.cpp @@ -55,10 +55,6 @@ RenderTableSection::RenderTableSection(Node* node) , m_outerBorderRight(0) , m_outerBorderTop(0) , m_outerBorderBottom(0) - , m_overflowLeft(0) - , m_overflowWidth(0) - , m_overflowTop(0) - , m_overflowHeight(0) , m_needsCellRecalc(false) , m_hasOverflowingCell(false) { @@ -501,10 +497,7 @@ int RenderTableSection::layoutRows(int toAdd) // Set the width of our section now. The rows will also be this width. setWidth(table()->contentWidth()); - m_overflowLeft = 0; - m_overflowWidth = width(); - m_overflowTop = 0; - m_overflowHeight = 0; + m_overflow.clear(); m_hasOverflowingCell = false; if (toAdd && totalRows && (m_rowPos[totalRows] || !nextSibling())) { @@ -705,12 +698,6 @@ int RenderTableSection::layoutRows(int toAdd) } else cell->setLocation(table()->columnPositions()[c] + hspacing, m_rowPos[rindx]); - m_overflowLeft = min(m_overflowLeft, cell->x() + cell->overflowLeft(false)); - m_overflowWidth = max(m_overflowWidth, cell->x() + cell->overflowWidth(false)); - m_overflowTop = min(m_overflowTop, cell->y() + cell->overflowTop(false)); - m_overflowHeight = max(m_overflowHeight, cell->y() + cell->overflowHeight(false)); - m_hasOverflowingCell |= cell->overflowLeft(false) || cell->overflowWidth(false) > cell->width() || cell->overflowTop(false) || cell->overflowHeight(false) > cell->height(); - // If the cell moved, we have to repaint it as well as any floating/positioned // descendants. An exception is if we need a layout. In this case, we know we're going to // repaint ourselves (and the cell) anyway. @@ -725,10 +712,23 @@ int RenderTableSection::layoutRows(int toAdd) ASSERT(!needsLayout()); + setHeight(m_rowPos[totalRows]); + + // Now that our height has been determined, add in overflow from cells. + for (int r = 0; r < totalRows; r++) { + for (int c = 0; c < nEffCols; c++) { + RenderTableCell* cell = cellAt(r, c).cell; + if (!cell) + continue; + if (r < totalRows - 1 && cell == cellAt(r + 1, c).cell) + continue; + addOverflowFromChild(cell); + } + } + m_hasOverflowingCell = m_overflow; + statePusher.pop(); - setHeight(m_rowPos[totalRows]); - m_overflowHeight = max(m_overflowHeight, height()); return height(); } diff --git a/WebCore/rendering/RenderTableSection.h b/WebCore/rendering/RenderTableSection.h index c0098bc..9f6d5ea 100644 --- a/WebCore/rendering/RenderTableSection.h +++ b/WebCore/rendering/RenderTableSection.h @@ -73,11 +73,6 @@ public: void appendColumn(int pos); void splitColumn(int pos, int newSize); - virtual int overflowWidth(bool includeInterior = true) const { return (!includeInterior && hasOverflowClip()) ? width() : m_overflowWidth; } - virtual int overflowLeft(bool includeInterior = true) const { return (!includeInterior && hasOverflowClip()) ? 0 : m_overflowLeft; } - virtual int overflowHeight(bool includeInterior = true) const { return (!includeInterior && hasOverflowClip()) ? height() : m_overflowHeight; } - virtual int overflowTop(bool includeInterior = true) const { return (!includeInterior && hasOverflowClip()) ? 0 : m_overflowTop; } - int calcOuterBorderTop() const; int calcOuterBorderBottom() const; int calcOuterBorderLeft(bool rtl) const; @@ -152,10 +147,6 @@ private: int m_outerBorderRight; int m_outerBorderTop; int m_outerBorderBottom; - int m_overflowLeft; - int m_overflowWidth; - int m_overflowTop; - int m_overflowHeight; bool m_needsCellRecalc; bool m_hasOverflowingCell; diff --git a/WebCore/rendering/RenderText.cpp b/WebCore/rendering/RenderText.cpp index ada3961..40c3d75 100644 --- a/WebCore/rendering/RenderText.cpp +++ b/WebCore/rendering/RenderText.cpp @@ -207,7 +207,7 @@ void RenderText::deleteTextBoxes() PassRefPtr<StringImpl> RenderText::originalText() const { Node* e = node(); - return e ? static_cast<Text*>(e)->string() : 0; + return e ? static_cast<Text*>(e)->dataImpl() : 0; } void RenderText::absoluteRects(Vector<IntRect>& rects, int tx, int ty) @@ -328,13 +328,13 @@ VisiblePosition RenderText::positionForPoint(const IntPoint& point) int offset; // FIXME: We should be able to roll these special cases into the general cases in the loop below. - if (firstTextBox() && point.y() < firstTextBox()->root()->bottomOverflow() && point.x() < firstTextBox()->m_x) { + if (firstTextBox() && point.y() < firstTextBox()->root()->lineBottom() && point.x() < firstTextBox()->m_x) { // at the y coordinate of the first line or above // and the x coordinate is to the left of the first text box left edge offset = firstTextBox()->offsetForPosition(point.x()); return createVisiblePosition(offset + firstTextBox()->start(), DOWNSTREAM); } - if (lastTextBox() && point.y() >= lastTextBox()->root()->topOverflow() && point.x() >= lastTextBox()->m_x + lastTextBox()->m_width) { + if (lastTextBox() && point.y() >= lastTextBox()->root()->lineTop() && point.x() >= lastTextBox()->m_x + lastTextBox()->m_width) { // at the y coordinate of the last line or below // and the x coordinate is to the right of the last text box right edge offset = lastTextBox()->offsetForPosition(point.x()); @@ -343,8 +343,8 @@ VisiblePosition RenderText::positionForPoint(const IntPoint& point) InlineTextBox* lastBoxAbove = 0; for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { - if (point.y() >= box->root()->topOverflow()) { - int bottom = box->root()->nextRootBox() ? box->root()->nextRootBox()->topOverflow() : box->root()->bottomOverflow(); + if (point.y() >= box->root()->lineTop()) { + int bottom = box->root()->nextRootBox() ? box->root()->nextRootBox()->lineTop() : box->root()->lineBottom(); if (point.y() < bottom) { offset = box->offsetForPosition(point.x()); @@ -387,8 +387,8 @@ IntRect RenderText::localCaretRect(InlineBox* inlineBox, int caretOffset, int* e InlineTextBox* box = static_cast<InlineTextBox*>(inlineBox); - int height = box->root()->bottomOverflow() - box->root()->topOverflow(); - int top = box->root()->topOverflow(); + int height = box->root()->lineBottom() - box->root()->lineTop(); + int top = box->root()->lineTop(); int left = box->positionForOffset(caretOffset); diff --git a/WebCore/rendering/RenderTextControl.cpp b/WebCore/rendering/RenderTextControl.cpp index 70b6518..bcb2455 100644 --- a/WebCore/rendering/RenderTextControl.cpp +++ b/WebCore/rendering/RenderTextControl.cpp @@ -67,8 +67,9 @@ static Color disabledTextColor(const Color& textColor, const Color& backgroundCo return disabledColor; } -RenderTextControl::RenderTextControl(Node* node) +RenderTextControl::RenderTextControl(Node* node, bool placeholderVisible) : RenderBlock(node) + , m_placeholderVisible(placeholderVisible) , m_edited(false) , m_userEdited(false) { @@ -92,14 +93,22 @@ void RenderTextControl::styleDidChange(StyleDifference diff, const RenderStyle* // Reset them now to avoid getting a spurious layout hint. textBlockRenderer->style()->setHeight(Length()); textBlockRenderer->style()->setWidth(Length()); - textBlockRenderer->setStyle(textBlockStyle); + setInnerTextStyle(textBlockStyle); + } + + setReplaced(isInline()); +} + +void RenderTextControl::setInnerTextStyle(PassRefPtr<RenderStyle> style) +{ + if (m_innerText) { + RefPtr<RenderStyle> textStyle = style; + m_innerText->renderer()->setStyle(textStyle); for (Node* n = m_innerText->firstChild(); n; n = n->traverseNextNode(m_innerText.get())) { if (n->renderer()) - n->renderer()->setStyle(textBlockStyle); + n->renderer()->setStyle(textStyle); } } - - setReplaced(isInline()); } static inline bool updateUserModifyProperty(Node* node, RenderStyle* style) @@ -173,7 +182,7 @@ void RenderTextControl::setInnerTextValue(const String& innerTextValue) frame->editor()->clearUndoRedoOperations(); if (AXObjectCache::accessibilityEnabled()) - document()->axObjectCache()->postNotification(this, "AXValueChanged", false); + document()->axObjectCache()->postNotification(this, AXObjectCache::AXValueChanged, false); } } @@ -507,7 +516,7 @@ void RenderTextControl::selectionChanged(bool userTriggered) if (Frame* frame = document()->frame()) { if (frame->selection()->isRange() && userTriggered) - node()->dispatchEvent(eventNames().selectEvent, true, false); + node()->dispatchEvent(Event::create(eventNames().selectEvent, true, false)); } } @@ -521,4 +530,18 @@ HTMLElement* RenderTextControl::innerTextElement() const return m_innerText.get(); } +void RenderTextControl::updatePlaceholderVisibility(bool placeholderShouldBeVisible, bool placeholderValueChanged) +{ + bool oldPlaceholderVisible = m_placeholderVisible; + m_placeholderVisible = placeholderShouldBeVisible; + if (oldPlaceholderVisible != m_placeholderVisible || placeholderValueChanged) { + // Sets the inner text style to the normal style or :placeholder style. + setInnerTextStyle(createInnerTextStyle(textBaseStyle())); + + // updateFromElement() of the subclasses updates the text content + // to the element's value(), placeholder(), or the empty string. + updateFromElement(); + } +} + } // namespace WebCore diff --git a/WebCore/rendering/RenderTextControl.h b/WebCore/rendering/RenderTextControl.h index c0fc343..cdd8716 100644 --- a/WebCore/rendering/RenderTextControl.h +++ b/WebCore/rendering/RenderTextControl.h @@ -56,8 +56,10 @@ public: VisiblePosition visiblePositionForIndex(int index); int indexForVisiblePosition(const VisiblePosition&); + void updatePlaceholderVisibility(bool, bool); + protected: - RenderTextControl(Node*); + RenderTextControl(Node*, bool); int scrollbarThickness() const; void adjustInnerTextStyle(const RenderStyle* startStyle, RenderStyle* textBlockStyle) const; @@ -76,6 +78,7 @@ protected: virtual void adjustControlHeightBasedOnLineHeight(int lineHeight) = 0; virtual void cacheSelection(int start, int end) = 0; virtual PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const = 0; + virtual RenderStyle* textBaseStyle() const = 0; virtual void updateFromElement(); virtual void calcHeight(); @@ -83,6 +86,8 @@ protected: friend class TextIterator; HTMLElement* innerTextElement() const; + bool m_placeholderVisible; + private: virtual const char* renderName() const { return "RenderTextControl"; } virtual bool isTextControl() const { return true; } @@ -92,6 +97,7 @@ private: virtual void removeLeftoverAnonymousBlock(RenderBlock*) { } virtual bool canHaveChildren() const { return false; } virtual bool avoidsFloats() const { return true; } + void setInnerTextStyle(PassRefPtr<RenderStyle>); virtual void addFocusRingRects(GraphicsContext*, int tx, int ty); diff --git a/WebCore/rendering/RenderTextControlMultiLine.cpp b/WebCore/rendering/RenderTextControlMultiLine.cpp index ac790e2..f1f60ab 100644 --- a/WebCore/rendering/RenderTextControlMultiLine.cpp +++ b/WebCore/rendering/RenderTextControlMultiLine.cpp @@ -22,18 +22,23 @@ #include "config.h" #include "RenderTextControlMultiLine.h" +#include "Event.h" #include "EventNames.h" #include "Frame.h" -#include "HitTestResult.h" +#include "HTMLNames.h" #include "HTMLTextAreaElement.h" +<<<<<<< HEAD:WebCore/rendering/RenderTextControlMultiLine.cpp #ifdef ANDROID_LAYOUT #include "Settings.h" #endif +======= +#include "HitTestResult.h" +>>>>>>> webkit.org at 49305:WebCore/rendering/RenderTextControlMultiLine.cpp namespace WebCore { -RenderTextControlMultiLine::RenderTextControlMultiLine(Node* node) - : RenderTextControl(node) +RenderTextControlMultiLine::RenderTextControlMultiLine(Node* node, bool placeholderVisible) + : RenderTextControl(node, placeholderVisible) { } @@ -46,16 +51,17 @@ RenderTextControlMultiLine::~RenderTextControlMultiLine() void RenderTextControlMultiLine::subtreeHasChanged() { RenderTextControl::subtreeHasChanged(); - static_cast<Element*>(node())->setFormControlValueMatchesRenderer(false); + HTMLTextAreaElement* textArea = static_cast<HTMLTextAreaElement*>(node()); + textArea->setFormControlValueMatchesRenderer(false); + textArea->updateValidity(); if (!node()->focused()) return; - // Fire the "input" DOM event - node()->dispatchEvent(eventNames().inputEvent, true, false); + node()->dispatchEvent(Event::create(eventNames().inputEvent, true, false)); if (Frame* frame = document()->frame()) - frame->textDidChangeInTextArea(static_cast<Element*>(node())); + frame->textDidChangeInTextArea(textArea); } bool RenderTextControlMultiLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction) @@ -63,7 +69,10 @@ bool RenderTextControlMultiLine::nodeAtPoint(const HitTestRequest& request, HitT if (!RenderTextControl::nodeAtPoint(request, result, x, y, tx, ty, hitTestAction)) return false; - if (result.innerNode() == node() || result.innerNode() == innerTextElement()) + bool resultIsTextValueOrPlaceholder + = !m_placeholderVisible && result.innerNode() == innerTextElement() + || m_placeholderVisible && result.innerNode()->isDescendantOf(innerTextElement()); + if (result.innerNode() == node() || resultIsTextValueOrPlaceholder) hitInnerTextElement(result, x, y, tx, ty); return true; @@ -95,7 +104,11 @@ void RenderTextControlMultiLine::updateFromElement() createSubtreeIfNeeded(0); RenderTextControl::updateFromElement(); - setInnerTextValue(static_cast<HTMLTextAreaElement*>(node())->value()); + HTMLTextAreaElement* textArea = static_cast<HTMLTextAreaElement*>(node()); + if (m_placeholderVisible) + setInnerTextValue(textArea->getAttribute(HTMLNames::placeholderAttr)); + else + setInnerTextValue(textArea->value()); } void RenderTextControlMultiLine::cacheSelection(int start, int end) @@ -105,8 +118,15 @@ void RenderTextControlMultiLine::cacheSelection(int start, int end) PassRefPtr<RenderStyle> RenderTextControlMultiLine::createInnerTextStyle(const RenderStyle* startStyle) const { - RefPtr<RenderStyle> textBlockStyle = RenderStyle::create(); - textBlockStyle->inheritFrom(startStyle); + RefPtr<RenderStyle> textBlockStyle; + if (m_placeholderVisible) { + if (RenderStyle* pseudoStyle = getCachedPseudoStyle(INPUT_PLACEHOLDER)) + textBlockStyle = RenderStyle::clone(pseudoStyle); + } + if (!textBlockStyle) { + textBlockStyle = RenderStyle::create(); + textBlockStyle->inheritFrom(startStyle); + } adjustInnerTextStyle(startStyle, textBlockStyle.get()); textBlockStyle->setDisplay(BLOCK); @@ -114,4 +134,9 @@ PassRefPtr<RenderStyle> RenderTextControlMultiLine::createInnerTextStyle(const R return textBlockStyle.release(); } +RenderStyle* RenderTextControlMultiLine::textBaseStyle() const +{ + return style(); +} + } diff --git a/WebCore/rendering/RenderTextControlMultiLine.h b/WebCore/rendering/RenderTextControlMultiLine.h index 7296653..3371a8f 100644 --- a/WebCore/rendering/RenderTextControlMultiLine.h +++ b/WebCore/rendering/RenderTextControlMultiLine.h @@ -28,7 +28,7 @@ namespace WebCore { class RenderTextControlMultiLine : public RenderTextControl { public: - RenderTextControlMultiLine(Node*); + RenderTextControlMultiLine(Node*, bool); virtual ~RenderTextControlMultiLine(); void forwardEvent(Event*); @@ -47,6 +47,7 @@ private: virtual void updateFromElement(); virtual void cacheSelection(int start, int end); + virtual RenderStyle* textBaseStyle() const; virtual PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const; }; diff --git a/WebCore/rendering/RenderTextControlSingleLine.cpp b/WebCore/rendering/RenderTextControlSingleLine.cpp index b448eb7..dd1c24c 100644 --- a/WebCore/rendering/RenderTextControlSingleLine.cpp +++ b/WebCore/rendering/RenderTextControlSingleLine.cpp @@ -48,9 +48,8 @@ namespace WebCore { using namespace HTMLNames; -RenderTextControlSingleLine::RenderTextControlSingleLine(Node* node) - : RenderTextControl(node) - , m_placeholderVisible(false) +RenderTextControlSingleLine::RenderTextControlSingleLine(Node* node, bool placeholderVisible) + : RenderTextControl(node, placeholderVisible) , m_searchPopupIsVisible(false) , m_shouldDrawCapsLockIndicator(false) , m_searchEventTimer(this, &RenderTextControlSingleLine::searchEventTimerFired) @@ -69,25 +68,9 @@ RenderTextControlSingleLine::~RenderTextControlSingleLine() m_innerBlock->detach(); } -bool RenderTextControlSingleLine::placeholderShouldBeVisible() const +RenderStyle* RenderTextControlSingleLine::textBaseStyle() const { - return inputElement()->placeholderShouldBeVisible(); -} - -void RenderTextControlSingleLine::updatePlaceholderVisibility() -{ - RenderStyle* parentStyle = m_innerBlock ? m_innerBlock->renderer()->style() : style(); - - RefPtr<RenderStyle> textBlockStyle = createInnerTextStyle(parentStyle); - HTMLElement* innerText = innerTextElement(); - innerText->renderer()->setStyle(textBlockStyle); - - for (Node* n = innerText->firstChild(); n; n = n->traverseNextNode(innerText)) { - if (RenderObject* renderer = n->renderer()) - renderer->setStyle(textBlockStyle); - } - - updateFromElement(); + return m_innerBlock ? m_innerBlock->renderer()->style() : style(); } void RenderTextControlSingleLine::addSearchResult() @@ -163,8 +146,6 @@ void RenderTextControlSingleLine::hidePopup() ASSERT(node()->isHTMLElement()); if (m_searchPopup) m_searchPopup->hide(); - - m_searchPopupIsVisible = false; } void RenderTextControlSingleLine::subtreeHasChanged() @@ -173,7 +154,11 @@ void RenderTextControlSingleLine::subtreeHasChanged() RenderTextControl::subtreeHasChanged(); InputElement* input = inputElement(); - input->setValueFromRenderer(input->constrainValue(text())); + // We don't need to call sanitizeUserInputValue() function here because + // InputElement::handleBeforeTextInsertedEvent() has already called + // sanitizeUserInputValue(). + // sanitizeValue() is needed because IME input doesn't dispatch BeforeTextInsertedEvent. + input->setValueFromRenderer(input->sanitizeValue(text())); if (m_cancelButton) updateCancelButtonVisibility(); @@ -480,17 +465,14 @@ void RenderTextControlSingleLine::updateFromElement() createSubtreeIfNeeded(); RenderTextControl::updateFromElement(); - bool placeholderVisibilityShouldChange = m_placeholderVisible != placeholderShouldBeVisible(); - m_placeholderVisible = placeholderShouldBeVisible(); - if (m_cancelButton) updateCancelButtonVisibility(); if (m_placeholderVisible) { ExceptionCode ec = 0; - innerTextElement()->setInnerText(inputElement()->placeholder(), ec); + innerTextElement()->setInnerText(static_cast<Element*>(node())->getAttribute(placeholderAttr), ec); ASSERT(!ec); - } else if (!static_cast<Element*>(node())->formControlValueMatchesRenderer() || placeholderVisibilityShouldChange) + } else setInnerTextValue(inputElement()->value()); if (m_searchPopupIsVisible) @@ -505,7 +487,7 @@ void RenderTextControlSingleLine::cacheSelection(int start, int end) PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerTextStyle(const RenderStyle* startStyle) const { RefPtr<RenderStyle> textBlockStyle; - if (placeholderShouldBeVisible()) { + if (m_placeholderVisible) { if (RenderStyle* pseudoStyle = getCachedPseudoStyle(INPUT_PLACEHOLDER)) textBlockStyle = RenderStyle::clone(pseudoStyle); } @@ -535,7 +517,7 @@ PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerTextStyle(const // After this, updateFromElement will immediately update the text displayed. // When the placeholder is no longer visible, updatePlaceholderVisiblity will reset the style, // and the text security mode will be set back to the computed value correctly. - if (placeholderShouldBeVisible()) + if (m_placeholderVisible) textBlockStyle->setTextSecurity(TSNONE); return textBlockStyle.release(); @@ -753,6 +735,11 @@ int RenderTextControlSingleLine::selectedIndex() const return -1; } +void RenderTextControlSingleLine::popupDidHide() +{ + m_searchPopupIsVisible = false; +} + bool RenderTextControlSingleLine::itemIsSeparator(unsigned listIndex) const { // The separator will be the second to last item in our list. @@ -832,12 +819,12 @@ void RenderTextControlSingleLine::setScrollTop(int newTop) innerTextElement()->setScrollTop(newTop); } -bool RenderTextControlSingleLine::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier) +bool RenderTextControlSingleLine::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier, Node** stopNode) { RenderLayer* layer = innerTextElement()->renderBox()->layer(); if (layer && layer->scroll(direction, granularity, multiplier)) return true; - return RenderBlock::scroll(direction, granularity, multiplier); + return RenderBlock::scroll(direction, granularity, multiplier, stopNode); } PassRefPtr<Scrollbar> RenderTextControlSingleLine::createScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, ScrollbarControlSize controlSize) diff --git a/WebCore/rendering/RenderTextControlSingleLine.h b/WebCore/rendering/RenderTextControlSingleLine.h index da9838f..e30ff0d 100644 --- a/WebCore/rendering/RenderTextControlSingleLine.h +++ b/WebCore/rendering/RenderTextControlSingleLine.h @@ -36,19 +36,18 @@ class TextControlInnerElement; class RenderTextControlSingleLine : public RenderTextControl, private PopupMenuClient { public: - RenderTextControlSingleLine(Node*); + RenderTextControlSingleLine(Node*, bool); virtual ~RenderTextControlSingleLine(); bool placeholderIsVisible() const { return m_placeholderVisible; } bool placeholderShouldBeVisible() const; - void updatePlaceholderVisibility(); void addSearchResult(); void stopSearchEventTimer(); bool popupIsVisible() const { return m_searchPopupIsVisible; } void showPopup(); - virtual void hidePopup(); // PopupMenuClient method + void hidePopup(); void forwardEvent(Event*); @@ -73,7 +72,7 @@ private: virtual int scrollHeight() const; virtual void setScrollLeft(int); virtual void setScrollTop(int); - virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1.0f); + virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1.0f, Node** stopNode = 0); int textBlockWidth() const; virtual int preferredContentWidth(float charWidth) const; @@ -84,6 +83,7 @@ private: virtual void cacheSelection(int start, int end); virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); + virtual RenderStyle* textBaseStyle() const; virtual PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const; PassRefPtr<RenderStyle> createInnerBlockStyle(const RenderStyle* startStyle) const; PassRefPtr<RenderStyle> createResultsButtonStyle(const RenderStyle* startStyle) const; @@ -109,6 +109,7 @@ private: virtual int clientPaddingRight() const; virtual int listSize() const; virtual int selectedIndex() const; + virtual void popupDidHide(); virtual bool itemIsSeparator(unsigned listIndex) const; virtual bool itemIsLabel(unsigned listIndex) const; virtual bool itemIsSelected(unsigned listIndex) const; @@ -121,7 +122,6 @@ private: InputElement* inputElement() const; - bool m_placeholderVisible; bool m_searchPopupIsVisible; bool m_shouldDrawCapsLockIndicator; diff --git a/WebCore/rendering/RenderTextFragment.cpp b/WebCore/rendering/RenderTextFragment.cpp index 7da9e5a..9ff1106 100644 --- a/WebCore/rendering/RenderTextFragment.cpp +++ b/WebCore/rendering/RenderTextFragment.cpp @@ -47,7 +47,7 @@ RenderTextFragment::RenderTextFragment(Node* node, StringImpl* str) PassRefPtr<StringImpl> RenderTextFragment::originalText() const { Node* e = node(); - RefPtr<StringImpl> result = (e ? static_cast<Text*>(e)->string() : contentString()); + RefPtr<StringImpl> result = (e ? static_cast<Text*>(e)->dataImpl() : contentString()); if (result && (start() > 0 || start() < result->length())) result = result->substring(start(), end()); return result.release(); @@ -76,7 +76,7 @@ UChar RenderTextFragment::previousCharacter() { if (start()) { Node* e = node(); - StringImpl* original = (e ? static_cast<Text*>(e)->string() : contentString()); + StringImpl* original = (e ? static_cast<Text*>(e)->dataImpl() : contentString()); if (original) return (*original)[start() - 1]; } diff --git a/WebCore/rendering/RenderTheme.cpp b/WebCore/rendering/RenderTheme.cpp index 63e7d45..238279a 100644 --- a/WebCore/rendering/RenderTheme.cpp +++ b/WebCore/rendering/RenderTheme.cpp @@ -30,6 +30,7 @@ #include "GraphicsContext.h" #include "HTMLInputElement.h" #include "HTMLNames.h" +#include "MediaControlElements.h" #include "Page.h" #include "RenderStyle.h" #include "RenderView.h" @@ -84,6 +85,7 @@ void RenderTheme::adjustStyle(CSSStyleSelector* selector, RenderStyle* style, El #if USE(NEW_THEME) switch (part) { + case ListButtonPart: case CheckboxPart: case RadioPart: case PushButtonPart: @@ -170,6 +172,7 @@ void RenderTheme::adjustStyle(CSSStyleSelector* selector, RenderStyle* style, El return adjustRadioStyle(selector, style, e); case PushButtonPart: case SquareButtonPart: + case ListButtonPart: case DefaultButtonPart: case ButtonPart: return adjustButtonStyle(selector, style, e); @@ -187,6 +190,7 @@ void RenderTheme::adjustStyle(CSSStyleSelector* selector, RenderStyle* style, El case MenulistButtonPart: return adjustMenuListButtonStyle(selector, style, e); case MediaSliderPart: + case MediaVolumeSliderPart: case SliderHorizontalPart: case SliderVerticalPart: return adjustSliderTrackStyle(selector, style, e); @@ -229,6 +233,7 @@ bool RenderTheme::paint(RenderObject* o, const RenderObject::PaintInfo& paintInf case RadioPart: case PushButtonPart: case SquareButtonPart: + case ListButtonPart: case DefaultButtonPart: case ButtonPart: m_theme->paint(part, controlStatesForRenderer(o), const_cast<GraphicsContext*>(paintInfo.context), r, o->style()->effectiveZoom(), o->view()->frameView()); @@ -247,6 +252,7 @@ bool RenderTheme::paint(RenderObject* o, const RenderObject::PaintInfo& paintInf return paintRadio(o, paintInfo, r); case PushButtonPart: case SquareButtonPart: + case ListButtonPart: case DefaultButtonPart: case ButtonPart: return paintButton(o, paintInfo, r); @@ -282,6 +288,14 @@ bool RenderTheme::paint(RenderObject* o, const RenderObject::PaintInfo& paintInf if (o->parent()->isSlider()) return paintMediaSliderThumb(o, paintInfo, r); break; + case MediaVolumeSliderContainerPart: + return paintMediaVolumeSliderContainer(o, paintInfo, r); + case MediaVolumeSliderPart: + return paintMediaVolumeSliderTrack(o, paintInfo, r); + case MediaVolumeSliderThumbPart: + if (o->parent()->isSlider()) + return paintMediaVolumeSliderThumb(o, paintInfo, r); + break; case MediaTimeRemainingPart: return paintMediaTimeRemaining(o, paintInfo, r); case MediaCurrentTimePart: @@ -329,6 +343,7 @@ bool RenderTheme::paintBorderOnly(RenderObject* o, const RenderObject::PaintInfo case RadioPart: case PushButtonPart: case SquareButtonPart: + case ListButtonPart: case DefaultButtonPart: case ButtonPart: case MenulistPart: @@ -363,6 +378,7 @@ bool RenderTheme::paintDecorations(RenderObject* o, const RenderObject::PaintInf case RadioPart: case PushButtonPart: case SquareButtonPart: + case ListButtonPart: case DefaultButtonPart: case ButtonPart: case MenulistPart: @@ -391,6 +407,23 @@ bool RenderTheme::hitTestMediaControlPart(RenderObject* o, const IntPoint& absPo FloatPoint localPoint = o->absoluteToLocal(absPoint, false, true); // respect transforms return toRenderBox(o)->borderBoxRect().contains(roundedIntPoint(localPoint)); } + +bool RenderTheme::shouldRenderMediaControlPart(ControlPart part, Element* e) +{ + HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(e); + switch (part) { + case MediaMuteButtonPart: + return mediaElement->hasAudio(); + case MediaRewindButtonPart: + return mediaElement->movieLoadType() != MediaPlayer::LiveStream; + case MediaReturnToRealtimeButtonPart: + return mediaElement->movieLoadType() == MediaPlayer::LiveStream; + case MediaFullscreenButtonPart: + return mediaElement->supportsFullscreen(); + default: + return true; + } +} #endif Color RenderTheme::activeSelectionBackgroundColor() const diff --git a/WebCore/rendering/RenderTheme.h b/WebCore/rendering/RenderTheme.h index 4f37015..68e2eba 100644 --- a/WebCore/rendering/RenderTheme.h +++ b/WebCore/rendering/RenderTheme.h @@ -172,6 +172,7 @@ public: #if ENABLE(VIDEO) // Media controls virtual bool hitTestMediaControlPart(RenderObject*, const IntPoint& absPoint); + virtual bool shouldRenderMediaControlPart(ControlPart, Element*); #endif protected: @@ -247,6 +248,9 @@ protected: virtual bool paintMediaSeekForwardButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; } virtual bool paintMediaSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; } virtual bool paintMediaSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; } + virtual bool paintMediaVolumeSliderContainer(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; } + virtual bool paintMediaVolumeSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; } + virtual bool paintMediaVolumeSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; } virtual bool paintMediaRewindButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; } virtual bool paintMediaReturnToRealtimeButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; } virtual bool paintMediaControlsBackground(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; } diff --git a/WebCore/rendering/RenderThemeChromiumLinux.cpp b/WebCore/rendering/RenderThemeChromiumLinux.cpp index c4020d3..9048ce3 100644 --- a/WebCore/rendering/RenderThemeChromiumLinux.cpp +++ b/WebCore/rendering/RenderThemeChromiumLinux.cpp @@ -45,6 +45,7 @@ PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page) RenderThemeChromiumLinux::RenderThemeChromiumLinux() { + m_caretBlinkInterval = RenderTheme::caretBlinkInterval(); } RenderThemeChromiumLinux::~RenderThemeChromiumLinux() @@ -91,9 +92,34 @@ Color RenderThemeChromiumLinux::inactiveListBoxSelectionForegroundColor() const return Color(0x32, 0x32, 0x32); } +void RenderThemeChromiumLinux::adjustSliderThumbSize(RenderObject* o) const +{ + // These sizes match the sizes in Chromium Win. + const int sliderThumbAlongAxis = 11; + const int sliderThumbAcrossAxis = 21; + if (o->style()->appearance() == SliderThumbHorizontalPart) { + o->style()->setWidth(Length(sliderThumbAlongAxis, Fixed)); + o->style()->setHeight(Length(sliderThumbAcrossAxis, Fixed)); + } else if (o->style()->appearance() == SliderThumbVerticalPart) { + o->style()->setWidth(Length(sliderThumbAcrossAxis, Fixed)); + o->style()->setHeight(Length(sliderThumbAlongAxis, Fixed)); + } else + RenderThemeChromiumSkia::adjustSliderThumbSize(o); +} + bool RenderThemeChromiumLinux::supportsControlTints() const { return true; } +void RenderThemeChromiumLinux::setCaretBlinkInterval(double interval) +{ + m_caretBlinkInterval = interval; +} + +double RenderThemeChromiumLinux::caretBlinkIntervalInternal() const +{ + return m_caretBlinkInterval; +} + } // namespace WebCore diff --git a/WebCore/rendering/RenderThemeChromiumLinux.h b/WebCore/rendering/RenderThemeChromiumLinux.h index e75ddd5..e137ad5 100644 --- a/WebCore/rendering/RenderThemeChromiumLinux.h +++ b/WebCore/rendering/RenderThemeChromiumLinux.h @@ -49,12 +49,19 @@ namespace WebCore { virtual Color inactiveListBoxSelectionBackgroundColor() const; virtual Color inactiveListBoxSelectionForegroundColor() const; + virtual void adjustSliderThumbSize(RenderObject*) const; + + void setCaretBlinkInterval(double interval); + virtual double caretBlinkIntervalInternal() const; + private: RenderThemeChromiumLinux(); virtual ~RenderThemeChromiumLinux(); // A general method asking if any control tinting is supported at all. virtual bool supportsControlTints() const; + + double m_caretBlinkInterval; }; } // namespace WebCore diff --git a/WebCore/rendering/RenderThemeChromiumMac.h b/WebCore/rendering/RenderThemeChromiumMac.h index ffb2548..61b5e8f 100644 --- a/WebCore/rendering/RenderThemeChromiumMac.h +++ b/WebCore/rendering/RenderThemeChromiumMac.h @@ -3,7 +3,6 @@ * * Copyright (C) 2005 Apple Computer, Inc. * Copyright (C) 2008, 2009 Google, Inc. - * Copyright (C) 2009 Kenneth Rohde Christiansen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -26,7 +25,6 @@ #define RenderThemeChromiumMac_h #import "RenderTheme.h" -#import <AppKit/AppKit.h> #import <wtf/HashMap.h> #import <wtf/RetainPtr.h> @@ -36,185 +34,166 @@ class WebCoreRenderThemeNotificationObserver; #endif +// This file (and its associated .mm file) is a clone of RenderThemeMac.h. See +// the .mm file for details. + namespace WebCore { - class RenderStyle; +class RenderStyle; + +class RenderThemeChromiumMac : public RenderTheme { +public: + static PassRefPtr<RenderTheme> create(); + + // A method asking if the control changes its tint when the window has focus or not. + virtual bool controlSupportsTints(const RenderObject*) const; + + // A general method asking if any control tinting is supported at all. + virtual bool supportsControlTints() const { return true; } + + virtual void adjustRepaintRect(const RenderObject*, IntRect&); + + virtual bool isControlStyled(const RenderStyle*, const BorderData&, + const FillLayer&, const Color& backgroundColor) const; + + virtual Color platformActiveSelectionBackgroundColor() const; + virtual Color platformInactiveSelectionBackgroundColor() const; + virtual Color platformActiveListBoxSelectionBackgroundColor() const; + virtual Color platformActiveListBoxSelectionForegroundColor() const; + virtual Color platformInactiveListBoxSelectionBackgroundColor() const; + virtual Color platformInactiveListBoxSelectionForegroundColor() const; + virtual Color platformFocusRingColor() const; - class RenderThemeChromiumMac : public RenderTheme { - public: - static PassRefPtr<RenderTheme> create(); + virtual ScrollbarControlSize scrollbarControlSizeForPart(ControlPart) { return SmallScrollbar; } + + virtual void platformColorsDidChange(); + + // System fonts. + virtual void systemFont(int cssValueId, FontDescription&) const; + + virtual int minimumMenuListSize(RenderStyle*) const; + + virtual void adjustSliderThumbSize(RenderObject*) const; + + virtual int popupInternalPaddingLeft(RenderStyle*) const; + virtual int popupInternalPaddingRight(RenderStyle*) const; + virtual int popupInternalPaddingTop(RenderStyle*) const; + virtual int popupInternalPaddingBottom(RenderStyle*) const; + + virtual bool paintCapsLockIndicator(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - // A method to obtain the baseline position for a "leaf" control. This will only be used if a baseline - // position cannot be determined by examining child content. Checkboxes and radio buttons are examples of - // controls that need to do this. - virtual int baselinePosition(const RenderObject*) const; + virtual Color systemColor(int cssValueId) const; - // A method asking if the control changes its tint when the window has focus or not. - virtual bool controlSupportsTints(const RenderObject*) const; +protected: + virtual bool supportsSelectionForegroundColors() const { return false; } - // A general method asking if any control tinting is supported at all. - virtual bool supportsControlTints() const { return true; } + virtual bool paintTextField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - virtual void adjustRepaintRect(const RenderObject*, IntRect&); + virtual bool paintTextArea(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual void adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - virtual bool isControlStyled(const RenderStyle*, const BorderData&, - const FillLayer&, const Color& backgroundColor) const; + virtual bool paintMenuList(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - virtual Color platformActiveSelectionBackgroundColor() const; - virtual Color platformInactiveSelectionBackgroundColor() const; - virtual Color platformActiveListBoxSelectionBackgroundColor() const; + virtual bool paintMenuListButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - virtual Color platformFocusRingColor() const; - - virtual void platformColorsDidChange(); + virtual bool paintSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual void adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - // System fonts. - virtual void systemFont(int cssValueId, FontDescription&) const; + virtual bool paintSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual void adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - virtual int minimumMenuListSize(RenderStyle*) const; + virtual bool paintSearchField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - virtual void adjustSliderThumbSize(RenderObject*) const; - - virtual int popupInternalPaddingLeft(RenderStyle*) const; - virtual int popupInternalPaddingRight(RenderStyle*) const; - virtual int popupInternalPaddingTop(RenderStyle*) const; - virtual int popupInternalPaddingBottom(RenderStyle*) const; - - virtual ScrollbarControlSize scrollbarControlSizeForPart(ControlPart) { return SmallScrollbar; } + virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual bool paintSearchFieldCancelButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + + virtual void adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual bool paintSearchFieldDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + + virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual bool paintSearchFieldResultsDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + + virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual bool paintSearchFieldResultsButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + +#if ENABLE(VIDEO) + virtual bool shouldRenderMediaControlPart(ControlPart, Element*); + virtual bool paintMediaPlayButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual bool paintMediaMuteButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual bool paintMediaSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual bool paintMediaSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual bool paintMediaVolumeSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual bool paintMediaVolumeSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual bool paintMediaControlsBackground(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + + // Media controls + virtual String extraMediaControlsStyleSheet(); +#endif + +private: + RenderThemeChromiumMac(); + virtual ~RenderThemeChromiumMac(); + + IntRect inflateRect(const IntRect&, const IntSize&, const int* margins, float zoomLevel = 1.0f) const; + + FloatRect convertToPaintingRect(const RenderObject* inputRenderer, const RenderObject* partRenderer, const FloatRect& inputRect, const IntRect& r) const; - virtual bool paintCapsLockIndicator(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + // Get the control size based off the font. Used by some of the controls (like buttons). + NSControlSize controlSizeForFont(RenderStyle*) const; + NSControlSize controlSizeForSystemFont(RenderStyle*) const; + void setControlSize(NSCell*, const IntSize* sizes, const IntSize& minSize, float zoomLevel = 1.0f); + void setSizeFromFont(RenderStyle*, const IntSize* sizes) const; + IntSize sizeForFont(RenderStyle*, const IntSize* sizes) const; + IntSize sizeForSystemFont(RenderStyle*, const IntSize* sizes) const; + void setFontFromControlSize(CSSStyleSelector*, RenderStyle*, NSControlSize) const; + + void updateActiveState(NSCell*, const RenderObject*); + void updateCheckedState(NSCell*, const RenderObject*); + void updateEnabledState(NSCell*, const RenderObject*); + void updateFocusedState(NSCell*, const RenderObject*); + void updatePressedState(NSCell*, const RenderObject*); + + // Helpers for adjusting appearance and for painting + + void setPopupButtonCellState(const RenderObject*, const IntRect&); + const IntSize* popupButtonSizes() const; + const int* popupButtonMargins() const; + const int* popupButtonPadding(NSControlSize) const; + void paintMenuListButtonGradients(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + const IntSize* menuListSizes() const; + + const IntSize* searchFieldSizes() const; + const IntSize* cancelButtonSizes() const; + const IntSize* resultsButtonSizes() const; + void setSearchCellState(RenderObject*, const IntRect&); + void setSearchFieldSize(RenderStyle*) const; + + NSPopUpButtonCell* popupButton() const; + NSSearchFieldCell* search() const; + NSMenu* searchMenuTemplate() const; + NSSliderCell* sliderThumbHorizontal() const; + NSSliderCell* sliderThumbVertical() const; + +private: + mutable RetainPtr<NSPopUpButtonCell> m_popupButton; + mutable RetainPtr<NSSearchFieldCell> m_search; + mutable RetainPtr<NSMenu> m_searchMenuTemplate; + mutable RetainPtr<NSSliderCell> m_sliderThumbHorizontal; + mutable RetainPtr<NSSliderCell> m_sliderThumbVertical; - virtual Color systemColor(int cssValueId) const; + bool m_isSliderThumbHorizontalPressed; + bool m_isSliderThumbVerticalPressed; - protected: - virtual bool supportsSelectionForegroundColors() const { return false; } + mutable HashMap<int, RGBA32> m_systemColorCache; - // Methods for each appearance value. - virtual bool paintCheckbox(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual void setCheckboxSize(RenderStyle*) const; - - virtual bool paintRadio(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual void setRadioSize(RenderStyle*) const; - - virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle*, WebCore::Element*) const; - virtual bool paintButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual void setButtonSize(RenderStyle*) const; - - virtual bool paintTextField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - - virtual bool paintTextArea(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual void adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - - virtual bool paintMenuList(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - - virtual bool paintMenuListButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - - virtual bool paintSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual void adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - - virtual bool paintSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual void adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - - virtual bool paintSearchField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - - virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - virtual bool paintSearchFieldCancelButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - - virtual void adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - virtual bool paintSearchFieldDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - - virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - virtual bool paintSearchFieldResultsDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - - virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - virtual bool paintSearchFieldResultsButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - - virtual bool paintMediaFullscreenButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual bool paintMediaPlayButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual bool paintMediaMuteButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual bool paintMediaSeekBackButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual bool paintMediaSeekForwardButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual bool paintMediaSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual bool paintMediaSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - - private: - RenderThemeChromiumMac(); - virtual ~RenderThemeChromiumMac(); - - IntRect inflateRect(const IntRect&, const IntSize&, const int* margins, float zoomLevel = 1.0f) const; - - // Get the control size based off the font. Used by some of the controls (like buttons). - NSControlSize controlSizeForFont(RenderStyle*) const; - NSControlSize controlSizeForSystemFont(RenderStyle*) const; - void setControlSize(NSCell*, const IntSize* sizes, const IntSize& minSize, float zoomLevel = 1.0f); - void setSizeFromFont(RenderStyle*, const IntSize* sizes) const; - IntSize sizeForFont(RenderStyle*, const IntSize* sizes) const; - IntSize sizeForSystemFont(RenderStyle*, const IntSize* sizes) const; - void setFontFromControlSize(CSSStyleSelector*, RenderStyle*, NSControlSize) const; - - void updateCheckedState(NSCell*, const RenderObject*); - void updateEnabledState(NSCell*, const RenderObject*); - void updateFocusedState(NSCell*, const RenderObject*); - void updatePressedState(NSCell*, const RenderObject*); - - // Helpers for adjusting appearance and for painting - const IntSize* checkboxSizes() const; - const int* checkboxMargins() const; - void setCheckboxCellState(const RenderObject*, const IntRect&); - - const IntSize* radioSizes() const; - const int* radioMargins() const; - void setRadioCellState(const RenderObject*, const IntRect&); - - void setButtonPaddingFromControlSize(RenderStyle*, NSControlSize) const; - const IntSize* buttonSizes() const; - const int* buttonMargins() const; - void setButtonCellState(const RenderObject*, const IntRect&); - - void setPopupButtonCellState(const RenderObject*, const IntRect&); - const IntSize* popupButtonSizes() const; - const int* popupButtonMargins() const; - const int* popupButtonPadding(NSControlSize) const; - void paintMenuListButtonGradients(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - const IntSize* menuListSizes() const; - - const IntSize* searchFieldSizes() const; - const IntSize* cancelButtonSizes() const; - const IntSize* resultsButtonSizes() const; - void setSearchCellState(RenderObject*, const IntRect&); - void setSearchFieldSize(RenderStyle*) const; - - NSButtonCell* checkbox() const; - NSButtonCell* radio() const; - NSButtonCell* button() const; - NSPopUpButtonCell* popupButton() const; - NSSearchFieldCell* search() const; - NSMenu* searchMenuTemplate() const; - NSSliderCell* sliderThumbHorizontal() const; - NSSliderCell* sliderThumbVertical() const; - - private: - mutable RetainPtr<NSButtonCell> m_checkbox; - mutable RetainPtr<NSButtonCell> m_radio; - mutable RetainPtr<NSButtonCell> m_button; - mutable RetainPtr<NSPopUpButtonCell> m_popupButton; - mutable RetainPtr<NSSearchFieldCell> m_search; - mutable RetainPtr<NSMenu> m_searchMenuTemplate; - mutable RetainPtr<NSSliderCell> m_sliderThumbHorizontal; - mutable RetainPtr<NSSliderCell> m_sliderThumbVertical; - - bool m_isSliderThumbHorizontalPressed; - bool m_isSliderThumbVerticalPressed; - - mutable HashMap<int, RGBA32> m_systemColorCache; - - RetainPtr<WebCoreRenderThemeNotificationObserver> m_notificationObserver; - }; + RetainPtr<WebCoreRenderThemeNotificationObserver> m_notificationObserver; + bool paintMediaButtonInternal(GraphicsContext*, const IntRect&, Image*); +}; } // namespace WebCore -#endif +#endif // RenderThemeChromiumMac_h diff --git a/WebCore/rendering/RenderThemeChromiumMac.mm b/WebCore/rendering/RenderThemeChromiumMac.mm index 23201c9..bcfcd57 100644 --- a/WebCore/rendering/RenderThemeChromiumMac.mm +++ b/WebCore/rendering/RenderThemeChromiumMac.mm @@ -1,7 +1,6 @@ /* - * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2008, 2009 Google, Inc. - * Copyright (C) 2009 Kenneth Rohde Christiansen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -19,25 +18,16 @@ * Boston, MA 02110-1301, USA. */ -// FIXME: we still need to figure out if passing a null view to the cell -// drawing routines will work. I expect not, and if that's the case we'll have -// to figure out something else. For now, at least leave the lines commented -// in, but the procurement of the view if 0'd. - #import "config.h" #import "RenderThemeChromiumMac.h" -#import <Carbon/Carbon.h> -#import <Cocoa/Cocoa.h> -#import <math.h> - #import "BitmapImage.h" #import "ChromiumBridge.h" #import "ColorMac.h" #import "CSSStyleSelector.h" #import "CSSValueKeywords.h" +#import "Document.h" #import "Element.h" -#import "FoundationExtras.h" #import "FrameView.h" #import "GraphicsContext.h" #import "HTMLInputElement.h" @@ -47,11 +37,18 @@ #import "LocalCurrentGraphicsContext.h" #import "MediaControlElements.h" #import "RenderMedia.h" +#import "RenderMediaControlsChromium.h" #import "RenderSlider.h" #import "RenderView.h" #import "SharedBuffer.h" +#import "UserAgentStyleSheets.h" #import "WebCoreSystemInterface.h" +#import "UserAgentStyleSheets.h" +#import <Carbon/Carbon.h> +#import <Cocoa/Cocoa.h> #import <wtf/RetainPtr.h> +#import <wtf/StdLibExtras.h> +#import <math.h> #ifdef BUILDING_ON_TIGER typedef int NSInteger; @@ -60,6 +57,25 @@ typedef unsigned NSUInteger; using std::min; +// This file (and its associated .h file) is a clone of RenderThemeMac.mm. +// Because the original file is designed to run in-process inside a Cocoa view, +// we must maintain a fork. Please maintain this file by performing parallel +// changes to it. +// +// The only changes from RenderThemeMac should be: +// - The classname change from RenderThemeMac to RenderThemeChromiumMac. +// - The introduction of RTCMFlippedView and FlippedView() and its use as the +// parent view for cell rendering. +// - In platformFocusRingColor(), the use of ChromiumBridge to determine if +// we're in layout test mode. +// - updateActiveState() and its use to update the cells' visual appearance. +// - All the paintMedia*() functions and extraMediaControlsStyleSheet() +// are forked from RenderThemeChromiumSkia instead of RenderThemeMac. +// +// For all other differences, if it was introduced in this file, then the +// maintainer forgot to include it in the list; otherwise it is an update that +// should have been applied to this file but was not. + // The methods in this file are specific to the Mac OS X platform. // FIXME: The platform-independent code in this class should be factored out and merged with RenderThemeSafari. @@ -84,48 +100,66 @@ using std::min; return self; } -- (void)systemColorsDidChange:(NSNotification *)notification +- (void)systemColorsDidChange:(NSNotification *)unusedNotification { - ASSERT([[notification name] isEqualToString:NSSystemColorsDidChangeNotification]); + ASSERT_UNUSED(unusedNotification, [[unusedNotification name] isEqualToString:NSSystemColorsDidChangeNotification]); _theme->platformColorsDidChange(); } @end +@interface RTCMFlippedView : NSView +{} + +- (BOOL)isFlipped; +- (NSText *)currentEditor; + +@end + +@implementation RTCMFlippedView + +- (BOOL)isFlipped { + return [[NSGraphicsContext currentContext] isFlipped]; +} + +- (NSText *)currentEditor { + return nil; +} + +@end + namespace WebCore { using namespace HTMLNames; enum { - TopMargin, - RightMargin, - BottomMargin, - LeftMargin + topMargin, + rightMargin, + bottomMargin, + leftMargin }; enum { - TopPadding, - RightPadding, - BottomPadding, - LeftPadding + topPadding, + rightPadding, + bottomPadding, + leftPadding }; -// In our Mac port, we don't define PLATFORM(MAC) and thus don't pick up the -// |operator NSRect()| on WebCore::IntRect and FloatRect. This substitues for -// that missing conversion operator. -NSRect IntRectToNSRect(const IntRect & rect) +// In Snow Leopard, many cells only check to see if the view they're passed is +// flipped, and if a nil view is passed, neglect to check if the current +// graphics context is flipped. Thus we pass a sham view to them, one whose +// flipped state just reflects the state of the context. +NSView* FlippedView() { - return NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height()); + static NSView* view = [[RTCMFlippedView alloc] init]; + return view; } -NSRect FloatRectToNSRect(const FloatRect & rect) +PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page*) { - return NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height()); -} - -IntRect NSRectToIntRect(const NSRect & rect) -{ - return IntRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); + static RenderTheme* rt = RenderThemeChromiumMac::create().releaseRef(); + return rt; } PassRefPtr<RenderTheme> RenderThemeChromiumMac::create() @@ -133,12 +167,6 @@ PassRefPtr<RenderTheme> RenderThemeChromiumMac::create() return adoptRef(new RenderThemeChromiumMac); } -PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page) -{ - static RenderTheme* rt = RenderThemeChromiumMac::create().releaseRef(); - return rt; -} - RenderThemeChromiumMac::RenderThemeChromiumMac() : m_isSliderThumbHorizontalPressed(false) , m_isSliderThumbVerticalPressed(false) @@ -173,6 +201,16 @@ Color RenderThemeChromiumMac::platformActiveListBoxSelectionBackgroundColor() co return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent])); } +Color RenderThemeChromiumMac::platformActiveListBoxSelectionForegroundColor() const +{ + return Color::white; +} + +Color RenderThemeChromiumMac::platformInactiveListBoxSelectionForegroundColor() const +{ + return Color::black; +} + Color RenderThemeChromiumMac::platformFocusRingColor() const { if (ChromiumBridge::layoutTestMode()) @@ -181,6 +219,11 @@ Color RenderThemeChromiumMac::platformFocusRingColor() const return systemColor(CSSValueWebkitFocusRingColor); } +Color RenderThemeChromiumMac::platformInactiveListBoxSelectionBackgroundColor() const +{ + return platformInactiveSelectionBackgroundColor(); +} + static FontWeight toFontWeight(NSInteger appKitFontWeight) { ASSERT(appKitFontWeight > 0 && appKitFontWeight < 15); @@ -210,51 +253,51 @@ static FontWeight toFontWeight(NSInteger appKitFontWeight) void RenderThemeChromiumMac::systemFont(int cssValueId, FontDescription& fontDescription) const { - static FontDescription systemFont; - static FontDescription smallSystemFont; - static FontDescription menuFont; - static FontDescription labelFont; - static FontDescription miniControlFont; - static FontDescription smallControlFont; - static FontDescription controlFont; + DEFINE_STATIC_LOCAL(FontDescription, systemFont, ()); + DEFINE_STATIC_LOCAL(FontDescription, smallSystemFont, ()); + DEFINE_STATIC_LOCAL(FontDescription, menuFont, ()); + DEFINE_STATIC_LOCAL(FontDescription, labelFont, ()); + DEFINE_STATIC_LOCAL(FontDescription, miniControlFont, ()); + DEFINE_STATIC_LOCAL(FontDescription, smallControlFont, ()); + DEFINE_STATIC_LOCAL(FontDescription, controlFont, ()); FontDescription* cachedDesc; NSFont* font = nil; switch (cssValueId) { - case CSSValueSmallCaption: - cachedDesc = &smallSystemFont; - if (!smallSystemFont.isAbsoluteSize()) - font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]]; - break; - case CSSValueMenu: - cachedDesc = &menuFont; - if (!menuFont.isAbsoluteSize()) - font = [NSFont menuFontOfSize:[NSFont systemFontSize]]; - break; - case CSSValueStatusBar: - cachedDesc = &labelFont; - if (!labelFont.isAbsoluteSize()) - font = [NSFont labelFontOfSize:[NSFont labelFontSize]]; - break; - case CSSValueWebkitMiniControl: - cachedDesc = &miniControlFont; - if (!miniControlFont.isAbsoluteSize()) - font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSMiniControlSize]]; - break; - case CSSValueWebkitSmallControl: - cachedDesc = &smallControlFont; - if (!smallControlFont.isAbsoluteSize()) - font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]; - break; - case CSSValueWebkitControl: - cachedDesc = &controlFont; - if (!controlFont.isAbsoluteSize()) - font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]]; - break; - default: - cachedDesc = &systemFont; - if (!systemFont.isAbsoluteSize()) - font = [NSFont systemFontOfSize:[NSFont systemFontSize]]; + case CSSValueSmallCaption: + cachedDesc = &smallSystemFont; + if (!smallSystemFont.isAbsoluteSize()) + font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]]; + break; + case CSSValueMenu: + cachedDesc = &menuFont; + if (!menuFont.isAbsoluteSize()) + font = [NSFont menuFontOfSize:[NSFont systemFontSize]]; + break; + case CSSValueStatusBar: + cachedDesc = &labelFont; + if (!labelFont.isAbsoluteSize()) + font = [NSFont labelFontOfSize:[NSFont labelFontSize]]; + break; + case CSSValueWebkitMiniControl: + cachedDesc = &miniControlFont; + if (!miniControlFont.isAbsoluteSize()) + font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSMiniControlSize]]; + break; + case CSSValueWebkitSmallControl: + cachedDesc = &smallControlFont; + if (!smallControlFont.isAbsoluteSize()) + font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]; + break; + case CSSValueWebkitControl: + cachedDesc = &controlFont; + if (!controlFont.isAbsoluteSize()) + font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]]; + break; + default: + cachedDesc = &systemFont; + if (!systemFont.isAbsoluteSize()) + font = [NSFont systemFontOfSize:[NSFont systemFontSize]]; } if (font) { @@ -271,7 +314,7 @@ void RenderThemeChromiumMac::systemFont(int cssValueId, FontDescription& fontDes static RGBA32 convertNSColorToColor(NSColor *color) { - NSColor *colorInColorSpace = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; + NSColor *colorInColorSpace = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace]; if (colorInColorSpace) { static const double scaleFactor = nextafter(256.0, 0.0); return makeRGB(static_cast<int>(scaleFactor * [colorInColorSpace redComponent]), @@ -291,7 +334,7 @@ static RGBA32 convertNSColorToColor(NSColor *color) samplesPerPixel:4 hasAlpha:YES isPlanar:NO - colorSpaceName:NSCalibratedRGBColorSpace + colorSpaceName:NSDeviceRGBColorSpace bytesPerRow:4 bitsPerPixel:32]; @@ -318,7 +361,7 @@ static RGBA32 menuBackgroundColor() samplesPerPixel:4 hasAlpha:YES isPlanar:NO - colorSpaceName:NSCalibratedRGBColorSpace + colorSpaceName:NSDeviceRGBColorSpace bytesPerRow:4 bitsPerPixel:32]; @@ -350,101 +393,101 @@ Color RenderThemeChromiumMac::systemColor(int cssValueId) const Color color; switch (cssValueId) { - case CSSValueActiveborder: - color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]); - break; - case CSSValueActivecaption: - color = convertNSColorToColor([NSColor windowFrameTextColor]); - break; - case CSSValueAppworkspace: - color = convertNSColorToColor([NSColor headerColor]); - break; - case CSSValueBackground: - // Use theme independent default - break; - case CSSValueButtonface: - // We use this value instead of NSColor's controlColor to avoid website incompatibilities. - // We may want to change this to use the NSColor in future. - color = 0xFFC0C0C0; - break; - case CSSValueButtonhighlight: - color = convertNSColorToColor([NSColor controlHighlightColor]); - break; - case CSSValueButtonshadow: - color = convertNSColorToColor([NSColor controlShadowColor]); - break; - case CSSValueButtontext: - color = convertNSColorToColor([NSColor controlTextColor]); - break; - case CSSValueCaptiontext: - color = convertNSColorToColor([NSColor textColor]); - break; - case CSSValueGraytext: - color = convertNSColorToColor([NSColor disabledControlTextColor]); - break; - case CSSValueHighlight: - color = convertNSColorToColor([NSColor selectedTextBackgroundColor]); - break; - case CSSValueHighlighttext: - color = convertNSColorToColor([NSColor selectedTextColor]); - break; - case CSSValueInactiveborder: - color = convertNSColorToColor([NSColor controlBackgroundColor]); - break; - case CSSValueInactivecaption: - color = convertNSColorToColor([NSColor controlBackgroundColor]); - break; - case CSSValueInactivecaptiontext: - color = convertNSColorToColor([NSColor textColor]); - break; - case CSSValueInfobackground: - // There is no corresponding NSColor for this so we use a hard coded value. - color = 0xFFFBFCC5; - break; - case CSSValueInfotext: - color = convertNSColorToColor([NSColor textColor]); - break; - case CSSValueMenu: - color = menuBackgroundColor(); - break; - case CSSValueMenutext: - color = convertNSColorToColor([NSColor selectedMenuItemTextColor]); - break; - case CSSValueScrollbar: - color = convertNSColorToColor([NSColor scrollBarColor]); - break; - case CSSValueText: - color = convertNSColorToColor([NSColor textColor]); - break; - case CSSValueThreeddarkshadow: - color = convertNSColorToColor([NSColor controlDarkShadowColor]); - break; - case CSSValueThreedshadow: - color = convertNSColorToColor([NSColor shadowColor]); - break; - case CSSValueThreedface: - // We use this value instead of NSColor's controlColor to avoid website incompatibilities. - // We may want to change this to use the NSColor in future. - color = 0xFFC0C0C0; - break; - case CSSValueThreedhighlight: - color = convertNSColorToColor([NSColor highlightColor]); - break; - case CSSValueThreedlightshadow: - color = convertNSColorToColor([NSColor controlLightHighlightColor]); - break; - case CSSValueWebkitFocusRingColor: - color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]); - break; - case CSSValueWindow: - color = convertNSColorToColor([NSColor windowBackgroundColor]); - break; - case CSSValueWindowframe: - color = convertNSColorToColor([NSColor windowFrameColor]); - break; - case CSSValueWindowtext: - color = convertNSColorToColor([NSColor windowFrameTextColor]); - break; + case CSSValueActiveborder: + color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]); + break; + case CSSValueActivecaption: + color = convertNSColorToColor([NSColor windowFrameTextColor]); + break; + case CSSValueAppworkspace: + color = convertNSColorToColor([NSColor headerColor]); + break; + case CSSValueBackground: + // Use theme independent default + break; + case CSSValueButtonface: + // We use this value instead of NSColor's controlColor to avoid website incompatibilities. + // We may want to change this to use the NSColor in future. + color = 0xFFC0C0C0; + break; + case CSSValueButtonhighlight: + color = convertNSColorToColor([NSColor controlHighlightColor]); + break; + case CSSValueButtonshadow: + color = convertNSColorToColor([NSColor controlShadowColor]); + break; + case CSSValueButtontext: + color = convertNSColorToColor([NSColor controlTextColor]); + break; + case CSSValueCaptiontext: + color = convertNSColorToColor([NSColor textColor]); + break; + case CSSValueGraytext: + color = convertNSColorToColor([NSColor disabledControlTextColor]); + break; + case CSSValueHighlight: + color = convertNSColorToColor([NSColor selectedTextBackgroundColor]); + break; + case CSSValueHighlighttext: + color = convertNSColorToColor([NSColor selectedTextColor]); + break; + case CSSValueInactiveborder: + color = convertNSColorToColor([NSColor controlBackgroundColor]); + break; + case CSSValueInactivecaption: + color = convertNSColorToColor([NSColor controlBackgroundColor]); + break; + case CSSValueInactivecaptiontext: + color = convertNSColorToColor([NSColor textColor]); + break; + case CSSValueInfobackground: + // There is no corresponding NSColor for this so we use a hard coded value. + color = 0xFFFBFCC5; + break; + case CSSValueInfotext: + color = convertNSColorToColor([NSColor textColor]); + break; + case CSSValueMenu: + color = menuBackgroundColor(); + break; + case CSSValueMenutext: + color = convertNSColorToColor([NSColor selectedMenuItemTextColor]); + break; + case CSSValueScrollbar: + color = convertNSColorToColor([NSColor scrollBarColor]); + break; + case CSSValueText: + color = convertNSColorToColor([NSColor textColor]); + break; + case CSSValueThreeddarkshadow: + color = convertNSColorToColor([NSColor controlDarkShadowColor]); + break; + case CSSValueThreedshadow: + color = convertNSColorToColor([NSColor shadowColor]); + break; + case CSSValueThreedface: + // We use this value instead of NSColor's controlColor to avoid website incompatibilities. + // We may want to change this to use the NSColor in future. + color = 0xFFC0C0C0; + break; + case CSSValueThreedhighlight: + color = convertNSColorToColor([NSColor highlightColor]); + break; + case CSSValueThreedlightshadow: + color = convertNSColorToColor([NSColor controlLightHighlightColor]); + break; + case CSSValueWebkitFocusRingColor: + color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]); + break; + case CSSValueWindow: + color = convertNSColorToColor([NSColor windowBackgroundColor]); + break; + case CSSValueWindowframe: + color = convertNSColorToColor([NSColor windowFrameColor]); + break; + case CSSValueWindowtext: + color = convertNSColorToColor([NSColor windowFrameTextColor]); + break; } if (!color.isValid()) @@ -457,7 +500,7 @@ Color RenderThemeChromiumMac::systemColor(int cssValueId) const } bool RenderThemeChromiumMac::isControlStyled(const RenderStyle* style, const BorderData& border, - const FillLayer& background, const Color& backgroundColor) const + const FillLayer& background, const Color& backgroundColor) const { if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart || style->appearance() == ListboxPart) return style->border() != border; @@ -472,62 +515,32 @@ bool RenderThemeChromiumMac::isControlStyled(const RenderStyle* style, const Bor return RenderTheme::isControlStyled(style, border, background, backgroundColor); } -// FIXME: Use the code from the old upstream version, before it was converted to the new theme API in r37731. void RenderThemeChromiumMac::adjustRepaintRect(const RenderObject* o, IntRect& r) { - float zoomLevel = o->style()->effectiveZoom(); - - switch (o->style()->appearance()) { - case CheckboxPart: { - // Since we query the prototype cell, we need to update its state to match. - setCheckboxCellState(o, r); - - // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox - // shadow" and the check. We don't consider this part of the bounds of the control in WebKit. - IntSize size = checkboxSizes()[[checkbox() controlSize]]; - size.setHeight(size.height() * zoomLevel); - size.setWidth(size.width() * zoomLevel); - r = inflateRect(r, size, checkboxMargins(), zoomLevel); - break; + ControlPart part = o->style()->appearance(); + +#if USE(NEW_THEME) + switch (part) { + case CheckboxPart: + case RadioPart: + case PushButtonPart: + case SquareButtonPart: + case DefaultButtonPart: + case ButtonPart: + return RenderTheme::adjustRepaintRect(o, r); + default: + break; } - case RadioPart: { - // Since we query the prototype cell, we need to update its state to match. - setRadioCellState(o, r); +#endif - // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox - // shadow" and the check. We don't consider this part of the bounds of the control in WebKit. - IntSize size = radioSizes()[[radio() controlSize]]; - size.setHeight(size.height() * zoomLevel); - size.setWidth(size.width() * zoomLevel); - r = inflateRect(r, size, radioMargins(), zoomLevel); - break; - } - case PushButtonPart: - case DefaultButtonPart: - case ButtonPart: { - // Since we query the prototype cell, we need to update its state to match. - setButtonCellState(o, r); - - // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox - // shadow" and the check. We don't consider this part of the bounds of the control in WebKit. - if ([button() bezelStyle] == NSRoundedBezelStyle) { - IntSize size = buttonSizes()[[button() controlSize]]; - size.setHeight(size.height() * zoomLevel); - size.setWidth(r.width()); - r = inflateRect(r, size, buttonMargins(), zoomLevel); - } - break; - } - case MenulistPart: { + float zoomLevel = o->style()->effectiveZoom(); + + if (part == MenulistPart) { setPopupButtonCellState(o, r); IntSize size = popupButtonSizes()[[popupButton() controlSize]]; size.setHeight(size.height() * zoomLevel); size.setWidth(r.width()); r = inflateRect(r, size, popupButtonMargins(), zoomLevel); - break; - } - default: - break; } } @@ -535,20 +548,61 @@ IntRect RenderThemeChromiumMac::inflateRect(const IntRect& r, const IntSize& siz { // Only do the inflation if the available width/height are too small. Otherwise try to // fit the glow/check space into the available box's width/height. - int widthDelta = r.width() - (size.width() + margins[LeftMargin] * zoomLevel + margins[RightMargin] * zoomLevel); - int heightDelta = r.height() - (size.height() + margins[TopMargin] * zoomLevel + margins[BottomMargin] * zoomLevel); + int widthDelta = r.width() - (size.width() + margins[leftMargin] * zoomLevel + margins[rightMargin] * zoomLevel); + int heightDelta = r.height() - (size.height() + margins[topMargin] * zoomLevel + margins[bottomMargin] * zoomLevel); IntRect result(r); if (widthDelta < 0) { - result.setX(result.x() - margins[LeftMargin] * zoomLevel); + result.setX(result.x() - margins[leftMargin] * zoomLevel); result.setWidth(result.width() - widthDelta); } if (heightDelta < 0) { - result.setY(result.y() - margins[TopMargin] * zoomLevel); + result.setY(result.y() - margins[topMargin] * zoomLevel); result.setHeight(result.height() - heightDelta); } return result; } +FloatRect RenderThemeChromiumMac::convertToPaintingRect(const RenderObject* inputRenderer, const RenderObject* partRenderer, const FloatRect& inputRect, const IntRect& r) const +{ + FloatRect partRect(inputRect); + + // Compute an offset between the part renderer and the input renderer + FloatSize offsetFromInputRenderer; + const RenderObject* renderer = partRenderer; + while (renderer && renderer != inputRenderer) { + RenderObject* containingRenderer = renderer->container(); + offsetFromInputRenderer -= renderer->offsetFromContainer(containingRenderer); + renderer = containingRenderer; + } + // If the input renderer was not a container, something went wrong + ASSERT(renderer == inputRenderer); + // Move the rect into partRenderer's coords + partRect.move(offsetFromInputRenderer); + // Account for the local drawing offset (tx, ty) + partRect.move(r.x(), r.y()); + + return partRect; +} + +// Updates the control tint (a.k.a. active state) of |cell| (from |o|). +// In the Chromium port, the renderer runs as a background process and controls' +// NSCell(s) lack a parent NSView. Therefore controls don't have their tint +// color updated correctly when the application is activated/deactivated. +// FocusController's setActive() is called when the application is +// activated/deactivated, which causes a repaint at which time this code is +// called. +// This function should be called before drawing any NSCell-derived controls, +// unless you're sure it isn't needed. +void RenderThemeChromiumMac::updateActiveState(NSCell* cell, const RenderObject* o) +{ + NSControlTint oldTint = [cell controlTint]; + NSControlTint tint = isActive(o) ? [NSColor currentControlTint] : + NSClearControlTint; + + if (tint != oldTint) + [cell setControlTint:tint]; +} + void RenderThemeChromiumMac::updateCheckedState(NSCell* cell, const RenderObject* o) { bool oldIndeterminate = [cell state] == NSMixedState; @@ -589,19 +643,6 @@ void RenderThemeChromiumMac::updatePressedState(NSCell* cell, const RenderObject [cell setHighlighted:pressed]; } -// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731. -int RenderThemeChromiumMac::baselinePosition(const RenderObject* o) const -{ - if (!o->isBox()) - return 0; - - if (o->style()->appearance() == CheckboxPart || o->style()->appearance() == RadioPart) { - const RenderBox* box = toRenderBox(o); - return box->marginTop() + box->height() - 2 * o->style()->effectiveZoom(); // The baseline is 2px up from the bottom of the checkbox/radio in AppKit. - } - return RenderTheme::baselinePosition(o); -} - bool RenderThemeChromiumMac::controlSupportsTints(const RenderObject* o) const { // An alternate way to implement this would be to get the appropriate cell object @@ -673,7 +714,7 @@ void RenderThemeChromiumMac::setSizeFromFont(RenderStyle* style, const IntSize* style->setHeight(Length(size.height(), Fixed)); } -void RenderThemeChromiumMac::setFontFromControlSize(CSSStyleSelector* selector, RenderStyle* style, NSControlSize controlSize) const +void RenderThemeChromiumMac::setFontFromControlSize(CSSStyleSelector*, RenderStyle* style, NSControlSize controlSize) const { FontDescription fontDescription; fontDescription.setIsAbsoluteSize(true); @@ -701,349 +742,10 @@ NSControlSize RenderThemeChromiumMac::controlSizeForSystemFont(RenderStyle* styl return NSMiniControlSize; } -// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731. -bool RenderThemeChromiumMac::paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) -{ - LocalCurrentGraphicsContext localContext(paintInfo.context); - - // Determine the width and height needed for the control and prepare the cell for painting. - setCheckboxCellState(o, r); - - paintInfo.context->save(); - - float zoomLevel = o->style()->effectiveZoom(); - - // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox - // shadow" and the check. We don't consider this part of the bounds of the control in WebKit. - NSButtonCell* checkbox = this->checkbox(); - IntSize size = checkboxSizes()[[checkbox controlSize]]; - size.setWidth(size.width() * zoomLevel); - size.setHeight(size.height() * zoomLevel); - IntRect inflatedRect = inflateRect(r, size, checkboxMargins(), zoomLevel); - - if (zoomLevel != 1.0f) { - inflatedRect.setWidth(inflatedRect.width() / zoomLevel); - inflatedRect.setHeight(inflatedRect.height() / zoomLevel); - paintInfo.context->translate(inflatedRect.x(), inflatedRect.y()); - paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel)); - paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y()); - } - - [checkbox drawWithFrame:NSRect(IntRectToNSRect(inflatedRect)) inView:nil]; - [checkbox setControlView:nil]; - - paintInfo.context->restore(); - - return false; -} - -// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731. -const IntSize* RenderThemeChromiumMac::checkboxSizes() const -{ - static const IntSize sizes[3] = { IntSize(14, 14), IntSize(12, 12), IntSize(10, 10) }; - return sizes; -} - -// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731. -const int* RenderThemeChromiumMac::checkboxMargins() const -{ - static const int margins[3][4] = - { - { 3, 4, 4, 2 }, - { 4, 3, 3, 3 }, - { 4, 3, 3, 3 }, - }; - return margins[[checkbox() controlSize]]; -} - -// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731. -void RenderThemeChromiumMac::setCheckboxCellState(const RenderObject* o, const IntRect& r) -{ - NSButtonCell* checkbox = this->checkbox(); - - // Set the control size based off the rectangle we're painting into. - setControlSize(checkbox, checkboxSizes(), r.size(), o->style()->effectiveZoom()); - - // Update the various states we respond to. - updateCheckedState(checkbox, o); - updateEnabledState(checkbox, o); - updatePressedState(checkbox, o); - updateFocusedState(checkbox, o); -} - -// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731. -void RenderThemeChromiumMac::setCheckboxSize(RenderStyle* style) const -{ - // If the width and height are both specified, then we have nothing to do. - if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto()) - return; - - // Use the font size to determine the intrinsic width of the control. - setSizeFromFont(style, checkboxSizes()); -} - -// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731. -bool RenderThemeChromiumMac::paintRadio(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) -{ - LocalCurrentGraphicsContext localContext(paintInfo.context); - - // Determine the width and height needed for the control and prepare the cell for painting. - setRadioCellState(o, r); - - paintInfo.context->save(); - - float zoomLevel = o->style()->effectiveZoom(); - - // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox - // shadow" and the check. We don't consider this part of the bounds of the control in WebKit. - NSButtonCell* radio = this->radio(); - IntSize size = radioSizes()[[radio controlSize]]; - size.setWidth(size.width() * zoomLevel); - size.setHeight(size.height() * zoomLevel); - IntRect inflatedRect = inflateRect(r, size, radioMargins(), zoomLevel); - - if (zoomLevel != 1.0f) { - inflatedRect.setWidth(inflatedRect.width() / zoomLevel); - inflatedRect.setHeight(inflatedRect.height() / zoomLevel); - paintInfo.context->translate(inflatedRect.x(), inflatedRect.y()); - paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel)); - paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y()); - } - - [radio drawWithFrame:NSRect(IntRectToNSRect(inflatedRect)) inView:nil]; - [radio setControlView:nil]; - - paintInfo.context->restore(); - - return false; -} - -// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731. -const IntSize* RenderThemeChromiumMac::radioSizes() const -{ - static const IntSize sizes[3] = { IntSize(14, 15), IntSize(12, 13), IntSize(10, 10) }; - return sizes; -} - -// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731. -const int* RenderThemeChromiumMac::radioMargins() const -{ - static const int margins[3][4] = - { - { 2, 2, 4, 2 }, - { 3, 2, 3, 2 }, - { 1, 0, 2, 0 }, - }; - return margins[[radio() controlSize]]; -} - -// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731. -void RenderThemeChromiumMac::setRadioCellState(const RenderObject* o, const IntRect& r) -{ - NSButtonCell* radio = this->radio(); - - // Set the control size based off the rectangle we're painting into. - setControlSize(radio, radioSizes(), r.size(), o->style()->effectiveZoom()); - - // Update the various states we respond to. - updateCheckedState(radio, o); - updateEnabledState(radio, o); - updatePressedState(radio, o); - updateFocusedState(radio, o); -} - -// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731. -void RenderThemeChromiumMac::setRadioSize(RenderStyle* style) const -{ - // If the width and height are both specified, then we have nothing to do. - if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto()) - return; - - // Use the font size to determine the intrinsic width of the control. - setSizeFromFont(style, radioSizes()); -} - -// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731. -void RenderThemeChromiumMac::setButtonPaddingFromControlSize(RenderStyle* style, NSControlSize size) const -{ - // Just use 8px. AppKit wants to use 11px for mini buttons, but that padding is just too large - // for real-world Web sites (creating a huge necessary minimum width for buttons whose space is - // by definition constrained, since we select mini only for small cramped environments. - // This also guarantees the HTML4 <button> will match our rendering by default, since we're using a consistent - // padding. - const int padding = 8 * style->effectiveZoom(); - style->setPaddingLeft(Length(padding, Fixed)); - style->setPaddingRight(Length(padding, Fixed)); - style->setPaddingTop(Length(0, Fixed)); - style->setPaddingBottom(Length(0, Fixed)); -} - -// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731. -void RenderThemeChromiumMac::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const -{ - // There are three appearance constants for buttons. - // (1) Push-button is the constant for the default Aqua system button. Push buttons will not scale vertically and will not allow - // custom fonts or colors. <input>s use this constant. This button will allow custom colors and font weights/variants but won't - // scale vertically. - // (2) square-button is the constant for the square button. This button will allow custom fonts and colors and will scale vertically. - // (3) Button is the constant that means "pick the best button as appropriate." <button>s use this constant. This button will - // also scale vertically and allow custom fonts and colors. It will attempt to use Aqua if possible and will make this determination - // solely on the rectangle of the control. - - // Determine our control size based off our font. - NSControlSize controlSize = controlSizeForFont(style); - - if (style->appearance() == PushButtonPart) { - // Ditch the border. - style->resetBorder(); - - // Height is locked to auto. - style->setHeight(Length(Auto)); - - // White-space is locked to pre - style->setWhiteSpace(PRE); - - // Set the button's vertical size. - setButtonSize(style); - - // Add in the padding that we'd like to use. - setButtonPaddingFromControlSize(style, controlSize); - - // Our font is locked to the appropriate system font size for the control. To clarify, we first use the CSS-specified font to figure out - // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate - // system font for the control size instead. - setFontFromControlSize(selector, style, controlSize); - } else { - // Set a min-height so that we can't get smaller than the mini button. - style->setMinHeight(Length(static_cast<int>(15 * style->effectiveZoom()), Fixed)); - - // Reset the top and bottom borders. - style->resetBorderTop(); - style->resetBorderBottom(); - } - - style->setBoxShadow(0); -} - -// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731. -const IntSize* RenderThemeChromiumMac::buttonSizes() const -{ - static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) }; - return sizes; -} - -// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731. -const int* RenderThemeChromiumMac::buttonMargins() const -{ - static const int margins[3][4] = - { - { 4, 6, 7, 6 }, - { 4, 5, 6, 5 }, - { 0, 1, 1, 1 }, - }; - return margins[[button() controlSize]]; -} - -// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731. -void RenderThemeChromiumMac::setButtonSize(RenderStyle* style) const -{ - // If the width and height are both specified, then we have nothing to do. - if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto()) - return; - - // Use the font size to determine the intrinsic width of the control. - setSizeFromFont(style, buttonSizes()); -} - -// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731. -void RenderThemeChromiumMac::setButtonCellState(const RenderObject* o, const IntRect& r) -{ - NSButtonCell* button = this->button(); - - // Set the control size based off the rectangle we're painting into. - if (o->style()->appearance() == SquareButtonPart || - r.height() > buttonSizes()[NSRegularControlSize].height() * o->style()->effectiveZoom()) { - // Use the square button - if ([button bezelStyle] != NSShadowlessSquareBezelStyle) - [button setBezelStyle:NSShadowlessSquareBezelStyle]; - } else if ([button bezelStyle] != NSRoundedBezelStyle) - [button setBezelStyle:NSRoundedBezelStyle]; - - setControlSize(button, buttonSizes(), r.size(), o->style()->effectiveZoom()); - - NSWindow *window = [nil window]; - BOOL isDefaultButton = (isDefault(o) && [window isKeyWindow]); - [button setKeyEquivalent:(isDefaultButton ? @"\r" : @"")]; - - // Update the various states we respond to. - updateCheckedState(button, o); - updateEnabledState(button, o); - updatePressedState(button, o); - updateFocusedState(button, o); -} - -// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731. -bool RenderThemeChromiumMac::paintButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) -{ - NSButtonCell* button = this->button(); - LocalCurrentGraphicsContext localContext(paintInfo.context); - - // Determine the width and height needed for the control and prepare the cell for painting. - setButtonCellState(o, r); - - paintInfo.context->save(); - - // We inflate the rect as needed to account for padding included in the cell to accommodate the button - // shadow. We don't consider this part of the bounds of the control in WebKit. - float zoomLevel = o->style()->effectiveZoom(); - IntSize size = buttonSizes()[[button controlSize]]; - size.setWidth(r.width()); - size.setHeight(size.height() * zoomLevel); - IntRect inflatedRect = r; - if ([button bezelStyle] == NSRoundedBezelStyle) { - // Center the button within the available space. - if (inflatedRect.height() > size.height()) { - inflatedRect.setY(inflatedRect.y() + (inflatedRect.height() - size.height()) / 2); - inflatedRect.setHeight(size.height()); - } - - // Now inflate it to account for the shadow. - inflatedRect = inflateRect(inflatedRect, size, buttonMargins(), zoomLevel); - - if (zoomLevel != 1.0f) { - inflatedRect.setWidth(inflatedRect.width() / zoomLevel); - inflatedRect.setHeight(inflatedRect.height() / zoomLevel); - paintInfo.context->translate(inflatedRect.x(), inflatedRect.y()); - paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel)); - paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y()); - } - } - - NSView *view = nil; - NSWindow *window = [view window]; - NSButtonCell *previousDefaultButtonCell = [window defaultButtonCell]; - - if (isDefault(o) && [window isKeyWindow]) { - [window setDefaultButtonCell:button]; - wkAdvanceDefaultButtonPulseAnimation(button); - } else if ([previousDefaultButtonCell isEqual:button]) - [window setDefaultButtonCell:nil]; - - [button drawWithFrame:NSRect(IntRectToNSRect(inflatedRect)) inView:view]; - [button setControlView:nil]; - - if (![previousDefaultButtonCell isEqual:button]) - [window setDefaultButtonCell:previousDefaultButtonCell]; - - paintInfo.context->restore(); - - return false; -} - bool RenderThemeChromiumMac::paintTextField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { LocalCurrentGraphicsContext localContext(paintInfo.context); - wkDrawBezeledTextFieldCell(IntRectToNSRect(r), isEnabled(o) && !isReadOnlyControl(o)); + wkDrawBezeledTextFieldCell(r, isEnabled(o) && !isReadOnlyControl(o)); return false; } @@ -1051,7 +753,7 @@ void RenderThemeChromiumMac::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle { } -bool RenderThemeChromiumMac::paintCapsLockIndicator(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +bool RenderThemeChromiumMac::paintCapsLockIndicator(RenderObject*, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { if (paintInfo.context->paintingDisabled()) return true; @@ -1065,7 +767,7 @@ bool RenderThemeChromiumMac::paintCapsLockIndicator(RenderObject* o, const Rende bool RenderThemeChromiumMac::paintTextArea(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { LocalCurrentGraphicsContext localContext(paintInfo.context); - wkDrawBezeledTextArea(IntRectToNSRect(r), isEnabled(o) && !isReadOnlyControl(o)); + wkDrawBezeledTextArea(r, isEnabled(o) && !isReadOnlyControl(o)); return false; } @@ -1103,8 +805,6 @@ const int* RenderThemeChromiumMac::popupButtonPadding(NSControlSize size) const bool RenderThemeChromiumMac::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { - LocalCurrentGraphicsContext localContext(paintInfo.context); - setPopupButtonCellState(o, r); NSPopUpButtonCell* popupButton = this->popupButton(); @@ -1134,7 +834,7 @@ bool RenderThemeChromiumMac::paintMenuList(RenderObject* o, const RenderObject:: paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y()); } - [popupButton drawWithFrame:IntRectToNSRect(inflatedRect) inView:nil]; + [popupButton drawWithFrame:inflatedRect inView:FlippedView()]; [popupButton setControlView:nil]; paintInfo.context->restore(); @@ -1142,19 +842,19 @@ bool RenderThemeChromiumMac::paintMenuList(RenderObject* o, const RenderObject:: return false; } -static const float baseFontSize = 11.0f; -static const float baseArrowHeight = 4.0f; -static const float baseArrowWidth = 5.0f; -static const float baseSpaceBetweenArrows = 2.0f; -static const int arrowPaddingLeft = 6; -static const int arrowPaddingRight = 6; -static const int paddingBeforeSeparator = 4; -static const int baseBorderRadius = 5; -static const int styledPopupPaddingLeft = 8; -static const int styledPopupPaddingTop = 1; -static const int styledPopupPaddingBottom = 2; +const float baseFontSize = 11.0f; +const float baseArrowHeight = 4.0f; +const float baseArrowWidth = 5.0f; +const float baseSpaceBetweenArrows = 2.0f; +const int arrowPaddingLeft = 6; +const int arrowPaddingRight = 6; +const int paddingBeforeSeparator = 4; +const int baseBorderRadius = 5; +const int styledPopupPaddingLeft = 8; +const int styledPopupPaddingTop = 1; +const int styledPopupPaddingBottom = 2; -static void TopGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData) +static void TopGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData) { static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.4f }; static float light[4] = { 1.0f, 1.0f, 1.0f, 0.15f }; @@ -1164,7 +864,7 @@ static void TopGradientInterpolate(void* info, const CGFloat* inData, CGFloat* o outData[i] = (1.0f - a) * dark[i] + a * light[i]; } -static void BottomGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData) +static void BottomGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData) { static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.0f }; static float light[4] = { 1.0f, 1.0f, 1.0f, 0.3f }; @@ -1174,7 +874,7 @@ static void BottomGradientInterpolate(void* info, const CGFloat* inData, CGFloat outData[i] = (1.0f - a) * dark[i] + a * light[i]; } -static void MainGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData) +static void MainGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData) { static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.15f }; static float light[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; @@ -1184,7 +884,7 @@ static void MainGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData[i] = (1.0f - a) * dark[i] + a * light[i]; } -static void TrackGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData) +static void TrackGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData) { static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.678f }; static float light[4] = { 0.0f, 0.0f, 0.0f, 0.13f }; @@ -1196,11 +896,21 @@ static void TrackGradientInterpolate(void* info, const CGFloat* inData, CGFloat* void RenderThemeChromiumMac::paintMenuListButtonGradients(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { + if (r.isEmpty()) + return; + CGContextRef context = paintInfo.context->platformContext(); paintInfo.context->save(); - int radius = o->style()->borderTopLeftRadius().width(); + IntSize topLeftRadius; + IntSize topRightRadius; + IntSize bottomLeftRadius; + IntSize bottomRightRadius; + + o->style()->getBorderRadiiForRect(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius); + + int radius = topLeftRadius.width(); RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB()); @@ -1223,33 +933,27 @@ void RenderThemeChromiumMac::paintMenuListButtonGradients(RenderObject* o, const RetainPtr<CGShadingRef> rightShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.right(), r.y()), CGPointMake(r.right() - radius, r.y()), mainFunction.get(), false, false)); paintInfo.context->save(); CGContextClipToRect(context, r); - paintInfo.context->addRoundedRectClip(r, - o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(), - o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius()); + paintInfo.context->addRoundedRectClip(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius); CGContextDrawShading(context, mainShading.get()); paintInfo.context->restore(); paintInfo.context->save(); CGContextClipToRect(context, topGradient); - paintInfo.context->addRoundedRectClip(enclosingIntRect(topGradient), - o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(), - IntSize(), IntSize()); + paintInfo.context->addRoundedRectClip(enclosingIntRect(topGradient), topLeftRadius, topRightRadius, IntSize(), IntSize()); CGContextDrawShading(context, topShading.get()); paintInfo.context->restore(); - paintInfo.context->save(); - CGContextClipToRect(context, bottomGradient); - paintInfo.context->addRoundedRectClip(enclosingIntRect(bottomGradient), - IntSize(), IntSize(), - o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius()); - CGContextDrawShading(context, bottomShading.get()); - paintInfo.context->restore(); + if (!bottomGradient.isEmpty()) { + paintInfo.context->save(); + CGContextClipToRect(context, bottomGradient); + paintInfo.context->addRoundedRectClip(enclosingIntRect(bottomGradient), IntSize(), IntSize(), bottomLeftRadius, bottomRightRadius); + CGContextDrawShading(context, bottomShading.get()); + paintInfo.context->restore(); + } paintInfo.context->save(); CGContextClipToRect(context, r); - paintInfo.context->addRoundedRectClip(r, - o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(), - o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius()); + paintInfo.context->addRoundedRectClip(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius); CGContextDrawShading(context, leftShading.get()); CGContextDrawShading(context, rightShading.get()); paintInfo.context->restore(); @@ -1259,8 +963,6 @@ void RenderThemeChromiumMac::paintMenuListButtonGradients(RenderObject* o, const bool RenderThemeChromiumMac::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { - paintInfo.context->save(); - IntRect bounds = IntRect(r.x() + o->style()->borderLeftWidth(), r.y() + o->style()->borderTopWidth(), r.width() - o->style()->borderLeftWidth() - o->style()->borderRightWidth(), @@ -1279,6 +981,8 @@ bool RenderThemeChromiumMac::paintMenuListButton(RenderObject* o, const RenderOb if (bounds.width() < arrowWidth + arrowPaddingLeft * o->style()->effectiveZoom()) return false; + paintInfo.context->save(); + paintInfo.context->setFillColor(o->style()->color()); paintInfo.context->setStrokeStyle(NoStroke); @@ -1357,7 +1061,7 @@ void RenderThemeChromiumMac::adjustMenuListStyle(CSSStyleSelector* selector, Ren int RenderThemeChromiumMac::popupInternalPaddingLeft(RenderStyle* style) const { if (style->appearance() == MenulistPart) - return popupButtonPadding(controlSizeForFont(style))[LeftPadding] * style->effectiveZoom(); + return popupButtonPadding(controlSizeForFont(style))[leftPadding] * style->effectiveZoom(); if (style->appearance() == MenulistButtonPart) return styledPopupPaddingLeft * style->effectiveZoom(); return 0; @@ -1366,7 +1070,7 @@ int RenderThemeChromiumMac::popupInternalPaddingLeft(RenderStyle* style) const int RenderThemeChromiumMac::popupInternalPaddingRight(RenderStyle* style) const { if (style->appearance() == MenulistPart) - return popupButtonPadding(controlSizeForFont(style))[RightPadding] * style->effectiveZoom(); + return popupButtonPadding(controlSizeForFont(style))[rightPadding] * style->effectiveZoom(); if (style->appearance() == MenulistButtonPart) { float fontScale = style->fontSize() / baseFontSize; float arrowWidth = baseArrowWidth * fontScale; @@ -1378,7 +1082,7 @@ int RenderThemeChromiumMac::popupInternalPaddingRight(RenderStyle* style) const int RenderThemeChromiumMac::popupInternalPaddingTop(RenderStyle* style) const { if (style->appearance() == MenulistPart) - return popupButtonPadding(controlSizeForFont(style))[TopPadding] * style->effectiveZoom(); + return popupButtonPadding(controlSizeForFont(style))[topPadding] * style->effectiveZoom(); if (style->appearance() == MenulistButtonPart) return styledPopupPaddingTop * style->effectiveZoom(); return 0; @@ -1387,13 +1091,13 @@ int RenderThemeChromiumMac::popupInternalPaddingTop(RenderStyle* style) const int RenderThemeChromiumMac::popupInternalPaddingBottom(RenderStyle* style) const { if (style->appearance() == MenulistPart) - return popupButtonPadding(controlSizeForFont(style))[BottomPadding] * style->effectiveZoom(); + return popupButtonPadding(controlSizeForFont(style))[bottomPadding] * style->effectiveZoom(); if (style->appearance() == MenulistButtonPart) return styledPopupPaddingBottom * style->effectiveZoom(); return 0; } -void RenderThemeChromiumMac::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const +void RenderThemeChromiumMac::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const { float fontScale = style->fontSize() / baseFontSize; @@ -1414,6 +1118,7 @@ void RenderThemeChromiumMac::setPopupButtonCellState(const RenderObject* o, cons setControlSize(popupButton, popupButtonSizes(), r.size(), o->style()->effectiveZoom()); // Update the various states we respond to. + updateActiveState(popupButton, o); updateCheckedState(popupButton, o); updateEnabledState(popupButton, o); updatePressedState(popupButton, o); @@ -1431,16 +1136,16 @@ int RenderThemeChromiumMac::minimumMenuListSize(RenderStyle* style) const return sizeForSystemFont(style, menuListSizes()).width(); } -static const int trackWidth = 5; -static const int trackRadius = 2; - -void RenderThemeChromiumMac::adjustSliderTrackStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const +void RenderThemeChromiumMac::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle* style, Element*) const { style->setBoxShadow(0); } bool RenderThemeChromiumMac::paintSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { + static const int trackWidth = 5; + static const int trackRadius = 2; + IntRect bounds = r; float zoomLevel = o->style()->effectiveZoom(); float zoomedTrackWidth = trackWidth * zoomLevel; @@ -1478,12 +1183,12 @@ bool RenderThemeChromiumMac::paintSliderTrack(RenderObject* o, const RenderObjec return false; } -void RenderThemeChromiumMac::adjustSliderThumbStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const +void RenderThemeChromiumMac::adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle* style, Element*) const { style->setBoxShadow(0); } -static const float verticalSliderHeightPadding = 0.1f; +const float verticalSliderHeightPadding = 0.1f; bool RenderThemeChromiumMac::paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { @@ -1496,6 +1201,7 @@ bool RenderThemeChromiumMac::paintSliderThumb(RenderObject* o, const RenderObjec LocalCurrentGraphicsContext localContext(paintInfo.context); // Update the various states we respond to. + updateActiveState(sliderThumbCell, o); updateEnabledState(sliderThumbCell, o->parent()); updateFocusedState(sliderThumbCell, o->parent()); @@ -1537,7 +1243,7 @@ bool RenderThemeChromiumMac::paintSliderThumb(RenderObject* o, const RenderObjec paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); } - [sliderThumbCell drawWithFrame:FloatRectToNSRect(unzoomedRect) inView:nil]; + [sliderThumbCell drawWithFrame:unzoomedRect inView:FlippedView()]; [sliderThumbCell setControlView:nil]; paintInfo.context->restore(); @@ -1545,21 +1251,20 @@ bool RenderThemeChromiumMac::paintSliderThumb(RenderObject* o, const RenderObjec return false; } -const int sliderThumbWidth = 15; -const int sliderThumbHeight = 15; -const int mediaSliderThumbWidth = 13; -const int mediaSliderThumbHeight = 14; - void RenderThemeChromiumMac::adjustSliderThumbSize(RenderObject* o) const { + static const int sliderThumbWidth = 15; + static const int sliderThumbHeight = 15; + float zoomLevel = o->style()->effectiveZoom(); if (o->style()->appearance() == SliderThumbHorizontalPart || o->style()->appearance() == SliderThumbVerticalPart) { o->style()->setWidth(Length(static_cast<int>(sliderThumbWidth * zoomLevel), Fixed)); o->style()->setHeight(Length(static_cast<int>(sliderThumbHeight * zoomLevel), Fixed)); - } else if (o->style()->appearance() == MediaSliderThumbPart) { - o->style()->setWidth(Length(mediaSliderThumbWidth, Fixed)); - o->style()->setHeight(Length(mediaSliderThumbHeight, Fixed)); } + +#if ENABLE(VIDEO) + RenderMediaControlsChromium::adjustMediaSliderThumbSize(o); +#endif } bool RenderThemeChromiumMac::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) @@ -1586,7 +1291,7 @@ bool RenderThemeChromiumMac::paintSearchField(RenderObject* o, const RenderObjec // Set the search button to nil before drawing. Then reset it so we can draw it later. [search setSearchButtonCell:nil]; - [search drawWithFrame:NSRect(IntRectToNSRect(unzoomedRect)) inView:nil]; + [search drawWithFrame:NSRect(unzoomedRect) inView:FlippedView()]; #ifdef BUILDING_ON_TIGER if ([search showsFirstResponder]) wkDrawTextFieldCellFocusRing(search, NSRect(unzoomedRect)); @@ -1600,13 +1305,14 @@ bool RenderThemeChromiumMac::paintSearchField(RenderObject* o, const RenderObjec return false; } -void RenderThemeChromiumMac::setSearchCellState(RenderObject* o, const IntRect& r) +void RenderThemeChromiumMac::setSearchCellState(RenderObject* o, const IntRect&) { NSSearchFieldCell* search = this->search(); [search setControlSize:controlSizeForFont(o->style())]; // Update the various states we respond to. + updateActiveState(search, o); updateEnabledState(search, o); updateFocusedState(search, o); } @@ -1627,7 +1333,7 @@ void RenderThemeChromiumMac::setSearchFieldSize(RenderStyle* style) const setSizeFromFont(style, searchFieldSizes()); } -void RenderThemeChromiumMac::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const +void RenderThemeChromiumMac::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element*) const { // Override border. style->resetBorder(); @@ -1660,22 +1366,25 @@ void RenderThemeChromiumMac::adjustSearchFieldStyle(CSSStyleSelector* selector, bool RenderThemeChromiumMac::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { - LocalCurrentGraphicsContext localContext(paintInfo.context); - Node* input = o->node()->shadowAncestorNode(); + if (!input->renderer()->isBox()) + return false; + setSearchCellState(input->renderer(), r); NSSearchFieldCell* search = this->search(); + updateActiveState([search cancelButtonCell], o); updatePressedState([search cancelButtonCell], o); paintInfo.context->save(); float zoomLevel = o->style()->effectiveZoom(); - NSRect bounds = [search cancelButtonRectForBounds:NSRect(IntRectToNSRect(input->renderer()->absoluteBoundingBoxRect()))]; - - IntRect unzoomedRect(NSRectToIntRect(bounds)); + FloatRect localBounds = [search cancelButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())]; + localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r); + + FloatRect unzoomedRect(localBounds); if (zoomLevel != 1.0f) { unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); @@ -1684,7 +1393,7 @@ bool RenderThemeChromiumMac::paintSearchFieldCancelButton(RenderObject* o, const paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); } - [[search cancelButtonCell] drawWithFrame:IntRectToNSRect(unzoomedRect) inView:nil]; + [[search cancelButtonCell] drawWithFrame:unzoomedRect inView:FlippedView()]; [[search cancelButtonCell] setControlView:nil]; paintInfo.context->restore(); @@ -1697,7 +1406,7 @@ const IntSize* RenderThemeChromiumMac::cancelButtonSizes() const return sizes; } -void RenderThemeChromiumMac::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const +void RenderThemeChromiumMac::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const { IntSize size = sizeForSystemFont(style, cancelButtonSizes()); style->setWidth(Length(size.width(), Fixed)); @@ -1711,8 +1420,8 @@ const IntSize* RenderThemeChromiumMac::resultsButtonSizes() const return sizes; } -static const int emptyResultsOffset = 9; -void RenderThemeChromiumMac::adjustSearchFieldDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const +const int emptyResultsOffset = 9; +void RenderThemeChromiumMac::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const { IntSize size = sizeForSystemFont(style, resultsButtonSizes()); style->setWidth(Length(size.width() - emptyResultsOffset, Fixed)); @@ -1720,12 +1429,12 @@ void RenderThemeChromiumMac::adjustSearchFieldDecorationStyle(CSSStyleSelector* style->setBoxShadow(0); } -bool RenderThemeChromiumMac::paintSearchFieldDecoration(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +bool RenderThemeChromiumMac::paintSearchFieldDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return false; } -void RenderThemeChromiumMac::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const +void RenderThemeChromiumMac::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const { IntSize size = sizeForSystemFont(style, resultsButtonSizes()); style->setWidth(Length(size.width(), Fixed)); @@ -1735,24 +1444,29 @@ void RenderThemeChromiumMac::adjustSearchFieldResultsDecorationStyle(CSSStyleSel bool RenderThemeChromiumMac::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { - LocalCurrentGraphicsContext localContext(paintInfo.context); - Node* input = o->node()->shadowAncestorNode(); + if (!input->renderer()->isBox()) + return false; + setSearchCellState(input->renderer(), r); NSSearchFieldCell* search = this->search(); + updateActiveState([search searchButtonCell], o); + if ([search searchMenuTemplate] != nil) [search setSearchMenuTemplate:nil]; - NSRect bounds = [search searchButtonRectForBounds:NSRect(IntRectToNSRect(input->renderer()->absoluteBoundingBoxRect()))]; - [[search searchButtonCell] drawWithFrame:bounds inView:nil]; + FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())]; + localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r); + + [[search searchButtonCell] drawWithFrame:localBounds inView:FlippedView()]; [[search searchButtonCell] setControlView:nil]; return false; } -static const int resultsArrowWidth = 5; -void RenderThemeChromiumMac::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const +const int resultsArrowWidth = 5; +void RenderThemeChromiumMac::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const { IntSize size = sizeForSystemFont(style, resultsButtonSizes()); style->setWidth(Length(size.width() + resultsArrowWidth, Fixed)); @@ -1762,13 +1476,16 @@ void RenderThemeChromiumMac::adjustSearchFieldResultsButtonStyle(CSSStyleSelecto bool RenderThemeChromiumMac::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { - LocalCurrentGraphicsContext localContext(paintInfo.context); - Node* input = o->node()->shadowAncestorNode(); + if (!input->renderer()->isBox()) + return false; + setSearchCellState(input->renderer(), r); NSSearchFieldCell* search = this->search(); + updateActiveState([search searchButtonCell], o); + if (![search searchMenuTemplate]) [search setSearchMenuTemplate:searchMenuTemplate()]; @@ -1776,9 +1493,10 @@ bool RenderThemeChromiumMac::paintSearchFieldResultsButton(RenderObject* o, cons float zoomLevel = o->style()->effectiveZoom(); - NSRect bounds = [search searchButtonRectForBounds:NSRect(IntRectToNSRect(input->renderer()->absoluteBoundingBoxRect()))]; + FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())]; + localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r); - IntRect unzoomedRect(NSRectToIntRect(bounds)); + IntRect unzoomedRect(localBounds); if (zoomLevel != 1.0f) { unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); @@ -1787,7 +1505,7 @@ bool RenderThemeChromiumMac::paintSearchFieldResultsButton(RenderObject* o, cons paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); } - [[search searchButtonCell] drawWithFrame:IntRectToNSRect(unzoomedRect) inView:nil]; + [[search searchButtonCell] drawWithFrame:unzoomedRect inView:FlippedView()]; [[search searchButtonCell] setControlView:nil]; paintInfo.context->restore(); @@ -1796,179 +1514,53 @@ bool RenderThemeChromiumMac::paintSearchFieldResultsButton(RenderObject* o, cons } #if ENABLE(VIDEO) -// FIXME: This enum is lifted from RenderThemeMac.mm We need to decide which theme to use for the default controls, or decide to avoid wkDrawMediaUIPart and render our own. -typedef enum { - MediaControllerThemeClassic = 1, - MediaControllerThemeQT = 2 -} MediaControllerThemeStyle; - -enum WKMediaControllerThemeState { - MediaUIPartDisabledFlag = 1 << 0, - MediaUIPartPressedFlag = 1 << 1, - MediaUIPartDrawEndCapsFlag = 1 << 3, -}; -#endif - -bool RenderThemeChromiumMac::paintMediaFullscreenButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +bool RenderThemeChromiumMac::shouldRenderMediaControlPart(ControlPart part, Element* e) { -#if ENABLE(VIDEO) - Node* node = o->node(); - if (!node) - return false; - - LocalCurrentGraphicsContext localContext(paintInfo.context); - wkDrawMediaUIPart(MediaFullscreenButton, MediaControllerThemeClassic, paintInfo.context->platformContext(), r, - node->active() ? MediaUIPartPressedFlag : 0); -#endif - return false; + return RenderMediaControlsChromium::shouldRenderMediaControlPart(part, e); } -bool RenderThemeChromiumMac::paintMediaMuteButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +bool RenderThemeChromiumMac::paintMediaPlayButton(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) { -#if ENABLE(VIDEO) - Node* node = o->node(); - Node* mediaNode = node ? node->shadowAncestorNode() : 0; - if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag))) - return false; - - HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode); - if (!mediaElement) - return false; - - LocalCurrentGraphicsContext localContext(paintInfo.context); - wkDrawMediaUIPart(mediaElement->muted() ? MediaUnMuteButton : MediaMuteButton, MediaControllerThemeClassic, paintInfo.context->platformContext(), r, - node->active() ? MediaUIPartPressedFlag : 0); -#endif - return false; + return RenderMediaControlsChromium::paintMediaControlsPart(MediaPlayButton, object, paintInfo, rect); } -bool RenderThemeChromiumMac::paintMediaPlayButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +bool RenderThemeChromiumMac::paintMediaMuteButton(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) { -#if ENABLE(VIDEO) - Node* node = o->node(); - Node* mediaNode = node ? node->shadowAncestorNode() : 0; - if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag))) - return false; - - HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode); - if (!mediaElement) - return false; - - LocalCurrentGraphicsContext localContext(paintInfo.context); - wkDrawMediaUIPart(mediaElement->canPlay() ? MediaPlayButton : MediaPauseButton, MediaControllerThemeClassic, paintInfo.context->platformContext(), r, - node->active() ? MediaUIPartPressedFlag : 0); -#endif - return false; + return RenderMediaControlsChromium::paintMediaControlsPart(MediaMuteButton, object, paintInfo, rect); } -bool RenderThemeChromiumMac::paintMediaSeekBackButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +bool RenderThemeChromiumMac::paintMediaSliderTrack(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) { -#if ENABLE(VIDEO) - Node* node = o->node(); - if (!node) - return false; - - LocalCurrentGraphicsContext localContext(paintInfo.context); - wkDrawMediaUIPart(MediaSeekBackButton, MediaControllerThemeClassic, paintInfo.context->platformContext(), r, - node->active() ? MediaUIPartPressedFlag : 0); -#endif - return false; + return RenderMediaControlsChromium::paintMediaControlsPart(MediaSlider, object, paintInfo, rect); } -bool RenderThemeChromiumMac::paintMediaSeekForwardButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +bool RenderThemeChromiumMac::paintMediaVolumeSliderTrack(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) { -#if ENABLE(VIDEO) - Node* node = o->node(); - if (!node) - return false; - - LocalCurrentGraphicsContext localContext(paintInfo.context); - wkDrawMediaUIPart(MediaSeekForwardButton, MediaControllerThemeClassic, paintInfo.context->platformContext(), r, - node->active() ? MediaUIPartPressedFlag : 0); -#endif - return false; + return RenderMediaControlsChromium::paintMediaControlsPart(MediaVolumeSlider, object, paintInfo, rect); } -bool RenderThemeChromiumMac::paintMediaSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +bool RenderThemeChromiumMac::paintMediaSliderThumb(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) { -#if ENABLE(VIDEO) - Node* node = o->node(); - Node* mediaNode = node ? node->shadowAncestorNode() : 0; - if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag))) - return false; - - HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode); - if (!mediaElement) - return false; - - float timeLoaded = 0; - float currentTime = 0; - float duration = 0; - if (MediaPlayer* player = mediaElement->player()) { - duration = player->duration(); - timeLoaded = player->maxTimeBuffered(); - currentTime = player->currentTime(); - } - - bool shouldDrawEndCaps = !toRenderMedia(mediaElement->renderer())->shouldShowTimeDisplayControls(); - wkDrawMediaSliderTrack(MediaControllerThemeClassic, paintInfo.context->platformContext(), r, timeLoaded, currentTime, duration, shouldDrawEndCaps ? MediaUIPartDrawEndCapsFlag : 0); -#endif - return false; + return RenderMediaControlsChromium::paintMediaControlsPart(MediaSliderThumb, object, paintInfo, rect); } -bool RenderThemeChromiumMac::paintMediaSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +bool RenderThemeChromiumMac::paintMediaVolumeSliderThumb(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) { -#if ENABLE(VIDEO) - Node* node = o->node(); - if (!node) - return false; - - LocalCurrentGraphicsContext localContext(paintInfo.context); - wkDrawMediaUIPart(MediaSliderThumb, MediaControllerThemeClassic, paintInfo.context->platformContext(), r, - node->active() ? MediaUIPartPressedFlag : 0); -#endif - return false; + return RenderMediaControlsChromium::paintMediaControlsPart(MediaVolumeSliderThumb, object, paintInfo, rect); } -// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731. -NSButtonCell* RenderThemeChromiumMac::checkbox() const +bool RenderThemeChromiumMac::paintMediaControlsBackground(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) { - if (!m_checkbox) { - m_checkbox.adoptNS([[NSButtonCell alloc] init]); - [m_checkbox.get() setButtonType:NSSwitchButton]; - [m_checkbox.get() setTitle:nil]; - [m_checkbox.get() setAllowsMixedState:YES]; - [m_checkbox.get() setFocusRingType:NSFocusRingTypeExterior]; - } - - return m_checkbox.get(); + return RenderMediaControlsChromium::paintMediaControlsPart(MediaTimelineContainer, object, paintInfo, rect); } - -// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731. -NSButtonCell* RenderThemeChromiumMac::radio() const -{ - if (!m_radio) { - m_radio.adoptNS([[NSButtonCell alloc] init]); - [m_radio.get() setButtonType:NSRadioButton]; - [m_radio.get() setTitle:nil]; - [m_radio.get() setFocusRingType:NSFocusRingTypeExterior]; - } - return m_radio.get(); -} - -// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731. -NSButtonCell* RenderThemeChromiumMac::button() const +String RenderThemeChromiumMac::extraMediaControlsStyleSheet() { - if (!m_button) { - m_button.adoptNS([[NSButtonCell alloc] init]); - [m_button.get() setTitle:nil]; - [m_button.get() setButtonType:NSMomentaryPushInButton]; - } - - return m_button.get(); + return String(mediaControlsChromiumUserAgentStyleSheet, sizeof(mediaControlsChromiumUserAgentStyleSheet)); } +#endif + NSPopUpButtonCell* RenderThemeChromiumMac::popupButton() const { if (!m_popupButton) { diff --git a/WebCore/rendering/RenderThemeChromiumSkia.cpp b/WebCore/rendering/RenderThemeChromiumSkia.cpp index 79804ac..3a39423 100644 --- a/WebCore/rendering/RenderThemeChromiumSkia.cpp +++ b/WebCore/rendering/RenderThemeChromiumSkia.cpp @@ -33,8 +33,11 @@ #include "MediaControlElements.h" #include "PlatformContextSkia.h" #include "RenderBox.h" +#include "RenderMediaControlsChromium.h" #include "RenderObject.h" +#include "RenderSlider.h" #include "ScrollbarTheme.h" +#include "TimeRanges.h" #include "TransformationMatrix.h" #include "UserAgentStyleSheets.h" @@ -70,19 +73,29 @@ static void setSizeIfAuto(RenderStyle* style, const IntSize& size) style->setHeight(Length(size.height(), Fixed)); } -#if ENABLE(VIDEO) -// Attempt to retrieve a HTMLMediaElement from a Node. Returns NULL if one cannot be found. -static HTMLMediaElement* mediaElementParent(Node* node) +static void drawVertLine(SkCanvas* canvas, int x, int y1, int y2, const SkPaint& paint) { - if (!node) - return 0; - Node* mediaNode = node->shadowAncestorNode(); - if (!mediaNode || (!mediaNode->hasTagName(HTMLNames::videoTag) && !mediaNode->hasTagName(HTMLNames::audioTag))) - return 0; + SkIRect skrect; + skrect.set(x, y1, x + 1, y2 + 1); + canvas->drawIRect(skrect, paint); +} - return static_cast<HTMLMediaElement*>(mediaNode); +static void drawHorizLine(SkCanvas* canvas, int x1, int x2, int y, const SkPaint& paint) +{ + SkIRect skrect; + skrect.set(x1, y, x2 + 1, y + 1); + canvas->drawIRect(skrect, paint); +} + +static void drawBox(SkCanvas* canvas, const IntRect& rect, const SkPaint& paint) +{ + const int right = rect.x() + rect.width() - 1; + const int bottom = rect.y() + rect.height() - 1; + drawHorizLine(canvas, rect.x(), right, rect.y(), paint); + drawVertLine(canvas, right, rect.y(), bottom, paint); + drawHorizLine(canvas, rect.x(), right, bottom, paint); + drawVertLine(canvas, rect.x(), rect.y(), bottom, paint); } -#endif // We aim to match IE here. // -IE uses a font based on the encoding as the default font for form controls. @@ -302,7 +315,7 @@ static void paintButtonLike(RenderTheme* theme, RenderObject* o, const RenderObj canvas->drawLine(rect.x() + 1, bottom - 1, right - 1, bottom - 1, paint); canvas->drawLine(rect.x(), rect.y() + 1, rect.x(), bottom - 1, paint); - paint.setARGB(0xff, 0, 0, 0); + paint.setColor(SK_ColorBLACK); SkPoint p[2]; const int lightEnd = theme->isPressed(o) ? 1 : 0; const int darkEnd = !lightEnd; @@ -460,42 +473,10 @@ bool RenderThemeChromiumSkia::paintSearchFieldResultsButton(RenderObject* o, con return false; } -bool RenderThemeChromiumSkia::paintMediaButtonInternal(GraphicsContext* context, const IntRect& rect, Image* image) -{ - // Create a destination rectangle for the image that is centered in the drawing rectangle, rounded left, and down. - IntRect imageRect = image->rect(); - imageRect.setY(rect.y() + (rect.height() - image->height() + 1) / 2); - imageRect.setX(rect.x() + (rect.width() - image->width() + 1) / 2); - - context->drawImage(image, imageRect); - return true; -} - bool RenderThemeChromiumSkia::paintMediaControlsBackground(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) { #if ENABLE(VIDEO) - HTMLMediaElement* mediaElement = mediaElementParent(object->node()); - if (!mediaElement) - return false; - - if (!rect.isEmpty()) - { - SkCanvas* canvas = paintInfo.context->platformContext()->canvas(); - SkPaint paint; - - // Draws the left border, it is always 1px wide. - paint.setColor(object->style()->borderLeftColor().rgb()); - canvas->drawLine(rect.x() + 1, rect.y(), - rect.x() + 1, rect.y() + rect.height(), - paint); - - // Draws the right border, it is always 1px wide. - paint.setColor(object->style()->borderRightColor().rgb()); - canvas->drawLine(rect.x() + rect.width() - 1, rect.y(), - rect.x() + rect.width() - 1, rect.y() + rect.height(), - paint); - } - return true; + return RenderMediaControlsChromium::paintMediaControlsPart(MediaTimelineContainer, object, paintInfo, rect); #else UNUSED_PARAM(object); UNUSED_PARAM(paintInfo); @@ -507,62 +488,7 @@ bool RenderThemeChromiumSkia::paintMediaControlsBackground(RenderObject* object, bool RenderThemeChromiumSkia::paintMediaSliderTrack(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) { #if ENABLE(VIDEO) - HTMLMediaElement* mediaElement = mediaElementParent(object->node()); - if (!mediaElement) - return false; - - SkCanvas* canvas = paintInfo.context->platformContext()->canvas(); - SkRect backgroundRect; - backgroundRect.set(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height()); - - SkPaint paint; - paint.setAntiAlias(true); - - // Draw the border of the time bar. The border only has one single color, - // width and radius. So use the property of the left border. - SkColor borderColor = object->style()->borderLeftColor().rgb(); - int borderWidth = object->style()->borderLeftWidth(); - IntSize borderRadius = object->style()->borderTopLeftRadius(); - paint.setStyle(SkPaint::kStroke_Style); - paint.setStrokeWidth(borderWidth); - paint.setColor(borderColor); - canvas->drawRoundRect(backgroundRect, borderRadius.width(), borderRadius.height(), paint); - - // Draw the background of the time bar. - SkColor backgroundColor = object->style()->backgroundColor().rgb(); - paint.setStyle(SkPaint::kFill_Style); - paint.setColor(backgroundColor); - canvas->drawRoundRect(backgroundRect, borderRadius.width(), borderRadius.height(), paint); - - if (backgroundRect.width() >= 3 && backgroundRect.height() >= 3) - { - // Draw the buffered ranges. - // FIXME: Draw multiple ranges if there are multiple buffered ranges. - SkRect bufferedRect; - bufferedRect.set(backgroundRect.fLeft + 2, backgroundRect.fTop + 2, - backgroundRect.fRight - 1, backgroundRect.fBottom - 1); - int width = static_cast<int>(bufferedRect.width() * mediaElement->percentLoaded()); - bufferedRect.fRight = bufferedRect.fLeft + width; - - SkPoint points[2] = { { 0, bufferedRect.fTop }, { 0, bufferedRect.fBottom } }; - SkColor startColor = object->style()->color().rgb(); - SkColor endColor = SkColorSetRGB(SkColorGetR(startColor) / 2, - SkColorGetG(startColor) / 2, - SkColorGetB(startColor) / 2); - SkColor colors[2] = { startColor, endColor }; - SkShader* gradient = SkGradientShader::CreateLinear(points, colors, 0, - sizeof(points) / sizeof(points[0]), - SkShader::kMirror_TileMode, 0); - - paint.reset(); - paint.setShader(gradient); - paint.setAntiAlias(true); - // Check for round rect with zero width or height, otherwise Skia will assert - if (bufferedRect.width() > 0 && bufferedRect.height() > 0) - canvas->drawRoundRect(bufferedRect, borderRadius.width(), borderRadius.height(), paint); - gradient->unref(); - } - return true; + return RenderMediaControlsChromium::paintMediaControlsPart(MediaSlider, object, paintInfo, rect); #else UNUSED_PARAM(object); UNUSED_PARAM(paintInfo); @@ -571,14 +497,22 @@ bool RenderThemeChromiumSkia::paintMediaSliderTrack(RenderObject* object, const #endif } -void RenderThemeChromiumSkia::adjustSliderThumbSize(RenderObject* object) const { +bool RenderThemeChromiumSkia::paintMediaVolumeSliderTrack(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) +{ #if ENABLE(VIDEO) - if (object->style()->appearance() == MediaSliderThumbPart) { - static Image* mediaSliderThumb = Image::loadPlatformResource("mediaSliderThumb").releaseRef(); + return RenderMediaControlsChromium::paintMediaControlsPart(MediaVolumeSlider, object, paintInfo, rect); +#else + UNUSED_PARAM(object); + UNUSED_PARAM(paintInfo); + UNUSED_PARAM(rect); + return false; +#endif +} - object->style()->setWidth(Length(mediaSliderThumb->width(), Fixed)); - object->style()->setHeight(Length(mediaSliderThumb->height(), Fixed)); - } +void RenderThemeChromiumSkia::adjustSliderThumbSize(RenderObject* object) const +{ +#if ENABLE(VIDEO) + RenderMediaControlsChromium::adjustMediaSliderThumbSize(object); #else UNUSED_PARAM(object); #endif @@ -587,12 +521,19 @@ void RenderThemeChromiumSkia::adjustSliderThumbSize(RenderObject* object) const bool RenderThemeChromiumSkia::paintMediaSliderThumb(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) { #if ENABLE(VIDEO) - if (!object->parent()->isSlider()) - return false; - - static Image* mediaSliderThumb = Image::loadPlatformResource("mediaSliderThumb").releaseRef(); + return RenderMediaControlsChromium::paintMediaControlsPart(MediaSliderThumb, object, paintInfo, rect); +#else + UNUSED_PARAM(object); + UNUSED_PARAM(paintInfo); + UNUSED_PARAM(rect); + return false; +#endif +} - return paintMediaButtonInternal(paintInfo.context, rect, mediaSliderThumb); +bool RenderThemeChromiumSkia::paintMediaVolumeSliderThumb(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) +{ +#if ENABLE(VIDEO) + return RenderMediaControlsChromium::paintMediaControlsPart(MediaVolumeSliderThumb, object, paintInfo, rect); #else UNUSED_PARAM(object); UNUSED_PARAM(paintInfo); @@ -604,14 +545,7 @@ bool RenderThemeChromiumSkia::paintMediaSliderThumb(RenderObject* object, const bool RenderThemeChromiumSkia::paintMediaPlayButton(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) { #if ENABLE(VIDEO) - HTMLMediaElement* mediaElement = mediaElementParent(object->node()); - if (!mediaElement) - return false; - - static Image* mediaPlay = Image::loadPlatformResource("mediaPlay").releaseRef(); - static Image* mediaPause = Image::loadPlatformResource("mediaPause").releaseRef(); - - return paintMediaButtonInternal(paintInfo.context, rect, mediaElement->paused() ? mediaPlay : mediaPause); + return RenderMediaControlsChromium::paintMediaControlsPart(MediaPlayButton, object, paintInfo, rect); #else UNUSED_PARAM(object); UNUSED_PARAM(paintInfo); @@ -623,14 +557,7 @@ bool RenderThemeChromiumSkia::paintMediaPlayButton(RenderObject* object, const R bool RenderThemeChromiumSkia::paintMediaMuteButton(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) { #if ENABLE(VIDEO) - HTMLMediaElement* mediaElement = mediaElementParent(object->node()); - if (!mediaElement) - return false; - - static Image* soundFull = Image::loadPlatformResource("mediaSoundFull").releaseRef(); - static Image* soundNone = Image::loadPlatformResource("mediaSoundNone").releaseRef(); - - return paintMediaButtonInternal(paintInfo.context, rect, mediaElement->muted() ? soundNone: soundFull); + return RenderMediaControlsChromium::paintMediaControlsPart(MediaMuteButton, object, paintInfo, rect); #else UNUSED_PARAM(object); UNUSED_PARAM(paintInfo); @@ -654,7 +581,7 @@ bool RenderThemeChromiumSkia::paintMenuList(RenderObject* o, const RenderObject: paintButtonLike(this, o, i, rect); SkPaint paint; - paint.setARGB(0xff, 0, 0, 0); + paint.setColor(SK_ColorBLACK); paint.setAntiAlias(true); paint.setStyle(SkPaint::kFill_Style); @@ -679,6 +606,69 @@ bool RenderThemeChromiumSkia::paintMenuListButton(RenderObject* o, const RenderO return paintMenuList(o, i, rect); } +bool RenderThemeChromiumSkia::paintSliderTrack(RenderObject*, const RenderObject::PaintInfo& i, const IntRect& rect) +{ + // Just paint a grey box for now (matches the color of a scrollbar background. + SkCanvas* const canvas = i.context->platformContext()->canvas(); + int verticalCenter = rect.y() + rect.height() / 2; + int top = std::max(rect.y(), verticalCenter - 2); + int bottom = std::min(rect.y() + rect.height(), verticalCenter + 2); + + SkPaint paint; + const SkColor grey = SkColorSetARGB(0xff, 0xe3, 0xdd, 0xd8); + paint.setColor(grey); + + SkRect skrect; + skrect.set(rect.x(), top, rect.x() + rect.width(), bottom); + canvas->drawRect(skrect, paint); + + return false; +} + +bool RenderThemeChromiumSkia::paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) +{ + // Make a thumb similar to the scrollbar thumb. + const bool hovered = isHovered(o) || toRenderSlider(o->parent())->inDragMode(); + const int midx = rect.x() + rect.width() / 2; + const int midy = rect.y() + rect.height() / 2; + const bool vertical = (o->style()->appearance() == SliderThumbVerticalPart); + SkCanvas* const canvas = i.context->platformContext()->canvas(); + + const SkColor thumbLightGrey = SkColorSetARGB(0xff, 0xf4, 0xf2, 0xef); + const SkColor thumbDarkGrey = SkColorSetARGB(0xff, 0xea, 0xe5, 0xe0); + SkPaint paint; + paint.setColor(hovered ? SK_ColorWHITE : thumbLightGrey); + + SkIRect skrect; + if (vertical) + skrect.set(rect.x(), rect.y(), midx + 1, rect.bottom()); + else + skrect.set(rect.x(), rect.y(), rect.right(), midy + 1); + + canvas->drawIRect(skrect, paint); + + paint.setColor(hovered ? thumbLightGrey : thumbDarkGrey); + + if (vertical) + skrect.set(midx + 1, rect.y(), rect.right(), rect.bottom()); + else + skrect.set(rect.x(), midy + 1, rect.right(), rect.bottom()); + + canvas->drawIRect(skrect, paint); + + const SkColor borderDarkGrey = SkColorSetARGB(0xff, 0x9d, 0x96, 0x8e); + paint.setColor(borderDarkGrey); + drawBox(canvas, rect, paint); + + if (rect.height() > 10 && rect.width() > 10) { + drawHorizLine(canvas, midx - 2, midx + 2, midy, paint); + drawHorizLine(canvas, midx - 2, midx + 2, midy - 3, paint); + drawHorizLine(canvas, midx - 2, midx + 2, midy + 3, paint); + } + + return false; +} + int RenderThemeChromiumSkia::popupInternalPaddingLeft(RenderStyle* style) const { return menuListInternalPadding(style, LeftPadding); @@ -719,6 +709,13 @@ int RenderThemeChromiumSkia::buttonInternalPaddingBottom() const return 1; } +#if ENABLE(VIDEO) +bool RenderThemeChromiumSkia::shouldRenderMediaControlPart(ControlPart part, Element* e) +{ + return RenderMediaControlsChromium::shouldRenderMediaControlPart(part, e); +} +#endif + // static void RenderThemeChromiumSkia::setDefaultFontSize(int fontSize) { diff --git a/WebCore/rendering/RenderThemeChromiumSkia.h b/WebCore/rendering/RenderThemeChromiumSkia.h index 7544c22..98e3a35 100644 --- a/WebCore/rendering/RenderThemeChromiumSkia.h +++ b/WebCore/rendering/RenderThemeChromiumSkia.h @@ -91,8 +91,10 @@ namespace WebCore { virtual bool paintMediaControlsBackground(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual bool paintMediaSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual bool paintMediaVolumeSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual void adjustSliderThumbSize(RenderObject*) const; virtual bool paintMediaSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual bool paintMediaVolumeSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual bool paintMediaPlayButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual bool paintMediaMuteButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); @@ -110,6 +112,9 @@ namespace WebCore { virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; virtual bool paintMenuListButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual bool paintSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual bool paintSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + // These methods define the padding for the MenuList's inner block. virtual int popupInternalPaddingLeft(RenderStyle*) const; virtual int popupInternalPaddingRight(RenderStyle*) const; @@ -121,6 +126,11 @@ namespace WebCore { virtual int buttonInternalPaddingTop() const; virtual int buttonInternalPaddingBottom() const; +#if ENABLE(VIDEO) + // Media controls + virtual bool shouldRenderMediaControlPart(ControlPart, Element*); +#endif + // Provide a way to pass the default font size from the Settings object // to the render theme. FIXME: http://b/1129186 A cleaner way would be // to remove the default font size from this object and have callers diff --git a/WebCore/rendering/RenderThemeChromiumWin.cpp b/WebCore/rendering/RenderThemeChromiumWin.cpp index 35d1580..20503f3 100644 --- a/WebCore/rendering/RenderThemeChromiumWin.cpp +++ b/WebCore/rendering/RenderThemeChromiumWin.cpp @@ -311,6 +311,52 @@ void RenderThemeChromiumWin::systemFont(int propId, FontDescription& fontDescrip fontDescription = *cachedDesc; } +// Map a CSSValue* system color to an index understood by GetSysColor(). +static int cssValueIdToSysColorIndex(int cssValueId) +{ + switch (cssValueId) { + case CSSValueActiveborder: return COLOR_ACTIVEBORDER; + case CSSValueActivecaption: return COLOR_ACTIVECAPTION; + case CSSValueAppworkspace: return COLOR_APPWORKSPACE; + case CSSValueBackground: return COLOR_BACKGROUND; + case CSSValueButtonface: return COLOR_BTNFACE; + case CSSValueButtonhighlight: return COLOR_BTNHIGHLIGHT; + case CSSValueButtonshadow: return COLOR_BTNSHADOW; + case CSSValueButtontext: return COLOR_BTNTEXT; + case CSSValueCaptiontext: return COLOR_CAPTIONTEXT; + case CSSValueGraytext: return COLOR_GRAYTEXT; + case CSSValueHighlight: return COLOR_HIGHLIGHT; + case CSSValueHighlighttext: return COLOR_HIGHLIGHTTEXT; + case CSSValueInactiveborder: return COLOR_INACTIVEBORDER; + case CSSValueInactivecaption: return COLOR_INACTIVECAPTION; + case CSSValueInactivecaptiontext: return COLOR_INACTIVECAPTIONTEXT; + case CSSValueInfobackground: return COLOR_INFOBK; + case CSSValueInfotext: return COLOR_INFOTEXT; + case CSSValueMenu: return COLOR_MENU; + case CSSValueMenutext: return COLOR_MENUTEXT; + case CSSValueScrollbar: return COLOR_SCROLLBAR; + case CSSValueThreeddarkshadow: return COLOR_3DDKSHADOW; + case CSSValueThreedface: return COLOR_3DFACE; + case CSSValueThreedhighlight: return COLOR_3DHIGHLIGHT; + case CSSValueThreedlightshadow: return COLOR_3DLIGHT; + case CSSValueThreedshadow: return COLOR_3DSHADOW; + case CSSValueWindow: return COLOR_WINDOW; + case CSSValueWindowframe: return COLOR_WINDOWFRAME; + case CSSValueWindowtext: return COLOR_WINDOWTEXT; + default: return -1; // Unsupported CSSValue + } +} + +Color RenderThemeChromiumWin::systemColor(int cssValueId) const +{ + int sysColorIndex = cssValueIdToSysColorIndex(cssValueId); + if (ChromiumBridge::layoutTestMode() || (sysColorIndex == -1)) + return RenderTheme::systemColor(cssValueId); + + COLORREF color = GetSysColor(sysColorIndex); + return Color(GetRValue(color), GetGValue(color), GetBValue(color)); +} + void RenderThemeChromiumWin::adjustSliderThumbSize(RenderObject* o) const { // These sizes match what WinXP draws for various menus. @@ -475,14 +521,36 @@ unsigned RenderThemeChromiumWin::determineSliderThumbState(RenderObject* o) unsigned RenderThemeChromiumWin::determineClassicState(RenderObject* o) { unsigned result = 0; - if (!isEnabled(o)) - result = DFCS_INACTIVE; - else if (isPressed(o)) // Active supersedes hover - result = DFCS_PUSHED; - else if (isHovered(o)) - result = DFCS_HOT; - if (isChecked(o)) - result |= DFCS_CHECKED; + + ControlPart part = o->style()->appearance(); + + // Sliders are always in the normal state. + if (part == SliderHorizontalPart || part == SliderVerticalPart) + return result; + + // So are readonly text fields. + if (isReadOnlyControl(o) && (part == TextFieldPart || part == TextAreaPart || part == SearchFieldPart)) + return result; + + if (part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart) { + if (!isEnabled(o->parent())) + result = DFCS_INACTIVE; + else if (toRenderSlider(o->parent())->inDragMode()) // Active supersedes hover + result = DFCS_PUSHED; + else if (isHovered(o)) + result = DFCS_HOT; + } else { + if (!isEnabled(o)) + result = DFCS_INACTIVE; + else if (isPressed(o)) // Active supersedes hover + result = DFCS_PUSHED; + else if (supportsFocus(part) && isFocused(o)) // So does focused + result = 0; + else if (isHovered(o)) + result = DFCS_HOT; + if (isChecked(o)) + result |= DFCS_CHECKED; + } return result; } @@ -524,6 +592,7 @@ ThemeData RenderThemeChromiumWin::getThemeData(RenderObject* o) break; case ListboxPart: case MenulistPart: + case MenulistButtonPart: case SearchFieldPart: case TextFieldPart: case TextAreaPart: diff --git a/WebCore/rendering/RenderThemeChromiumWin.h b/WebCore/rendering/RenderThemeChromiumWin.h index 5e98c9b..3b86980 100644 --- a/WebCore/rendering/RenderThemeChromiumWin.h +++ b/WebCore/rendering/RenderThemeChromiumWin.h @@ -59,6 +59,7 @@ namespace WebCore { // System fonts. virtual void systemFont(int propId, FontDescription&) const; + virtual Color systemColor(int cssValueId) const;
virtual void adjustSliderThumbSize(RenderObject*) const; diff --git a/WebCore/rendering/RenderThemeMac.h b/WebCore/rendering/RenderThemeMac.h index 85f141f..1d68c63 100644 --- a/WebCore/rendering/RenderThemeMac.h +++ b/WebCore/rendering/RenderThemeMac.h @@ -132,6 +132,8 @@ protected: // Media controls virtual String extraMediaControlsStyleSheet(); + + virtual bool shouldRenderMediaControlPart(ControlPart, Element*); #endif private: diff --git a/WebCore/rendering/RenderThemeMac.mm b/WebCore/rendering/RenderThemeMac.mm index 6315f9f..03e39a0 100644 --- a/WebCore/rendering/RenderThemeMac.mm +++ b/WebCore/rendering/RenderThemeMac.mm @@ -38,6 +38,7 @@ #import "RenderSlider.h" #import "RenderView.h" #import "SharedBuffer.h" +#import "TimeRanges.h" #import "WebCoreSystemInterface.h" #import "UserAgentStyleSheets.h" #import <Carbon/Carbon.h> @@ -472,6 +473,7 @@ void RenderThemeMac::adjustRepaintRect(const RenderObject* o, IntRect& r) case RadioPart: case PushButtonPart: case SquareButtonPart: + case ListButtonPart: case DefaultButtonPart: case ButtonPart: return RenderTheme::adjustRepaintRect(o, r); @@ -824,11 +826,21 @@ static void TrackGradientInterpolate(void*, const CGFloat* inData, CGFloat* outD void RenderThemeMac::paintMenuListButtonGradients(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { + if (r.isEmpty()) + return; + CGContextRef context = paintInfo.context->platformContext(); paintInfo.context->save(); - int radius = o->style()->borderTopLeftRadius().width(); + IntSize topLeftRadius; + IntSize topRightRadius; + IntSize bottomLeftRadius; + IntSize bottomRightRadius; + + o->style()->getBorderRadiiForRect(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius); + + int radius = topLeftRadius.width(); RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB()); @@ -851,33 +863,27 @@ void RenderThemeMac::paintMenuListButtonGradients(RenderObject* o, const RenderO RetainPtr<CGShadingRef> rightShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.right(), r.y()), CGPointMake(r.right() - radius, r.y()), mainFunction.get(), false, false)); paintInfo.context->save(); CGContextClipToRect(context, r); - paintInfo.context->addRoundedRectClip(r, - o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(), - o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius()); + paintInfo.context->addRoundedRectClip(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius); CGContextDrawShading(context, mainShading.get()); paintInfo.context->restore(); paintInfo.context->save(); CGContextClipToRect(context, topGradient); - paintInfo.context->addRoundedRectClip(enclosingIntRect(topGradient), - o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(), - IntSize(), IntSize()); + paintInfo.context->addRoundedRectClip(enclosingIntRect(topGradient), topLeftRadius, topRightRadius, IntSize(), IntSize()); CGContextDrawShading(context, topShading.get()); paintInfo.context->restore(); - paintInfo.context->save(); - CGContextClipToRect(context, bottomGradient); - paintInfo.context->addRoundedRectClip(enclosingIntRect(bottomGradient), - IntSize(), IntSize(), - o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius()); - CGContextDrawShading(context, bottomShading.get()); - paintInfo.context->restore(); + if (!bottomGradient.isEmpty()) { + paintInfo.context->save(); + CGContextClipToRect(context, bottomGradient); + paintInfo.context->addRoundedRectClip(enclosingIntRect(bottomGradient), IntSize(), IntSize(), bottomLeftRadius, bottomRightRadius); + CGContextDrawShading(context, bottomShading.get()); + paintInfo.context->restore(); + } paintInfo.context->save(); CGContextClipToRect(context, r); - paintInfo.context->addRoundedRectClip(r, - o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(), - o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius()); + paintInfo.context->addRoundedRectClip(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius); CGContextDrawShading(context, leftShading.get()); CGContextDrawShading(context, rightShading.get()); paintInfo.context->restore(); @@ -887,8 +893,6 @@ void RenderThemeMac::paintMenuListButtonGradients(RenderObject* o, const RenderO bool RenderThemeMac::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { - paintInfo.context->save(); - IntRect bounds = IntRect(r.x() + o->style()->borderLeftWidth(), r.y() + o->style()->borderTopWidth(), r.width() - o->style()->borderLeftWidth() - o->style()->borderRightWidth(), @@ -907,6 +911,8 @@ bool RenderThemeMac::paintMenuListButton(RenderObject* o, const RenderObject::Pa if (bounds.width() < arrowWidth + arrowPaddingLeft * o->style()->effectiveZoom()) return false; + paintInfo.context->save(); + paintInfo.context->setFillColor(o->style()->color()); paintInfo.context->setStrokeStyle(NoStroke); @@ -1416,7 +1422,7 @@ bool RenderThemeMac::paintSearchFieldResultsButton(RenderObject* o, const Render #if ENABLE(VIDEO) typedef enum { MediaControllerThemeClassic = 1, - MediaControllerThemeQT = 2 + MediaControllerThemeQuickTime = 2 } MediaControllerThemeStyle; static int mediaControllerTheme() @@ -1450,7 +1456,7 @@ static int mediaControllerTheme() return controllerTheme; #endif - controllerTheme = MediaControllerThemeQT; + controllerTheme = MediaControllerThemeQuickTime; return controllerTheme; } #endif @@ -1473,10 +1479,10 @@ void RenderThemeMac::adjustSliderThumbSize(RenderObject* o) const int width = mediaSliderThumbWidth; int height = mediaSliderThumbHeight; - if (mediaControllerTheme() == MediaControllerThemeQT) { + if (mediaControllerTheme() == MediaControllerThemeQuickTime) { CGSize size; - wkMeasureMediaUIPart(MediaSliderThumb, MediaControllerThemeQT, NULL, &size); + wkMeasureMediaUIPart(MediaSliderThumb, MediaControllerThemeQuickTime, NULL, &size); width = size.width; height = size.height; } @@ -1500,7 +1506,9 @@ static unsigned getMediaUIPartStateFlags(Node* node) { unsigned flags = 0; - if (node->active()) + if (node->disabled()) + flags |= MediaUIPartDisabledFlag; + else if (node->active()) flags |= MediaUIPartPressedFlag; return flags; } @@ -1510,7 +1518,7 @@ static FloatRect getUnzoomedRectAndAdjustCurrentContext(RenderObject* o, const R { float zoomLevel = o->style()->effectiveZoom(); FloatRect unzoomedRect(originalRect); - if (zoomLevel != 1.0f && mediaControllerTheme() == MediaControllerThemeQT) { + if (zoomLevel != 1.0f && mediaControllerTheme() == MediaControllerThemeQuickTime) { unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y()); @@ -1539,7 +1547,7 @@ bool RenderThemeMac::paintMediaMuteButton(RenderObject* o, const RenderObject::P if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag))) return false; - if (MediaControlPlayButtonElement* btn = static_cast<MediaControlPlayButtonElement*>(node)) { + if (MediaControlMuteButtonElement* btn = static_cast<MediaControlMuteButtonElement*>(node)) { LocalCurrentGraphicsContext localContext(paintInfo.context); wkDrawMediaUIPart(btn->displayType(), mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node)); @@ -1594,14 +1602,13 @@ bool RenderThemeMac::paintMediaSliderTrack(RenderObject* o, const RenderObject:: if (!mediaElement) return false; - float timeLoaded = 0; - float currentTime = 0; - float duration = 0; - if (MediaPlayer* player = mediaElement->player()) { - duration = player->duration(); - timeLoaded = player->maxTimeBuffered(); - currentTime = player->currentTime(); - } + RefPtr<TimeRanges> timeRanges = mediaElement->buffered(); + ExceptionCode ignoredException; + float timeLoaded = timeRanges->length() ? timeRanges->end(0, ignoredException) : 0; + float currentTime = mediaElement->currentTime(); + float duration = mediaElement->duration(); + if (isnan(duration)) + duration = 0; paintInfo.context->save(); FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r); @@ -1685,12 +1692,21 @@ bool RenderThemeMac::paintMediaTimeRemaining(RenderObject* o, const RenderObject String RenderThemeMac::extraMediaControlsStyleSheet() { - if (mediaControllerTheme() == MediaControllerThemeQT) - return String(mediaControlsQTUserAgentStyleSheet, sizeof(mediaControlsQTUserAgentStyleSheet)); + if (mediaControllerTheme() == MediaControllerThemeQuickTime) + return String(mediaControlsQuickTimeUserAgentStyleSheet, sizeof(mediaControlsQuickTimeUserAgentStyleSheet)); else return String(); } -#endif + +bool RenderThemeMac::shouldRenderMediaControlPart(ControlPart part, Element* e) +{ + if (part == MediaFullscreenButtonPart) + return mediaControllerTheme() == MediaControllerThemeQuickTime; + + return RenderTheme::shouldRenderMediaControlPart(part, e); +} + +#endif // ENABLE(VIDEO) NSPopUpButtonCell* RenderThemeMac::popupButton() const { diff --git a/WebCore/rendering/RenderThemeSafari.cpp b/WebCore/rendering/RenderThemeSafari.cpp index 23998d4..8e53088 100644 --- a/WebCore/rendering/RenderThemeSafari.cpp +++ b/WebCore/rendering/RenderThemeSafari.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008 Apple Inc. + * Copyright (C) 2007, 2008, 2009 Apple Inc. * Copyright (C) 2009 Kenneth Rohde Christiansen * * This library is free software; you can redistribute it and/or @@ -744,11 +744,21 @@ static void TrackGradientInterpolate(void* info, const CGFloat* inData, CGFloat* void RenderThemeSafari::paintMenuListButtonGradients(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { + if (r.isEmpty()) + return; + CGContextRef context = paintInfo.context->platformContext(); paintInfo.context->save(); - int radius = o->style()->borderTopLeftRadius().width(); + IntSize topLeftRadius; + IntSize topRightRadius; + IntSize bottomLeftRadius; + IntSize bottomRightRadius; + + o->style()->getBorderRadiiForRect(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius); + + int radius = topLeftRadius.width(); RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB()); @@ -771,33 +781,27 @@ void RenderThemeSafari::paintMenuListButtonGradients(RenderObject* o, const Rend RetainPtr<CGShadingRef> rightShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.right(), r.y()), CGPointMake(r.right() - radius, r.y()), mainFunction.get(), false, false)); paintInfo.context->save(); CGContextClipToRect(context, r); - paintInfo.context->addRoundedRectClip(r, - o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(), - o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius()); + paintInfo.context->addRoundedRectClip(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius); CGContextDrawShading(context, mainShading.get()); paintInfo.context->restore(); paintInfo.context->save(); CGContextClipToRect(context, topGradient); - paintInfo.context->addRoundedRectClip(enclosingIntRect(topGradient), - o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(), - IntSize(), IntSize()); + paintInfo.context->addRoundedRectClip(enclosingIntRect(topGradient), topLeftRadius, topRightRadius, IntSize(), IntSize()); CGContextDrawShading(context, topShading.get()); paintInfo.context->restore(); - paintInfo.context->save(); - CGContextClipToRect(context, bottomGradient); - paintInfo.context->addRoundedRectClip(enclosingIntRect(bottomGradient), - IntSize(), IntSize(), - o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius()); - CGContextDrawShading(context, bottomShading.get()); - paintInfo.context->restore(); + if (!bottomGradient.isEmpty()) { + paintInfo.context->save(); + CGContextClipToRect(context, bottomGradient); + paintInfo.context->addRoundedRectClip(enclosingIntRect(bottomGradient), IntSize(), IntSize(), bottomLeftRadius, bottomRightRadius); + CGContextDrawShading(context, bottomShading.get()); + paintInfo.context->restore(); + } paintInfo.context->save(); CGContextClipToRect(context, r); - paintInfo.context->addRoundedRectClip(r, - o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(), - o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius()); + paintInfo.context->addRoundedRectClip(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius); CGContextDrawShading(context, leftShading.get()); CGContextDrawShading(context, rightShading.get()); paintInfo.context->restore(); @@ -807,8 +811,6 @@ void RenderThemeSafari::paintMenuListButtonGradients(RenderObject* o, const Rend bool RenderThemeSafari::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { - paintInfo.context->save(); - IntRect bounds = IntRect(r.x() + o->style()->borderLeftWidth(), r.y() + o->style()->borderTopWidth(), r.width() - o->style()->borderLeftWidth() - o->style()->borderRightWidth(), @@ -826,6 +828,8 @@ bool RenderThemeSafari::paintMenuListButton(RenderObject* o, const RenderObject: if (bounds.width() < arrowWidth + arrowPaddingLeft) return false; + paintInfo.context->save(); + paintInfo.context->setFillColor(o->style()->color()); paintInfo.context->setStrokeColor(NoStroke); diff --git a/WebCore/rendering/RenderView.cpp b/WebCore/rendering/RenderView.cpp index 584e38a..c4a666f 100644 --- a/WebCore/rendering/RenderView.cpp +++ b/WebCore/rendering/RenderView.cpp @@ -133,12 +133,10 @@ void RenderView::layout() if (needsLayout()) RenderBlock::layout(); - // Reset overflowWidth and overflowHeight, since they act as a lower bound for docWidth() and docHeight(). - setOverflowWidth(width()); - setOverflowHeight(height()); - - setOverflowWidth(docWidth()); - setOverflowHeight(docHeight()); + // Reset overflow and then replace it with docWidth and docHeight. + m_overflow.clear(); + addLayoutOverflow(IntRect(0, 0, docWidth(), docHeight())); + ASSERT(layoutDelta() == IntSize()); ASSERT(m_layoutStateDisableCount == 0); @@ -472,6 +470,8 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e return; } + m_frameView->beginDeferredRepaints(); + // Have any of the old selected objects changed compared to the new selection? for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i) { RenderObject* obj = i->first; @@ -523,6 +523,8 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e newInfo->repaint(); delete newInfo; } + + m_frameView->endDeferredRepaints(); } void RenderView::clearSelection() diff --git a/WebCore/rendering/RenderWidget.cpp b/WebCore/rendering/RenderWidget.cpp index 36f4fed..5a5c9f1 100644 --- a/WebCore/rendering/RenderWidget.cpp +++ b/WebCore/rendering/RenderWidget.cpp @@ -28,6 +28,7 @@ #include "GraphicsContext.h" #include "HitTestResult.h" #include "RenderView.h" +#include "RenderWidgetProtector.h" using namespace std; @@ -60,6 +61,15 @@ void RenderWidget::destroy() // So the code below includes copied and pasted contents of // both RenderBox::destroy() and RenderObject::destroy(). // Fix originally made for <rdar://problem/4228818>. + + // <rdar://problem/6937089> suggests that node() can be null by the time we call renderArena() + // in the end of this function. One way this might happen is if this function was invoked twice + // in a row, so bail out and turn a crash into an assertion failure in debug builds and a leak + // in release builds. + ASSERT(node()); + if (!node()) + return; + animation()->cancelAnimations(this); if (RenderView* v = view()) @@ -90,6 +100,14 @@ void RenderWidget::destroy() destroyLayer(); } + // <rdar://problem/6937089> suggests that node() can be null here. One way this might happen is + // if this function was re-entered (and therefore the null check at the beginning did not fail), + // so bail out and turn a crash into an assertion failure in debug builds and a leak in release + // builds. + ASSERT(node()); + if (!node()) + return; + // Grab the arena from node()->document()->renderArena() before clearing the node pointer. // Clear the node before deref-ing, as this may be deleted when deref is called. RenderArena* arena = renderArena(); @@ -106,10 +124,9 @@ RenderWidget::~RenderWidget() void RenderWidget::setWidgetGeometry(const IntRect& frame) { if (node() && m_widget->frameRect() != frame) { - RenderArena* arena = ref(); - RefPtr<Node> protectedElement(node()); + RenderWidgetProtector protector(this); + RefPtr<Node> protectedNode(node()); m_widget->setFrameRect(frame); - deref(arena); } } @@ -158,6 +175,12 @@ void RenderWidget::styleDidChange(StyleDifference diff, const RenderStyle* oldSt } } +void RenderWidget::showSubstituteImage(PassRefPtr<Image> prpImage) +{ + m_substituteImage = prpImage; + repaint(); +} + void RenderWidget::paint(PaintInfo& paintInfo, int tx, int ty) { if (!shouldPaint(paintInfo, tx, ty)) @@ -183,11 +206,15 @@ void RenderWidget::paint(PaintInfo& paintInfo, int tx, int ty) #endif if (style()->hasBorderRadius()) { + IntRect borderRect = IntRect(tx, ty, width(), height()); + + if (borderRect.isEmpty()) + return; + // Push a clip if we have a border radius, since we want to round the foreground content that gets painted. paintInfo.context->save(); IntSize topLeft, topRight, bottomLeft, bottomRight; - IntRect borderRect = IntRect(tx, ty, width(), height()); style()->getBorderRadiiForRect(borderRect, topLeft, topRight, bottomLeft, bottomRight); paintInfo.context->addRoundedRectClip(borderRect, topLeft, topRight, bottomLeft, bottomRight); @@ -201,7 +228,10 @@ void RenderWidget::paint(PaintInfo& paintInfo, int tx, int ty) // Tell the widget to paint now. This is the only time the widget is allowed // to paint itself. That way it will composite properly with z-indexed layers. - m_widget->paint(paintInfo.context, paintInfo.rect); + if (m_substituteImage) + paintInfo.context->drawImage(m_substituteImage.get(), m_widget->frameRect()); + else + m_widget->paint(paintInfo.context, paintInfo.rect); if (m_widget->isFrameView() && paintInfo.overlapTestRequests && !static_cast<FrameView*>(m_widget.get())->useSlowRepaints()) { ASSERT(!paintInfo.overlapTestRequests->contains(this)); @@ -248,11 +278,9 @@ void RenderWidget::updateWidgetPosition() IntRect oldBounds(m_widget->frameRect()); bool boundsChanged = newBounds != oldBounds; if (boundsChanged) { - RenderArena* arena = ref(); - node()->ref(); + RenderWidgetProtector protector(this); + RefPtr<Node> protectedNode(node()); m_widget->setFrameRect(newBounds); - node()->deref(); - deref(arena); } #ifndef FLATTEN_IFRAME diff --git a/WebCore/rendering/RenderWidget.h b/WebCore/rendering/RenderWidget.h index bb68143..78537fd 100644 --- a/WebCore/rendering/RenderWidget.h +++ b/WebCore/rendering/RenderWidget.h @@ -40,6 +40,8 @@ public: void updateWidgetPosition(); + void showSubstituteImage(PassRefPtr<Image>); + protected: RenderWidget(Node*); @@ -61,10 +63,12 @@ private: void setWidgetGeometry(const IntRect&); + friend class RenderWidgetProtector; RenderArena* ref() { ++m_refCount; return renderArena(); } void deref(RenderArena*); RefPtr<Widget> m_widget; + RefPtr<Image> m_substituteImage; FrameView* m_frameView; int m_refCount; }; diff --git a/WebCore/rendering/RenderWidgetProtector.h b/WebCore/rendering/RenderWidgetProtector.h new file mode 100644 index 0000000..788304c --- /dev/null +++ b/WebCore/rendering/RenderWidgetProtector.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RenderWidgetProtector_h +#define RenderWidgetProtector_h + +#include "RenderWidget.h" + +namespace WebCore { + +class RenderWidgetProtector : private Noncopyable { +public: + RenderWidgetProtector(RenderWidget* object) + : m_object(object) + , m_arena(object->ref()) + { + } + + ~RenderWidgetProtector() + { + m_object->deref(m_arena); + } + +private: + RenderWidget* m_object; + RenderArena* m_arena; +}; + +} + +#endif // RenderWidgetProtector_h diff --git a/WebCore/rendering/RootInlineBox.cpp b/WebCore/rendering/RootInlineBox.cpp index e8f04da..c8e072e 100644 --- a/WebCore/rendering/RootInlineBox.cpp +++ b/WebCore/rendering/RootInlineBox.cpp @@ -38,28 +38,8 @@ namespace WebCore { typedef WTF::HashMap<const RootInlineBox*, EllipsisBox*> EllipsisBoxMap; static EllipsisBoxMap* gEllipsisBoxMap = 0; -void* RootInlineBox::Overflow::operator new(size_t sz, RenderArena* renderArena) throw() -{ - return renderArena->allocate(sz); -} - -void RootInlineBox::Overflow::operator delete(void* ptr, size_t sz) -{ - // Stash size where destroy can find it. - *(size_t *)ptr = sz; -} - -void RootInlineBox::Overflow::destroy(RenderArena* renderArena) -{ - delete this; - // Recover the size left there for us by operator delete and free the memory. - renderArena->free(*(size_t *)this, this); -} - void RootInlineBox::destroy(RenderArena* arena) { - if (m_overflow) - m_overflow->destroy(arena); detachEllipsisBox(arena); InlineFlowBox::destroy(arena); } @@ -155,8 +135,8 @@ void RootInlineBox::addHighlightOverflow() // Highlight acts as a selection inflation. FloatRect rootRect(0, selectionTop(), width(), selectionHeight()); IntRect inflatedRect = enclosingIntRect(page->chrome()->client()->customHighlightRect(renderer()->node(), renderer()->style()->highlight(), rootRect)); - setHorizontalOverflowPositions(min(leftOverflow(), inflatedRect.x()), max(rightOverflow(), inflatedRect.right())); - setVerticalOverflowPositions(min(topOverflow(), inflatedRect.y()), max(bottomOverflow(), inflatedRect.bottom())); + setHorizontalOverflowPositions(leftLayoutOverflow(), rightLayoutOverflow(), min(leftVisualOverflow(), inflatedRect.x()), max(rightVisualOverflow(), inflatedRect.right())); + setVerticalOverflowPositions(topLayoutOverflow(), bottomLayoutOverflow(), min(topVisualOverflow(), inflatedRect.y()), max(bottomVisualOverflow(), inflatedRect.bottom()), height()); } void RootInlineBox::paintCustomHighlight(RenderObject::PaintInfo& paintInfo, int tx, int ty, const AtomicString& highlightType) @@ -205,12 +185,8 @@ bool RootInlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re void RootInlineBox::adjustPosition(int dx, int dy) { InlineFlowBox::adjustPosition(dx, dy); - if (m_overflow) { - m_overflow->m_topOverflow += dy; - m_overflow->m_bottomOverflow += dy; - m_overflow->m_selectionTop += dy; - m_overflow->m_selectionBottom += dy; - } + m_lineTop += dy; + m_lineBottom += dy; m_blockHeight += dy; } @@ -225,6 +201,37 @@ void RootInlineBox::childRemoved(InlineBox* box) } } +int RootInlineBox::verticallyAlignBoxes(int heightOfBlock) +{ + int maxPositionTop = 0; + int maxPositionBottom = 0; + int maxAscent = 0; + int maxDescent = 0; + + // 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 = renderer(); + while (curr && !curr->node()) + curr = curr->container(); + bool strictMode = (curr && curr->document()->inStrictMode()); + + computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode); + + if (maxAscent + maxDescent < max(maxPositionTop, maxPositionBottom)) + adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom); + + int maxHeight = maxAscent + maxDescent; + int lineTop = heightOfBlock; + int lineBottom = heightOfBlock; + placeBoxesVertically(heightOfBlock, maxHeight, maxAscent, strictMode, lineTop, lineBottom); + computeVerticalOverflow(lineTop, lineBottom, strictMode); + setLineTopBottomPositions(lineTop, lineBottom); + + heightOfBlock += maxHeight; + + return heightOfBlock; +} + GapRects RootInlineBox::fillLineSelectionGap(int selTop, int selHeight, RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty, const RenderObject::PaintInfo* paintInfo) { @@ -321,9 +328,9 @@ InlineBox* RootInlineBox::lastSelectedBox() return 0; } -int RootInlineBox::selectionTop() +int RootInlineBox::selectionTop() const { - int selectionTop = m_overflow ? m_overflow->m_selectionTop : m_y; + int selectionTop = m_lineTop; if (!prevRootBox()) return selectionTop; @@ -407,18 +414,6 @@ EllipsisBox* RootInlineBox::ellipsisBox() const return gEllipsisBoxMap->get(this); } -void RootInlineBox::setVerticalOverflowPositions(int top, int bottom) -{ - if (!m_overflow) { - const Font& font = renderer()->style(m_firstLine)->font(); - if (top == m_y && bottom == m_y + font.height()) - return; - m_overflow = new (renderer()->renderArena()) Overflow(this); - } - m_overflow->m_topOverflow = top; - m_overflow->m_bottomOverflow = bottom; -} - void RootInlineBox::removeLineBoxFromRenderObject() { block()->lineBoxes()->removeLineBox(this); diff --git a/WebCore/rendering/RootInlineBox.h b/WebCore/rendering/RootInlineBox.h index 171be9d..b0b0e15 100644 --- a/WebCore/rendering/RootInlineBox.h +++ b/WebCore/rendering/RootInlineBox.h @@ -38,31 +38,33 @@ class RootInlineBox : public InlineFlowBox { public: RootInlineBox(RenderObject* obj) : InlineFlowBox(obj) - , m_overflow(0) , m_lineBreakObj(0) , m_lineBreakPos(0) + , m_lineTop(0) + , m_lineBottom(0) { } + virtual void destroy(RenderArena*); + virtual bool isRootInlineBox() const { return true; } - virtual void destroy(RenderArena*); void detachEllipsisBox(RenderArena*); - RootInlineBox* nextRootBox() { return static_cast<RootInlineBox*>(m_nextLine); } - RootInlineBox* prevRootBox() { return static_cast<RootInlineBox*>(m_prevLine); } + RootInlineBox* nextRootBox() const { return static_cast<RootInlineBox*>(m_nextLine); } + RootInlineBox* prevRootBox() const { return static_cast<RootInlineBox*>(m_prevLine); } virtual void adjustPosition(int dx, int dy); - virtual int topOverflow() const { return m_overflow ? m_overflow->m_topOverflow : m_y; } - virtual int bottomOverflow() const { return m_overflow ? m_overflow->m_bottomOverflow : m_y + m_renderer->style(m_firstLine)->font().height(); } - virtual int leftOverflow() const { return m_overflow ? m_overflow->m_leftOverflow : m_x; } - virtual int rightOverflow() const { return m_overflow ? m_overflow->m_rightOverflow : m_x + m_width; } + int lineTop() const { return m_lineTop; } + int lineBottom() const { return m_lineBottom; } - virtual void setVerticalOverflowPositions(int top, int bottom); - void setHorizontalOverflowPositions(int left, int right); + int selectionTop() const; + int selectionBottom() const { return lineBottom(); } + int selectionHeight() const { return max(0, selectionBottom() - selectionTop()); } - virtual void setVerticalSelectionPositions(int top, int bottom); + virtual int verticallyAlignBoxes(int heightOfBlock); + void setLineTopBottomPositions(int top, int bottom); virtual RenderLineBoxList* rendererLineBoxes() const; @@ -116,68 +118,36 @@ public: RenderBlock* block() const; - int selectionTop(); - int selectionBottom() { return m_overflow ? m_overflow->m_selectionBottom : m_y + height(); } - int selectionHeight() { return max(0, selectionBottom() - selectionTop()); } - InlineBox* closestLeafChildForXPos(int x, bool onlyEditableLeaves = false); Vector<RenderBox*>& floats() { ASSERT(!isDirty()); - if (!m_overflow) - m_overflow = new (m_renderer->renderArena()) Overflow(this); - return m_overflow->floats; + if (!m_floats) + m_floats.set(new Vector<RenderBox*>()); + return *m_floats; } - Vector<RenderBox*>* floatsPtr() { ASSERT(!isDirty()); return m_overflow ? &m_overflow->floats : 0; } + Vector<RenderBox*>* floatsPtr() { ASSERT(!isDirty()); return m_floats.get(); } virtual void extractLineBoxFromRenderObject(); virtual void attachLineBoxToRenderObject(); virtual void removeLineBoxFromRenderObject(); protected: - // Normally we are only as tall as the style on our block dictates, but we might have content - // that spills out above the height of our font (e.g, a tall image), or something that extends further - // below our line (e.g., a child whose font has a huge descent). - - // Allocated only when some of these fields have non-default values - struct Overflow { - Overflow(RootInlineBox* box) - : m_topOverflow(box->m_y) - , m_bottomOverflow(box->m_y + box->height()) - , m_leftOverflow(box->m_x) - , m_rightOverflow(box->m_x + box->m_width) - , m_selectionTop(box->m_y) - , m_selectionBottom(box->m_y + box->height()) - { - } - - void destroy(RenderArena*); - void* operator new(size_t, RenderArena*) throw(); - void operator delete(void*, size_t); - - int m_topOverflow; - int m_bottomOverflow; - int m_leftOverflow; - int m_rightOverflow; - int m_selectionTop; - int m_selectionBottom; - // Floats hanging off the line are pushed into this vector during layout. It is only - // good for as long as the line has not been marked dirty. - Vector<RenderBox*> floats; - private: - void* operator new(size_t) throw(); - }; - - Overflow* m_overflow; - // Where this line ended. The exact object and the position within that object are stored so that // we can create an InlineIterator beginning just after the end of this line. RenderObject* m_lineBreakObj; unsigned m_lineBreakPos; RefPtr<BidiContext> m_lineBreakContext; + int m_lineTop; + int m_lineBottom; + + // Floats hanging off the line are pushed into this vector during layout. It is only + // good for as long as the line has not been marked dirty. + OwnPtr<Vector<RenderBox*> > m_floats; + // The height of the block at the end of this line. This is where the next line starts. int m_blockHeight; @@ -186,27 +156,10 @@ protected: WTF::Unicode::Direction m_lineBreakBidiStatusLast : 5; }; -inline void RootInlineBox::setHorizontalOverflowPositions(int left, int right) -{ - if (!m_overflow) { - if (left == m_x && right == m_x + m_width) - return; - m_overflow = new (m_renderer->renderArena()) Overflow(this); - } - m_overflow->m_leftOverflow = left; - m_overflow->m_rightOverflow = right; -} - -inline void RootInlineBox::setVerticalSelectionPositions(int top, int bottom) +inline void RootInlineBox::setLineTopBottomPositions(int top, int bottom) { - if (!m_overflow) { - const Font& font = m_renderer->style(m_firstLine)->font(); - if (top == m_y && bottom == m_y + font.height()) - return; - m_overflow = new (m_renderer->renderArena()) Overflow(this); - } - m_overflow->m_selectionTop = top; - m_overflow->m_selectionBottom = bottom; + m_lineTop = top; + m_lineBottom = bottom; } } // namespace WebCore diff --git a/WebCore/rendering/SVGRootInlineBox.cpp b/WebCore/rendering/SVGRootInlineBox.cpp index 8319e7c..5829742 100644 --- a/WebCore/rendering/SVGRootInlineBox.cpp +++ b/WebCore/rendering/SVGRootInlineBox.cpp @@ -1087,8 +1087,8 @@ void SVGRootInlineBox::layoutInlineBoxes(InlineFlowBox* start, Vector<SVGChar>:: start->setWidth(highX - lowX); static_cast<SVGRootInlineBox*>(start)->setHeight(highY - lowY); - start->setVerticalOverflowPositions(top, bottom); - start->setVerticalSelectionPositions(top, bottom); + start->computeVerticalOverflow(top, bottom, true); + static_cast<SVGRootInlineBox*>(start)->setLineTopBottomPositions(top, bottom); } } diff --git a/WebCore/rendering/style/FillLayer.cpp b/WebCore/rendering/style/FillLayer.cpp index 9c491aa..ec910c9 100644 --- a/WebCore/rendering/style/FillLayer.cpp +++ b/WebCore/rendering/style/FillLayer.cpp @@ -31,18 +31,20 @@ FillLayer::FillLayer(EFillLayerType type) , m_attachment(FillLayer::initialFillAttachment(type)) , m_clip(FillLayer::initialFillClip(type)) , m_origin(FillLayer::initialFillOrigin(type)) - , m_repeat(FillLayer::initialFillRepeat(type)) + , m_repeatX(FillLayer::initialFillRepeatX(type)) + , m_repeatY(FillLayer::initialFillRepeatY(type)) , m_composite(FillLayer::initialFillComposite(type)) - , m_size(FillLayer::initialFillSize(type)) + , m_sizeType(SizeNone) + , m_sizeLength(FillLayer::initialFillSizeLength(type)) , m_imageSet(false) , m_attachmentSet(false) , m_clipSet(false) , m_originSet(false) - , m_repeatSet(false) + , m_repeatXSet(false) + , m_repeatYSet(false) , m_xPosSet(false) , m_yPosSet(false) , m_compositeSet(type == MaskFillLayer) - , m_sizeSet(false) , m_type(type) , m_next(0) { @@ -55,18 +57,20 @@ FillLayer::FillLayer(const FillLayer& o) , m_attachment(o.m_attachment) , m_clip(o.m_clip) , m_origin(o.m_origin) - , m_repeat(o.m_repeat) + , m_repeatX(o.m_repeatX) + , m_repeatY(o.m_repeatY) , m_composite(o.m_composite) - , m_size(o.m_size) + , m_sizeType(o.m_sizeType) + , m_sizeLength(o.m_sizeLength) , m_imageSet(o.m_imageSet) , m_attachmentSet(o.m_attachmentSet) , m_clipSet(o.m_clipSet) , m_originSet(o.m_originSet) - , m_repeatSet(o.m_repeatSet) + , m_repeatXSet(o.m_repeatXSet) + , m_repeatYSet(o.m_repeatYSet) , m_xPosSet(o.m_xPosSet) , m_yPosSet(o.m_yPosSet) , m_compositeSet(o.m_compositeSet) - , m_sizeSet(o.m_sizeSet) , m_type(o.m_type) , m_next(o.m_next ? new FillLayer(*o.m_next) : 0) { @@ -91,18 +95,20 @@ FillLayer& FillLayer::operator=(const FillLayer& o) m_clip = o.m_clip; m_composite = o.m_composite; m_origin = o.m_origin; - m_repeat = o.m_repeat; - m_size = o.m_size; + m_repeatX = o.m_repeatX; + m_repeatY = o.m_repeatY; + m_sizeType = o.m_sizeType; + m_sizeLength = o.m_sizeLength; m_imageSet = o.m_imageSet; m_attachmentSet = o.m_attachmentSet; m_clipSet = o.m_clipSet; m_compositeSet = o.m_compositeSet; m_originSet = o.m_originSet; - m_repeatSet = o.m_repeatSet; + m_repeatXSet = o.m_repeatXSet; + m_repeatYSet = o.m_repeatYSet; m_xPosSet = o.m_xPosSet; m_yPosSet = o.m_yPosSet; - m_sizeSet = o.m_sizeSet; m_type = o.m_type; @@ -115,9 +121,9 @@ bool FillLayer::operator==(const FillLayer& o) const // to propagate patterns into layers. All layer comparisons happen after values have all been filled in anyway. return StyleImage::imagesEquivalent(m_image.get(), o.m_image.get()) && m_xPosition == o.m_xPosition && m_yPosition == o.m_yPosition && m_attachment == o.m_attachment && m_clip == o.m_clip && - m_composite == o.m_composite && m_origin == o.m_origin && m_repeat == o.m_repeat && - m_size == o.m_size && m_type == o.m_type && - ((m_next && o.m_next) ? *m_next == *o.m_next : m_next == o.m_next); + m_composite == o.m_composite && m_origin == o.m_origin && m_repeatX == o.m_repeatX && + m_repeatY == o.m_repeatY && m_sizeType == o.m_sizeType && m_sizeLength == o.m_sizeLength && + m_type == o.m_type && ((m_next && o.m_next) ? *m_next == *o.m_next : m_next == o.m_next); } void FillLayer::fillUnsetProperties() @@ -200,11 +206,22 @@ void FillLayer::fillUnsetProperties() } } - for (curr = this; curr && curr->isRepeatSet(); curr = curr->next()) { } + for (curr = this; curr && curr->isRepeatXSet(); curr = curr->next()) { } if (curr && curr != this) { // We need to fill in the remaining values with the pattern specified. for (FillLayer* pattern = this; curr; curr = curr->next()) { - curr->m_repeat = pattern->m_repeat; + curr->m_repeatX = pattern->m_repeatX; + pattern = pattern->next(); + if (pattern == curr || !pattern) + pattern = this; + } + } + + for (curr = this; curr && curr->isRepeatYSet(); curr = curr->next()) { } + if (curr && curr != this) { + // We need to fill in the remaining values with the pattern specified. + for (FillLayer* pattern = this; curr; curr = curr->next()) { + curr->m_repeatY = pattern->m_repeatY; pattern = pattern->next(); if (pattern == curr || !pattern) pattern = this; @@ -215,7 +232,8 @@ void FillLayer::fillUnsetProperties() if (curr && curr != this) { // We need to fill in the remaining values with the pattern specified. for (FillLayer* pattern = this; curr; curr = curr->next()) { - curr->m_size = pattern->m_size; + curr->m_sizeType = pattern->m_sizeType; + curr->m_sizeLength = pattern->m_sizeLength; pattern = pattern->next(); if (pattern == curr || !pattern) pattern = this; @@ -232,7 +250,8 @@ void FillLayer::cullEmptyLayers() !next->isXPositionSet() && !next->isYPositionSet() && !next->isAttachmentSet() && !next->isClipSet() && !next->isCompositeSet() && !next->isOriginSet() && - !next->isRepeatSet() && !next->isSizeSet()) { + !next->isRepeatXSet() && !next->isRepeatYSet() + && !next->isSizeSet()) { delete next; p->m_next = 0; break; diff --git a/WebCore/rendering/style/FillLayer.h b/WebCore/rendering/style/FillLayer.h index c3944ad..fb928b6 100644 --- a/WebCore/rendering/style/FillLayer.h +++ b/WebCore/rendering/style/FillLayer.h @@ -34,6 +34,31 @@ namespace WebCore { +struct FillSize { + FillSize() + : type(SizeLength) + { + } + + FillSize(EFillSizeType t, LengthSize l) + : type(t) + , size(l) + { + } + + bool operator==(const FillSize& o) const + { + return type == o.type && size == o.size; + } + bool operator!=(const FillSize& o) const + { + return !(*this == o); + } + + EFillSizeType type; + LengthSize size; +}; + struct FillLayer { public: FillLayer(EFillLayerType); @@ -45,9 +70,11 @@ public: EFillAttachment attachment() const { return static_cast<EFillAttachment>(m_attachment); } EFillBox clip() const { return static_cast<EFillBox>(m_clip); } EFillBox origin() const { return static_cast<EFillBox>(m_origin); } - EFillRepeat repeat() const { return static_cast<EFillRepeat>(m_repeat); } + EFillRepeat repeatX() const { return static_cast<EFillRepeat>(m_repeatX); } + EFillRepeat repeatY() const { return static_cast<EFillRepeat>(m_repeatY); } CompositeOperator composite() const { return static_cast<CompositeOperator>(m_composite); } - LengthSize size() const { return m_size; } + LengthSize sizeLength() const { return m_sizeLength; } + FillSize size() const { return FillSize(static_cast<EFillSizeType>(m_sizeType), m_sizeLength); } const FillLayer* next() const { return m_next; } FillLayer* next() { return m_next; } @@ -58,19 +85,23 @@ public: bool isAttachmentSet() const { return m_attachmentSet; } bool isClipSet() const { return m_clipSet; } bool isOriginSet() const { return m_originSet; } - bool isRepeatSet() const { return m_repeatSet; } + bool isRepeatXSet() const { return m_repeatXSet; } + bool isRepeatYSet() const { return m_repeatYSet; } bool isCompositeSet() const { return m_compositeSet; } - bool isSizeSet() const { return m_sizeSet; } + bool isSizeSet() const { return m_sizeType != SizeNone; } void setImage(StyleImage* i) { m_image = i; m_imageSet = true; } - void setXPosition(const Length& l) { m_xPosition = l; m_xPosSet = true; } - void setYPosition(const Length& l) { m_yPosition = l; m_yPosSet = true; } + void setXPosition(Length l) { m_xPosition = l; m_xPosSet = true; } + void setYPosition(Length l) { m_yPosition = l; m_yPosSet = true; } void setAttachment(EFillAttachment attachment) { m_attachment = attachment; m_attachmentSet = true; } void setClip(EFillBox b) { m_clip = b; m_clipSet = true; } void setOrigin(EFillBox b) { m_origin = b; m_originSet = true; } - void setRepeat(EFillRepeat r) { m_repeat = r; m_repeatSet = true; } + void setRepeatX(EFillRepeat r) { m_repeatX = r; m_repeatXSet = true; } + void setRepeatY(EFillRepeat r) { m_repeatY = r; m_repeatYSet = true; } void setComposite(CompositeOperator c) { m_composite = c; m_compositeSet = true; } - void setSize(const LengthSize& b) { m_size = b; m_sizeSet = true; } + void setSizeType(EFillSizeType b) { m_sizeType = b; } + void setSizeLength(LengthSize l) { m_sizeLength = l; } + void setSize(FillSize f) { m_sizeType = f.type; m_sizeLength = f.size; } void clearImage() { m_imageSet = false; } void clearXPosition() { m_xPosSet = false; } @@ -78,9 +109,10 @@ public: void clearAttachment() { m_attachmentSet = false; } void clearClip() { m_clipSet = false; } void clearOrigin() { m_originSet = false; } - void clearRepeat() { m_repeatSet = false; } + void clearRepeatX() { m_repeatXSet = false; } + void clearRepeatY() { m_repeatYSet = false; } void clearComposite() { m_compositeSet = false; } - void clearSize() { m_sizeSet = false; } + void clearSize() { m_sizeType = SizeNone; } void setNext(FillLayer* n) { if (m_next != n) { delete m_next; m_next = n; } } @@ -117,9 +149,12 @@ public: static EFillAttachment initialFillAttachment(EFillLayerType) { return ScrollBackgroundAttachment; } static EFillBox initialFillClip(EFillLayerType) { return BorderFillBox; } static EFillBox initialFillOrigin(EFillLayerType type) { return type == BackgroundFillLayer ? PaddingFillBox : BorderFillBox; } - static EFillRepeat initialFillRepeat(EFillLayerType) { return RepeatFill; } + static EFillRepeat initialFillRepeatX(EFillLayerType) { return RepeatFill; } + static EFillRepeat initialFillRepeatY(EFillLayerType) { return RepeatFill; } static CompositeOperator initialFillComposite(EFillLayerType) { return CompositeSourceOver; } - static LengthSize initialFillSize(EFillLayerType) { return LengthSize(); } + static EFillSizeType initialFillSizeType(EFillLayerType) { return SizeLength; } + static LengthSize initialFillSizeLength(EFillLayerType) { return LengthSize(); } + static FillSize initialFillSize(EFillLayerType) { return FillSize(); } static Length initialFillXPosition(EFillLayerType) { return Length(0.0, Percent); } static Length initialFillYPosition(EFillLayerType) { return Length(0.0, Percent); } static StyleImage* initialFillImage(EFillLayerType) { return 0; } @@ -136,20 +171,22 @@ public: unsigned m_attachment : 2; // EFillAttachment unsigned m_clip : 2; // EFillBox unsigned m_origin : 2; // EFillBox - unsigned m_repeat : 2; // EFillRepeat + unsigned m_repeatX : 3; // EFillRepeat + unsigned m_repeatY : 3; // EFillRepeat unsigned m_composite : 4; // CompositeOperator - - LengthSize m_size; + unsigned m_sizeType : 2; // EFillSizeType + + LengthSize m_sizeLength; bool m_imageSet : 1; bool m_attachmentSet : 1; bool m_clipSet : 1; bool m_originSet : 1; - bool m_repeatSet : 1; + bool m_repeatXSet : 1; + bool m_repeatYSet : 1; bool m_xPosSet : 1; bool m_yPosSet : 1; bool m_compositeSet : 1; - bool m_sizeSet : 1; unsigned m_type : 1; // EFillLayerType diff --git a/WebCore/rendering/style/RenderStyle.cpp b/WebCore/rendering/style/RenderStyle.cpp index 0e258c8..a861fea 100644 --- a/WebCore/rendering/style/RenderStyle.cpp +++ b/WebCore/rendering/style/RenderStyle.cpp @@ -324,6 +324,7 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon *rareNonInheritedData->flexibleBox.get() != *other->rareNonInheritedData->flexibleBox.get()) return StyleDifferenceLayout; + // FIXME: We should add an optimized form of layout that just recomputes visual overflow. if (!rareNonInheritedData->shadowDataEquivalent(*other->rareNonInheritedData.get())) return StyleDifferenceLayout; @@ -453,6 +454,12 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon if (inherited->m_effectiveZoom != other->inherited->m_effectiveZoom) return StyleDifferenceLayout; + if (rareNonInheritedData->opacity == 1 && other->rareNonInheritedData->opacity < 1 || + rareNonInheritedData->opacity < 1 && other->rareNonInheritedData->opacity == 1) { + // FIXME: We should add an optimized form of layout that just recomputes visual overflow. + return StyleDifferenceLayout; + } + // Make sure these left/top/right/bottom checks stay below all layout checks and above // all visible checks. if (position() != StaticPosition) { diff --git a/WebCore/rendering/style/RenderStyle.h b/WebCore/rendering/style/RenderStyle.h index 720bc8d..f1591de 100644 --- a/WebCore/rendering/style/RenderStyle.h +++ b/WebCore/rendering/style/RenderStyle.h @@ -521,26 +521,29 @@ public: const Color& backgroundColor() const { return background->m_color; } StyleImage* backgroundImage() const { return background->m_background.m_image.get(); } - EFillRepeat backgroundRepeat() const { return static_cast<EFillRepeat>(background->m_background.m_repeat); } + EFillRepeat backgroundRepeatX() const { return static_cast<EFillRepeat>(background->m_background.m_repeatX); } + EFillRepeat backgroundRepeatY() const { return static_cast<EFillRepeat>(background->m_background.m_repeatY); } CompositeOperator backgroundComposite() const { return static_cast<CompositeOperator>(background->m_background.m_composite); } EFillAttachment backgroundAttachment() const { return static_cast<EFillAttachment>(background->m_background.m_attachment); } EFillBox backgroundClip() const { return static_cast<EFillBox>(background->m_background.m_clip); } EFillBox backgroundOrigin() const { return static_cast<EFillBox>(background->m_background.m_origin); } Length backgroundXPosition() const { return background->m_background.m_xPosition; } Length backgroundYPosition() const { return background->m_background.m_yPosition; } - LengthSize backgroundSize() const { return background->m_background.m_size; } + EFillSizeType backgroundSizeType() const { return static_cast<EFillSizeType>(background->m_background.m_sizeType); } + LengthSize backgroundSizeLength() const { return background->m_background.m_sizeLength; } FillLayer* accessBackgroundLayers() { return &(background.access()->m_background); } const FillLayer* backgroundLayers() const { return &(background->m_background); } StyleImage* maskImage() const { return rareNonInheritedData->m_mask.m_image.get(); } - EFillRepeat maskRepeat() const { return static_cast<EFillRepeat>(rareNonInheritedData->m_mask.m_repeat); } + EFillRepeat maskRepeatX() const { return static_cast<EFillRepeat>(rareNonInheritedData->m_mask.m_repeatX); } + EFillRepeat maskRepeatY() const { return static_cast<EFillRepeat>(rareNonInheritedData->m_mask.m_repeatY); } CompositeOperator maskComposite() const { return static_cast<CompositeOperator>(rareNonInheritedData->m_mask.m_composite); } EFillAttachment maskAttachment() const { return static_cast<EFillAttachment>(rareNonInheritedData->m_mask.m_attachment); } EFillBox maskClip() const { return static_cast<EFillBox>(rareNonInheritedData->m_mask.m_clip); } EFillBox maskOrigin() const { return static_cast<EFillBox>(rareNonInheritedData->m_mask.m_origin); } Length maskXPosition() const { return rareNonInheritedData->m_mask.m_xPosition; } Length maskYPosition() const { return rareNonInheritedData->m_mask.m_yPosition; } - LengthSize maskSize() const { return rareNonInheritedData->m_mask.m_size; } + LengthSize maskSize() const { return rareNonInheritedData->m_mask.m_sizeLength; } FillLayer* accessMaskLayers() { return &(rareNonInheritedData.access()->m_mask); } const FillLayer* maskLayers() const { return &(rareNonInheritedData->m_mask); } const NinePieceImage& maskBoxImage() const { return rareNonInheritedData->m_maskBoxImage; } @@ -755,7 +758,8 @@ public: void setBackgroundXPosition(Length l) { SET_VAR(background, m_background.m_xPosition, l) } void setBackgroundYPosition(Length l) { SET_VAR(background, m_background.m_yPosition, l) } - void setBackgroundSize(LengthSize l) { SET_VAR(background, m_background.m_size, l) } + void setBackgroundSize(EFillSizeType b) { SET_VAR(background, m_background.m_sizeType, b) } + void setBackgroundSizeLength(LengthSize l) { SET_VAR(background, m_background.m_sizeLength, l) } void setBorderImage(const NinePieceImage& b) { SET_VAR(surround, border.image, b) } @@ -868,7 +872,7 @@ public: void setMaskBoxImage(const NinePieceImage& b) { SET_VAR(rareNonInheritedData, m_maskBoxImage, b) } void setMaskXPosition(Length l) { SET_VAR(rareNonInheritedData, m_mask.m_xPosition, l) } void setMaskYPosition(Length l) { SET_VAR(rareNonInheritedData, m_mask.m_yPosition, l) } - void setMaskSize(LengthSize l) { SET_VAR(rareNonInheritedData, m_mask.m_size, l) } + void setMaskSize(LengthSize l) { SET_VAR(rareNonInheritedData, m_mask.m_sizeLength, l) } void setBorderCollapse(bool collapse) { inherited_flags._border_collapse = collapse; } void setHorizontalBorderSpacing(short v) { SET_VAR(inherited, horizontal_border_spacing, v) } diff --git a/WebCore/rendering/style/RenderStyleConstants.h b/WebCore/rendering/style/RenderStyleConstants.h index c491816..3010947 100644 --- a/WebCore/rendering/style/RenderStyleConstants.h +++ b/WebCore/rendering/style/RenderStyleConstants.h @@ -4,6 +4,7 @@ * (C) 2000 Dirk Mueller (mueller@kde.org) * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com) + * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -68,10 +69,10 @@ enum PseudoId { NOPSEUDO, FIRST_LINE, FIRST_LETTER, BEFORE, AFTER, SELECTION, FIRST_LINE_INHERITED, SCROLLBAR, FILE_UPLOAD_BUTTON, INPUT_PLACEHOLDER, SLIDER_THUMB, SEARCH_CANCEL_BUTTON, SEARCH_DECORATION, SEARCH_RESULTS_DECORATION, SEARCH_RESULTS_BUTTON, MEDIA_CONTROLS_PANEL, MEDIA_CONTROLS_PLAY_BUTTON, MEDIA_CONTROLS_MUTE_BUTTON, MEDIA_CONTROLS_TIMELINE, MEDIA_CONTROLS_TIMELINE_CONTAINER, - MEDIA_CONTROLS_CURRENT_TIME_DISPLAY, MEDIA_CONTROLS_TIME_REMAINING_DISPLAY, MEDIA_CONTROLS_SEEK_BACK_BUTTON, - MEDIA_CONTROLS_SEEK_FORWARD_BUTTON, MEDIA_CONTROLS_FULLSCREEN_BUTTON, MEDIA_CONTROLS_REWIND_BUTTON, - MEDIA_CONTROLS_RETURN_TO_REALTIME_BUTTON, MEDIA_CONTROLS_STATUS_DISPLAY, - SCROLLBAR_THUMB, SCROLLBAR_BUTTON, SCROLLBAR_TRACK, SCROLLBAR_TRACK_PIECE, SCROLLBAR_CORNER, RESIZER, + MEDIA_CONTROLS_VOLUME_SLIDER, MEDIA_CONTROLS_VOLUME_SLIDER_CONTAINER, MEDIA_CONTROLS_CURRENT_TIME_DISPLAY, MEDIA_CONTROLS_TIME_REMAINING_DISPLAY, MEDIA_CONTROLS_SEEK_BACK_BUTTON, + MEDIA_CONTROLS_SEEK_FORWARD_BUTTON, MEDIA_CONTROLS_FULLSCREEN_BUTTON, MEDIA_CONTROLS_REWIND_BUTTON, MEDIA_CONTROLS_RETURN_TO_REALTIME_BUTTON, + MEDIA_CONTROLS_STATUS_DISPLAY, SCROLLBAR_THUMB, SCROLLBAR_BUTTON, SCROLLBAR_TRACK, SCROLLBAR_TRACK_PIECE, SCROLLBAR_CORNER, RESIZER, + INPUT_LIST_BUTTON, FIRST_INTERNAL_PSEUDOID = FILE_UPLOAD_BUTTON }; @@ -131,13 +132,16 @@ enum EFillBox { }; enum EFillRepeat { - RepeatFill, RepeatXFill, RepeatYFill, NoRepeatFill + RepeatFill, NoRepeatFill, RoundFill, SpaceFill }; enum EFillLayerType { BackgroundFillLayer, MaskFillLayer }; +// CSS3 Background Values +enum EFillSizeType { Contain, Cover, SizeLength, SizeNone }; + // CSS3 Marquee Properties enum EMarqueeBehavior { MNONE, MSCROLL, MSLIDE, MALTERNATE }; @@ -298,7 +302,11 @@ enum EDisplay { TABLE, INLINE_TABLE, TABLE_ROW_GROUP, TABLE_HEADER_GROUP, TABLE_FOOTER_GROUP, TABLE_ROW, TABLE_COLUMN_GROUP, TABLE_COLUMN, TABLE_CELL, - TABLE_CAPTION, BOX, INLINE_BOX, NONE + TABLE_CAPTION, BOX, INLINE_BOX, +#if ENABLE(WCSS) + WAP_MARQUEE, +#endif + NONE }; enum EPointerEvents { diff --git a/WebCore/rendering/style/SVGRenderStyle.h b/WebCore/rendering/style/SVGRenderStyle.h index 0e9dae4..e50d349 100644 --- a/WebCore/rendering/style/SVGRenderStyle.h +++ b/WebCore/rendering/style/SVGRenderStyle.h @@ -65,7 +65,6 @@ namespace WebCore { SVG_RS_DEFINE_ATTRIBUTE_INHERITED(LineJoin, JoinStyle, joinStyle, MiterJoin) SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EShapeRendering, ShapeRendering, shapeRendering, SR_AUTO) SVG_RS_DEFINE_ATTRIBUTE_INHERITED(ETextAnchor, TextAnchor, textAnchor, TA_START) - SVG_RS_DEFINE_ATTRIBUTE_INHERITED(ETextRendering, TextRendering, textRendering, TR_AUTO) SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EWritingMode, WritingMode, writingMode, WM_LRTB) SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EGlyphOrientation, GlyphOrientationHorizontal, glyphOrientationHorizontal, GO_0DEG) SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EGlyphOrientation, GlyphOrientationVertical, glyphOrientationVertical, GO_AUTO) @@ -113,7 +112,6 @@ namespace WebCore { return (_colorRendering == other._colorRendering) && (_imageRendering == other._imageRendering) && (_shapeRendering == other._shapeRendering) && - (_textRendering == other._textRendering) && (_clipRule == other._clipRule) && (_fillRule == other._fillRule) && (_capStyle == other._capStyle) && @@ -134,7 +132,6 @@ namespace WebCore { unsigned _colorRendering : 2; // EColorRendering unsigned _imageRendering : 2; // EImageRendering unsigned _shapeRendering : 2; // EShapeRendering - unsigned _textRendering : 2; // ETextRendering unsigned _clipRule : 1; // WindRule unsigned _fillRule : 1; // WindRule unsigned _capStyle : 2; // LineCap @@ -190,7 +187,6 @@ namespace WebCore { svg_inherited_flags._fillRule = initialFillRule(); svg_inherited_flags._imageRendering = initialImageRendering(); svg_inherited_flags._shapeRendering = initialShapeRendering(); - svg_inherited_flags._textRendering = initialTextRendering(); svg_inherited_flags._textAnchor = initialTextAnchor(); svg_inherited_flags._capStyle = initialCapStyle(); svg_inherited_flags._joinStyle = initialJoinStyle(); diff --git a/WebCore/rendering/style/SVGRenderStyleDefs.h b/WebCore/rendering/style/SVGRenderStyleDefs.h index b7bf026..c0f5d4e 100644 --- a/WebCore/rendering/style/SVGRenderStyleDefs.h +++ b/WebCore/rendering/style/SVGRenderStyleDefs.h @@ -95,10 +95,6 @@ namespace WebCore { SR_AUTO, SR_OPTIMIZESPEED, SR_CRISPEDGES, SR_GEOMETRICPRECISION }; - enum ETextRendering { - TR_AUTO, TR_OPTIMIZESPEED, TR_OPTIMIZELEGIBILITY, TR_GEOMETRICPRECISION - }; - enum EWritingMode { WM_LRTB, WM_LR, WM_RLTB, WM_RL, WM_TBRL, WM_TB }; |