diff options
Diffstat (limited to 'Source/WebCore/rendering')
122 files changed, 2541 insertions, 1778 deletions
diff --git a/Source/WebCore/rendering/AutoTableLayout.cpp b/Source/WebCore/rendering/AutoTableLayout.cpp index 2c3636e04..0af1f78bf 100644 --- a/Source/WebCore/rendering/AutoTableLayout.cpp +++ b/Source/WebCore/rendering/AutoTableLayout.cpp @@ -244,8 +244,8 @@ void AutoTableLayout::computePreferredLogicalWidths(LayoutUnit& minWidth, Layout if (scaleColumns) { maxNonPercent = maxNonPercent * 100 / max(remainingPercent, epsilon); - maxWidth = max<int>(maxWidth, static_cast<int>(min(maxNonPercent, MAX_LAYOUT_UNIT / 2.0f))); - maxWidth = max<int>(maxWidth, static_cast<int>(min(maxPercent, MAX_LAYOUT_UNIT / 2.0f))); + maxWidth = max<int>(maxWidth, static_cast<int>(min(maxNonPercent, static_cast<float>(tableMaxWidth)))); + maxWidth = max<int>(maxWidth, static_cast<int>(min(maxPercent, static_cast<float>(tableMaxWidth)))); } maxWidth = max<int>(maxWidth, spanMaxLogicalWidth); @@ -260,7 +260,7 @@ void AutoTableLayout::computePreferredLogicalWidths(LayoutUnit& minWidth, Layout maxWidth = minWidth; } else if (!remainingPercent && maxNonPercent) { // if there was no remaining percent, maxWidth is invalid - maxWidth = MAX_LAYOUT_UNIT; + maxWidth = tableMaxWidth; } Length tableLogicalMinWidth = m_table->style()->logicalMinWidth(); diff --git a/Source/WebCore/rendering/ColumnInfo.h b/Source/WebCore/rendering/ColumnInfo.h index e462a84a5..553564c53 100644 --- a/Source/WebCore/rendering/ColumnInfo.h +++ b/Source/WebCore/rendering/ColumnInfo.h @@ -38,6 +38,7 @@ public: : m_desiredColumnWidth(0) , m_desiredColumnCount(1) , m_progressionAxis(InlineAxis) + , m_progressionIsReversed(false) , m_columnCount(1) , m_columnHeight(0) , m_minimumColumnHeight(0) @@ -59,6 +60,9 @@ public: Axis progressionAxis() const { return m_progressionAxis; } void setProgressionAxis(Axis progressionAxis) { m_progressionAxis = progressionAxis; } + bool progressionIsReversed() const { return m_progressionIsReversed; } + void setProgressionIsReversed(bool reversed) { m_progressionIsReversed = reversed; } + unsigned columnCount() const { return m_columnCount; } LayoutUnit columnHeight() const { return m_columnHeight; } @@ -102,6 +106,7 @@ private: LayoutUnit m_desiredColumnWidth; unsigned m_desiredColumnCount; Axis m_progressionAxis; + bool m_progressionIsReversed; unsigned m_columnCount; LayoutUnit m_columnHeight; diff --git a/Source/WebCore/rendering/CounterNode.cpp b/Source/WebCore/rendering/CounterNode.cpp index f3cc4da03..09f0175e5 100644 --- a/Source/WebCore/rendering/CounterNode.cpp +++ b/Source/WebCore/rendering/CounterNode.cpp @@ -261,25 +261,22 @@ void CounterNode::insertAfter(CounterNode* newChild, CounterNode* refChild, cons newChild->m_parent = this; newChild->m_previousSibling = refChild; - if (!newChild->m_firstChild || newChild->m_hasResetType) { + if (next) { + ASSERT(next->m_previousSibling == refChild); + next->m_previousSibling = newChild; newChild->m_nextSibling = next; - if (next) { - ASSERT(next->m_previousSibling == refChild); - next->m_previousSibling = newChild; - } else { - ASSERT(m_lastChild == refChild); - m_lastChild = newChild; - } + } else { + ASSERT(m_lastChild == refChild); + m_lastChild = newChild; + } + if (!newChild->m_firstChild || newChild->m_hasResetType) { newChild->m_countInParent = newChild->computeCountInParent(); newChild->resetThisAndDescendantsRenderers(); if (next) next->recount(); return; } - // If the new child is the last in the sibling list we must set the parent's lastChild. - if (!newChild->m_nextSibling) - m_lastChild = newChild; // The code below handles the case when a formerly root increment counter is loosing its root position // and therefore its children become next siblings. diff --git a/Source/WebCore/rendering/FilterEffectRenderer.cpp b/Source/WebCore/rendering/FilterEffectRenderer.cpp index 54e8c1cf5..ebf6b7ee6 100644 --- a/Source/WebCore/rendering/FilterEffectRenderer.cpp +++ b/Source/WebCore/rendering/FilterEffectRenderer.cpp @@ -42,10 +42,11 @@ #include <wtf/MathExtras.h> #if ENABLE(CSS_SHADERS) && ENABLE(WEBGL) +#include "CustomFilterGlobalContext.h" #include "CustomFilterProgram.h" #include "CustomFilterOperation.h" #include "FECustomFilter.h" -#include "FrameView.h" +#include "RenderView.h" #include "Settings.h" #endif @@ -271,7 +272,9 @@ bool FilterEffectRenderer::build(Document* document, const FilterOperations& ope CustomFilterOperation* customFilterOperation = static_cast<CustomFilterOperation*>(filterOperation); RefPtr<CustomFilterProgram> program = customFilterOperation->program(); if (program->isLoaded()) { - effect = FECustomFilter::create(this, document->view()->root()->hostWindow(), program, customFilterOperation->parameters(), + CustomFilterGlobalContext* globalContext = document->renderView()->customFilterGlobalContext(); + globalContext->prepareContextIfNeeded(document->view()->hostWindow()); + effect = FECustomFilter::create(this, globalContext, program, customFilterOperation->parameters(), customFilterOperation->meshRows(), customFilterOperation->meshColumns(), customFilterOperation->meshBoxType(), customFilterOperation->meshType()); m_hasCustomShaderFilter = true; diff --git a/Source/WebCore/rendering/FixedTableLayout.cpp b/Source/WebCore/rendering/FixedTableLayout.cpp index 54272b117..41dd906e1 100644 --- a/Source/WebCore/rendering/FixedTableLayout.cpp +++ b/Source/WebCore/rendering/FixedTableLayout.cpp @@ -166,11 +166,6 @@ 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::computePreferredLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth) { // FIXME: This entire calculation is incorrect for both minwidth and maxwidth. @@ -204,8 +199,8 @@ void FixedTableLayout::computePreferredLogicalWidths(LayoutUnit& minWidth, Layou // 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->document()->inQuirksMode() && m_table->style()->logicalWidth().isPercent() && maxWidth < TABLE_MAX_WIDTH) - maxWidth = TABLE_MAX_WIDTH; + if (m_table->document()->inQuirksMode() && m_table->style()->logicalWidth().isPercent() && maxWidth < tableMaxWidth) + maxWidth = tableMaxWidth; } void FixedTableLayout::layout() diff --git a/Source/WebCore/rendering/HitTestResult.cpp b/Source/WebCore/rendering/HitTestResult.cpp index 66e1da96b..5ffb65969 100644 --- a/Source/WebCore/rendering/HitTestResult.cpp +++ b/Source/WebCore/rendering/HitTestResult.cpp @@ -622,21 +622,23 @@ bool HitTestResult::addNodeToRectBasedTestResult(Node* node, const LayoutPoint& mutableRectBasedTestResult().add(node); - if (node->renderer()->isInline()) { + bool regionFilled = rect.contains(rectForPoint(pointInContainer)); + // FIXME: This code (incorrectly) attempts to correct for culled inline nodes. See https://bugs.webkit.org/show_bug.cgi?id=85849. + if (node->renderer()->isInline() && !regionFilled) { for (RenderObject* curr = node->renderer()->parent(); curr; curr = curr->parent()) { if (!curr->isRenderInline()) break; - + // We need to make sure the nodes for culled inlines get included. RenderInline* currInline = toRenderInline(curr); if (currInline->alwaysCreateLineBoxes()) break; - + if (currInline->visibleToHitTesting() && currInline->node()) mutableRectBasedTestResult().add(currInline->node()->shadowAncestorNode()); } } - return !rect.contains(rectForPoint(pointInContainer)); + return !regionFilled; } bool HitTestResult::addNodeToRectBasedTestResult(Node* node, const LayoutPoint& pointInContainer, const FloatRect& rect) @@ -655,21 +657,23 @@ bool HitTestResult::addNodeToRectBasedTestResult(Node* node, const LayoutPoint& mutableRectBasedTestResult().add(node); - if (node->renderer()->isInline()) { + bool regionFilled = rect.contains(rectForPoint(pointInContainer)); + // FIXME: This code (incorrectly) attempts to correct for culled inline nodes. See https://bugs.webkit.org/show_bug.cgi?id=85849. + if (node->renderer()->isInline() && !regionFilled) { for (RenderObject* curr = node->renderer()->parent(); curr; curr = curr->parent()) { if (!curr->isRenderInline()) break; - + // We need to make sure the nodes for culled inlines get included. RenderInline* currInline = toRenderInline(curr); if (currInline->alwaysCreateLineBoxes()) break; - + if (currInline->visibleToHitTesting() && currInline->node()) mutableRectBasedTestResult().add(currInline->node()->shadowAncestorNode()); } } - return !rect.contains(rectForPoint(pointInContainer)); + return !regionFilled; } void HitTestResult::append(const HitTestResult& other) @@ -706,4 +710,21 @@ HitTestResult::NodeSet& HitTestResult::mutableRectBasedTestResult() return *m_rectBasedTestResult; } +Vector<String> HitTestResult::dictationAlternatives() const +{ + // Return the dictation context handle if the text at this point has DictationAlternative marker, which means this text is + if (!m_innerNonSharedNode) + return Vector<String>(); + + DocumentMarker* marker = m_innerNonSharedNode->document()->markers()->markerContainingPoint(hitTestPoint().point(), DocumentMarker::DictationAlternatives); + if (!marker) + return Vector<String>(); + + Frame* frame = innerNonSharedNode()->document()->frame(); + if (!frame) + return Vector<String>(); + + return frame->editor()->dictationAlternativesForMarker(marker); +} + } // namespace WebCore diff --git a/Source/WebCore/rendering/HitTestResult.h b/Source/WebCore/rendering/HitTestResult.h index a18fdb5a2..19ddbd1ac 100644 --- a/Source/WebCore/rendering/HitTestResult.h +++ b/Source/WebCore/rendering/HitTestResult.h @@ -157,6 +157,8 @@ public: // the same thing as mutableRectBasedTestResult(), but here the return value is const. const NodeSet& rectBasedTestResult() const; + Vector<String> dictationAlternatives() const; + private: NodeSet& mutableRectBasedTestResult(); // See above. diff --git a/Source/WebCore/rendering/InlineBox.cpp b/Source/WebCore/rendering/InlineBox.cpp index 957e0f0cb..6f328c1af 100644 --- a/Source/WebCore/rendering/InlineBox.cpp +++ b/Source/WebCore/rendering/InlineBox.cpp @@ -37,7 +37,7 @@ using namespace std; namespace WebCore { -class SameSizeAsInlineBox { +struct SameSizeAsInlineBox { virtual ~SameSizeAsInlineBox() { } void* a[4]; FloatPoint b; diff --git a/Source/WebCore/rendering/InlineFlowBox.cpp b/Source/WebCore/rendering/InlineFlowBox.cpp index 58c97dd69..c10941875 100644 --- a/Source/WebCore/rendering/InlineFlowBox.cpp +++ b/Source/WebCore/rendering/InlineFlowBox.cpp @@ -27,7 +27,6 @@ #include "GraphicsContext.h" #include "InlineTextBox.h" #include "HitTestResult.h" -#include "RootInlineBox.h" #include "RenderBlock.h" #include "RenderInline.h" #include "RenderLayer.h" @@ -45,7 +44,7 @@ using namespace std; namespace WebCore { -class SameSizeAsInlineFlowBox : public InlineBox { +struct SameSizeAsInlineFlowBox : public InlineBox { void* pointers[5]; uint32_t bitfields : 24; }; diff --git a/Source/WebCore/rendering/InlineTextBox.cpp b/Source/WebCore/rendering/InlineTextBox.cpp index be7e76673..9e731d638 100644 --- a/Source/WebCore/rendering/InlineTextBox.cpp +++ b/Source/WebCore/rendering/InlineTextBox.cpp @@ -851,8 +851,8 @@ void InlineTextBox::paintSelection(GraphicsContext* context, const FloatPoint& b LayoutUnit selectionBottom = root()->selectionBottom(); LayoutUnit selectionTop = root()->selectionTopAdjustedForPrecedingBlock(); - LayoutUnit deltaY = renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom - logicalBottom() : logicalTop() - selectionTop; - LayoutUnit selHeight = max<LayoutUnit>(ZERO_LAYOUT_UNIT, selectionBottom - selectionTop); + int deltaY = roundToInt(renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom - logicalBottom() : logicalTop() - selectionTop); + int selHeight = max(0, roundToInt(selectionBottom - selectionTop)); FloatPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY); FloatRect clipRect(localOrigin, FloatSize(m_logicalWidth, selHeight)); @@ -1030,7 +1030,8 @@ void InlineTextBox::paintDocumentMarker(GraphicsContext* pt, const FloatPoint& b if (m_truncation != cNoTruncation) markerSpansWholeBox = false; - if (!markerSpansWholeBox || grammar) { + bool isDictationMarker = marker->type() == DocumentMarker::DictationAlternatives; + if (!markerSpansWholeBox || grammar || isDictationMarker) { int startPosition = max<int>(marker->startOffset() - m_start, 0); int endPosition = min<int>(marker->endOffset() - m_start, m_len); @@ -1050,7 +1051,7 @@ void InlineTextBox::paintDocumentMarker(GraphicsContext* pt, const FloatPoint& b // Store rendered rects for bad grammar markers, so we can hit-test against it elsewhere in order to // display a toolTip. We don't do this for misspelling markers. - if (grammar) { + if (grammar || isDictationMarker) { markerRect.move(-boxOrigin.x(), -boxOrigin.y()); markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox(); toRenderedDocumentMarker(marker)->setRenderedRect(markerRect); diff --git a/Source/WebCore/rendering/RenderBlock.cpp b/Source/WebCore/rendering/RenderBlock.cpp index 157d84bcc..1fc2d80f9 100755 --- a/Source/WebCore/rendering/RenderBlock.cpp +++ b/Source/WebCore/rendering/RenderBlock.cpp @@ -590,7 +590,13 @@ void RenderBlock::splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock, RenderBoxModelObject* curr = toRenderBoxModelObject(parent()); RenderBoxModelObject* currChild = this; RenderObject* currChildNextSibling = currChild->nextSibling(); - + bool documentUsesBeforeAfterRules = document()->usesBeforeAfterRules(); + + // Note: |this| can be destroyed inside this loop if it is an empty anonymous + // block and we try to call updateBeforeAfterContent inside which removes the + // generated content and additionally cleans up |this| empty anonymous block. + // See RenderBlock::removeChild(). DO NOT reference any local variables to |this| + // after this point. while (curr && curr != fromBlock) { ASSERT(curr->isRenderBlock()); @@ -617,7 +623,7 @@ void RenderBlock::splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock, // has to move into the inline continuation. Call updateBeforeAfterContent to ensure that the inline's :after // content gets properly destroyed. bool isLastChild = (currChildNextSibling == blockCurr->lastChild()); - if (document()->usesBeforeAfterRules()) + if (documentUsesBeforeAfterRules) blockCurr->children()->updateBeforeAfterContent(blockCurr, AFTER); if (isLastChild && currChildNextSibling != blockCurr->lastChild()) currChildNextSibling = 0; // We destroyed the last child, so now we need to update @@ -627,8 +633,7 @@ void RenderBlock::splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock, // Since we are doing layout anyway, it is easier to blow away the entire list, than // traversing down the subtree looking for positioned children and then remove them // from our positioned objects list. - if (currChildNextSibling) - blockCurr->removePositionedObjects(0); + blockCurr->removePositionedObjects(0); // Now we need to take all of the children starting from the first child // *after* currChild and append them all to the clone. @@ -1228,6 +1233,32 @@ void RenderBlock::removeChild(RenderObject* oldChild) // If this was our last child be sure to clear out our line boxes. if (childrenInline()) deleteLineBoxTree(); + + // If we are an empty anonymous block in the continuation chain, + // we need to remove ourself and fix the continuation chain. + if (!beingDestroyed() && isAnonymousBlockContinuation()) { + RenderObject* containingBlockIgnoringAnonymous = containingBlock(); + while (containingBlockIgnoringAnonymous && containingBlockIgnoringAnonymous->isAnonymousBlock()) + containingBlockIgnoringAnonymous = containingBlockIgnoringAnonymous->containingBlock(); + for (RenderObject* curr = this; curr; curr = curr->previousInPreOrder(containingBlockIgnoringAnonymous)) { + if (curr->virtualContinuation() != this) + continue; + + // Found our previous continuation. We just need to point it to + // |this|'s next continuation. + RenderBoxModelObject* nextContinuation = continuation(); + if (curr->isRenderInline()) + toRenderInline(curr)->setContinuation(nextContinuation); + else if (curr->isRenderBlock()) + toRenderBlock(curr)->setContinuation(nextContinuation); + else + ASSERT_NOT_REACHED(); + + break; + } + setContinuation(0); + destroy(); + } } } @@ -2643,17 +2674,18 @@ void RenderBlock::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& pain bool antialias = shouldAntialiasLines(paintInfo.context); if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) { - LayoutUnit currLogicalLeftOffset = style()->isLeftToRightDirection() ? ZERO_LAYOUT_UNIT : contentLogicalWidth(); + bool leftToRight = style()->isLeftToRightDirection() ^ colInfo->progressionIsReversed(); + LayoutUnit currLogicalLeftOffset = leftToRight ? ZERO_LAYOUT_UNIT : contentLogicalWidth(); LayoutUnit ruleAdd = logicalLeftOffsetForContent(); - LayoutUnit ruleLogicalLeft = style()->isLeftToRightDirection() ? ZERO_LAYOUT_UNIT : contentLogicalWidth(); + LayoutUnit ruleLogicalLeft = leftToRight ? ZERO_LAYOUT_UNIT : contentLogicalWidth(); LayoutUnit inlineDirectionSize = colInfo->desiredColumnWidth(); BoxSide boxSide = isHorizontalWritingMode() - ? style()->isLeftToRightDirection() ? BSLeft : BSRight - : style()->isLeftToRightDirection() ? BSTop : BSBottom; + ? leftToRight ? BSLeft : BSRight + : leftToRight ? BSTop : BSBottom; for (unsigned i = 0; i < colCount; i++) { // Move to the next position. - if (style()->isLeftToRightDirection()) { + if (leftToRight) { ruleLogicalLeft += inlineDirectionSize + colGap / 2; currLogicalLeftOffset += inlineDirectionSize + colGap; } else { @@ -2674,20 +2706,31 @@ void RenderBlock::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& pain ruleLogicalLeft = currLogicalLeftOffset; } } else { - LayoutUnit ruleLeft = isHorizontalWritingMode() ? borderLeft() + paddingLeft() : colGap / 2 - colGap - ruleThickness / 2 + borderBefore() + paddingBefore(); + bool topToBottom = !style()->isFlippedBlocksWritingMode() ^ colInfo->progressionIsReversed(); + LayoutUnit ruleLeft = isHorizontalWritingMode() + ? borderLeft() + paddingLeft() + : colGap / 2 - colGap - ruleThickness / 2 + (!colInfo->progressionIsReversed() ? borderBefore() + paddingBefore() : borderAfter() + paddingAfter()); LayoutUnit ruleWidth = isHorizontalWritingMode() ? contentWidth() : ruleThickness; - LayoutUnit ruleTop = isHorizontalWritingMode() ? colGap / 2 - colGap - ruleThickness / 2 + borderBefore() + paddingBefore() : borderStart() + paddingStart(); + LayoutUnit ruleTop = isHorizontalWritingMode() + ? colGap / 2 - colGap - ruleThickness / 2 + (!colInfo->progressionIsReversed() ? borderBefore() + paddingBefore() : borderAfter() + paddingAfter()) + : borderStart() + paddingStart(); LayoutUnit ruleHeight = isHorizontalWritingMode() ? ruleThickness : contentHeight(); LayoutRect ruleRect(ruleLeft, ruleTop, ruleWidth, ruleHeight); - flipForWritingMode(ruleRect); + if (!topToBottom) { + if (isHorizontalWritingMode()) + ruleRect.setY(height() - ruleRect.maxY()); + else + ruleRect.setX(width() - ruleRect.maxX()); + } + ruleRect.moveBy(paintOffset); BoxSide boxSide = isHorizontalWritingMode() - ? !style()->isFlippedBlocksWritingMode() ? BSTop : BSBottom - : !style()->isFlippedBlocksWritingMode() ? BSLeft : BSRight; + ? topToBottom ? BSTop : BSBottom + : topToBottom ? BSLeft : BSRight; - LayoutSize step(0, !style()->isFlippedBlocksWritingMode() ? colInfo->columnHeight() + colGap : -(colInfo->columnHeight() + colGap)); + LayoutSize step(0, topToBottom ? colInfo->columnHeight() + colGap : -(colInfo->columnHeight() + colGap)); if (!isHorizontalWritingMode()) step = step.transposedSize(); @@ -2739,7 +2782,7 @@ void RenderBlock::paintColumnContents(PaintInfo& paintInfo, const LayoutPoint& p // like overflow:hidden. // FIXME: Content and column rules that extend outside column boxes at the edges of the multi-column element // are clipped according to the 'overflow' property. - context->clip(clipRect); + context->clip(pixelSnappedIntRect(clipRect)); // Adjust our x and y when painting. LayoutPoint adjustedPaintOffset = paintOffset + offset; @@ -3166,12 +3209,12 @@ static void clipOutPositionedObjects(const PaintInfo* paintInfo, const LayoutPoi } } -static int blockDirectionOffset(RenderBlock* rootBlock, const LayoutSize& offsetFromRootBlock) +static LayoutUnit blockDirectionOffset(RenderBlock* rootBlock, const LayoutSize& offsetFromRootBlock) { return rootBlock->isHorizontalWritingMode() ? offsetFromRootBlock.height() : offsetFromRootBlock.width(); } -static int inlineDirectionOffset(RenderBlock* rootBlock, const LayoutSize& offsetFromRootBlock) +static LayoutUnit inlineDirectionOffset(RenderBlock* rootBlock, const LayoutSize& offsetFromRootBlock) { return rootBlock->isHorizontalWritingMode() ? offsetFromRootBlock.width() : offsetFromRootBlock.height(); } @@ -3377,31 +3420,23 @@ LayoutRect RenderBlock::blockSelectionGap(RenderBlock* rootBlock, const LayoutPo LayoutRect gapRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, LayoutRect(logicalLeft, logicalTop, logicalWidth, logicalHeight)); if (paintInfo) - paintInfo->context->fillRect(gapRect, selectionBackgroundColor(), style()->colorSpace()); + paintInfo->context->fillRect(pixelSnappedIntRect(gapRect), selectionBackgroundColor(), style()->colorSpace()); return gapRect; } -static inline void alignSelectionRectToDevicePixels(LayoutRect& rect) -{ - LayoutUnit maxX = floorToInt(rect.maxX()); - rect.setX(floorToInt(rect.x())); - rect.setWidth((maxX - rect.x()).round()); -} - LayoutRect RenderBlock::logicalLeftSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock, RenderObject* selObj, LayoutUnit logicalLeft, LayoutUnit logicalTop, LayoutUnit logicalHeight, const PaintInfo* paintInfo) { LayoutUnit rootBlockLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalTop; LayoutUnit rootBlockLogicalLeft = max(logicalLeftSelectionOffset(rootBlock, logicalTop), logicalLeftSelectionOffset(rootBlock, logicalTop + logicalHeight)); - LayoutUnit rootBlockLogicalRight = min(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + logicalLeft, min(logicalRightSelectionOffset(rootBlock, logicalTop), logicalRightSelectionOffset(rootBlock, logicalTop + logicalHeight))); + LayoutUnit rootBlockLogicalRight = min(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + floorToInt(logicalLeft), min(logicalRightSelectionOffset(rootBlock, logicalTop), logicalRightSelectionOffset(rootBlock, logicalTop + logicalHeight))); LayoutUnit rootBlockLogicalWidth = rootBlockLogicalRight - rootBlockLogicalLeft; if (rootBlockLogicalWidth <= ZERO_LAYOUT_UNIT) return LayoutRect(); LayoutRect gapRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, LayoutRect(rootBlockLogicalLeft, rootBlockLogicalTop, rootBlockLogicalWidth, logicalHeight)); - alignSelectionRectToDevicePixels(gapRect); if (paintInfo) - paintInfo->context->fillRect(gapRect, selObj->selectionBackgroundColor(), selObj->style()->colorSpace()); + paintInfo->context->fillRect(pixelSnappedIntRect(gapRect), selObj->selectionBackgroundColor(), selObj->style()->colorSpace()); return gapRect; } @@ -3409,16 +3444,15 @@ LayoutRect RenderBlock::logicalRightSelectionGap(RenderBlock* rootBlock, const L RenderObject* selObj, LayoutUnit logicalRight, LayoutUnit logicalTop, LayoutUnit logicalHeight, const PaintInfo* paintInfo) { LayoutUnit rootBlockLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalTop; - LayoutUnit rootBlockLogicalLeft = max(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + logicalRight, max(logicalLeftSelectionOffset(rootBlock, logicalTop), logicalLeftSelectionOffset(rootBlock, logicalTop + logicalHeight))); + LayoutUnit rootBlockLogicalLeft = max(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + floorToInt(logicalRight), max(logicalLeftSelectionOffset(rootBlock, logicalTop), logicalLeftSelectionOffset(rootBlock, logicalTop + logicalHeight))); LayoutUnit rootBlockLogicalRight = min(logicalRightSelectionOffset(rootBlock, logicalTop), logicalRightSelectionOffset(rootBlock, logicalTop + logicalHeight)); LayoutUnit rootBlockLogicalWidth = rootBlockLogicalRight - rootBlockLogicalLeft; if (rootBlockLogicalWidth <= ZERO_LAYOUT_UNIT) return LayoutRect(); LayoutRect gapRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, LayoutRect(rootBlockLogicalLeft, rootBlockLogicalTop, rootBlockLogicalWidth, logicalHeight)); - alignSelectionRectToDevicePixels(gapRect); if (paintInfo) - paintInfo->context->fillRect(gapRect, selObj->selectionBackgroundColor(), selObj->style()->colorSpace()); + paintInfo->context->fillRect(pixelSnappedIntRect(gapRect), selObj->selectionBackgroundColor(), selObj->style()->colorSpace()); return gapRect; } @@ -3513,18 +3547,12 @@ void RenderBlock::insertPositionedObject(RenderBox* o) m_positionedObjects = adoptPtr(new PositionedObjectsListHashSet); m_positionedObjects->add(o); - - if (o->style()->position() == FixedPosition && view()) - view()->insertFixedPositionedObject(o); } void RenderBlock::removePositionedObject(RenderBox* o) { if (m_positionedObjects) m_positionedObjects->remove(o); - - if (view()) - view()->removeFixedPositionedObject(o); } void RenderBlock::removePositionedObjects(RenderBlock* o) @@ -4963,6 +4991,7 @@ void RenderBlock::setDesiredColumnCountAndWidth(int count, LayoutUnit width) info->setDesiredColumnCount(count); info->setDesiredColumnWidth(width); info->setProgressionAxis(style()->hasInlineColumnAxis() ? ColumnInfo::InlineAxis : ColumnInfo::BlockAxis); + info->setProgressionIsReversed(style()->columnProgression() == ReverseColumnProgression); } } @@ -5005,12 +5034,16 @@ LayoutRect RenderBlock::columnRectAt(ColumnInfo* colInfo, unsigned index) const LayoutUnit colLogicalLeft = logicalLeftOffsetForContent(); int colGap = columnGap(); if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) { - if (style()->isLeftToRightDirection()) + if (style()->isLeftToRightDirection() ^ colInfo->progressionIsReversed()) colLogicalLeft += index * (colLogicalWidth + colGap); else colLogicalLeft += contentLogicalWidth() - colLogicalWidth - index * (colLogicalWidth + colGap); - } else - colLogicalTop += index * (colLogicalHeight + colGap); + } else { + if (!colInfo->progressionIsReversed()) + colLogicalTop += index * (colLogicalHeight + colGap); + else + colLogicalTop += contentLogicalHeight() - colLogicalHeight - index * (colLogicalHeight + colGap); + } if (isHorizontalWritingMode()) return LayoutRect(colLogicalLeft, colLogicalTop, colLogicalWidth, colLogicalHeight); @@ -5697,9 +5730,6 @@ void RenderBlock::computeInlinePreferredLogicalWidths() updatePreferredWidth(m_maxPreferredLogicalWidth, inlineMax); } -// Use a very large value (in effect infinite). -#define BLOCK_MAX_WIDTH 15000 - void RenderBlock::computeBlockPreferredLogicalWidths() { RenderStyle* styleToUse = style(); @@ -6493,80 +6523,17 @@ LayoutRect RenderBlock::localCaretRect(InlineBox* inlineBox, int caretOffset, La if (firstChild()) return RenderBox::localCaretRect(inlineBox, caretOffset, extraWidthToEndOfLine); - // This is a special case: - // The element is not an inline element, and it's empty. So we have to - // calculate a fake position to indicate where objects are to be inserted. - - // FIXME: This does not take into account either :first-line or :first-letter - // However, as soon as some content is entered, the line boxes will be - // constructed and this kludge is not called any more. So only the caret size - // of an empty :first-line'd block is wrong. I think we can live with that. - RenderStyle* currentStyle = firstLineStyle(); - LayoutUnit height = lineHeight(true, currentStyle->isHorizontalWritingMode() ? HorizontalLine : VerticalLine); - - enum CaretAlignment { alignLeft, alignRight, alignCenter }; - - CaretAlignment alignment = alignLeft; - - switch (currentStyle->textAlign()) { - case TAAUTO: - case JUSTIFY: - if (!currentStyle->isLeftToRightDirection()) - alignment = alignRight; - break; - case LEFT: - case WEBKIT_LEFT: - break; - case CENTER: - case WEBKIT_CENTER: - alignment = alignCenter; - break; - case RIGHT: - case WEBKIT_RIGHT: - alignment = alignRight; - break; - case TASTART: - if (!currentStyle->isLeftToRightDirection()) - alignment = alignRight; - break; - case TAEND: - if (currentStyle->isLeftToRightDirection()) - alignment = alignRight; - break; - } - - LayoutUnit x = borderLeft() + paddingLeft(); - LayoutUnit w = width(); - - switch (alignment) { - case alignLeft: - if (currentStyle->isLeftToRightDirection()) - x += textIndentOffset(); - break; - case alignCenter: - x = (x + w - (borderRight() + paddingRight())) / 2; - if (currentStyle->isLeftToRightDirection()) - x += textIndentOffset() / 2; - else - x -= textIndentOffset() / 2; - break; - case alignRight: - x = w - (borderRight() + paddingRight()) - caretWidth; - if (!currentStyle->isLeftToRightDirection()) - x -= textIndentOffset(); - break; - } - x = min(x, w - borderRight() - paddingRight() - caretWidth); + LayoutRect caretRect = localCaretRectForEmptyElement(width(), textIndentOffset()); if (extraWidthToEndOfLine) { if (isRenderBlock()) { - *extraWidthToEndOfLine = w - (x + caretWidth); + *extraWidthToEndOfLine = width() - caretRect.maxX(); } else { // FIXME: This code looks wrong. // myRight and containerRight are set up, but then clobbered. // So *extraWidthToEndOfLine will always be 0 here. - LayoutUnit myRight = x + caretWidth; + LayoutUnit myRight = caretRect.maxX(); // FIXME: why call localToAbsoluteForContent() twice here, too? FloatPoint absRightPoint = localToAbsolute(FloatPoint(myRight, 0)); @@ -6577,9 +6544,7 @@ LayoutRect RenderBlock::localCaretRect(InlineBox* inlineBox, int caretOffset, La } } - LayoutUnit y = paddingTop() + borderTop(); - - return LayoutRect(x, y, caretWidth, height); + return caretRect; } void RenderBlock::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& additionalOffset) diff --git a/Source/WebCore/rendering/RenderBlockLineLayout.cpp b/Source/WebCore/rendering/RenderBlockLineLayout.cpp index eb7e87efb..046ffef39 100755 --- a/Source/WebCore/rendering/RenderBlockLineLayout.cpp +++ b/Source/WebCore/rendering/RenderBlockLineLayout.cpp @@ -98,7 +98,7 @@ public: private: void computeAvailableWidthFromLeftAndRight() { - m_availableWidth = max(0, m_right - m_left) + m_overhangWidth; + m_availableWidth = max(0.0f, m_right - m_left) + m_overhangWidth; } private: @@ -106,8 +106,8 @@ private: float m_uncommittedWidth; float m_committedWidth; float m_overhangWidth; // The amount by which |m_availableWidth| has been inflated to account for possible contraction due to ruby overhang. - int m_left; - int m_right; + float m_left; + float m_right; float m_availableWidth; bool m_isFirstLine; }; @@ -115,8 +115,8 @@ private: inline void LineWidth::updateAvailableWidth() { LayoutUnit height = m_block->logicalHeight(); - m_left = m_block->pixelSnappedLogicalLeftOffsetForLine(height, m_isFirstLine); - m_right = m_block->pixelSnappedLogicalRightOffsetForLine(height, m_isFirstLine); + m_left = m_block->logicalLeftOffsetForLine(height, m_isFirstLine); + m_right = m_block->logicalRightOffsetForLine(height, m_isFirstLine); computeAvailableWidthFromLeftAndRight(); } @@ -554,7 +554,7 @@ ETextAlign RenderBlock::textAlignmentForLine(bool endsWithSoftBreak) const { ETextAlign alignment = style()->textAlign(); if (!endsWithSoftBreak && alignment == JUSTIFY) - alignment = TAAUTO; + alignment = TASTART; return alignment; } @@ -714,6 +714,14 @@ void RenderBlock::updateLogicalWidthForAlignment(const ETextAlign& textAlign, Bi case WEBKIT_LEFT: updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); break; + case RIGHT: + case WEBKIT_RIGHT: + updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); + break; + case CENTER: + case WEBKIT_CENTER: + updateLogicalWidthForCenterAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); + break; case JUSTIFY: adjustInlineDirectionLineBounds(expansionOpportunityCount, logicalLeft, availableLogicalWidth); if (expansionOpportunityCount) { @@ -723,22 +731,7 @@ void RenderBlock::updateLogicalWidthForAlignment(const ETextAlign& textAlign, Bi } break; } - // fall through - case TAAUTO: - // for right to left fall through to right aligned - if (style()->isLeftToRightDirection()) { - if (totalLogicalWidth > availableLogicalWidth && trailingSpaceRun) - trailingSpaceRun->m_box->setLogicalWidth(max<float>(0, trailingSpaceRun->m_box->logicalWidth() - totalLogicalWidth + availableLogicalWidth)); - break; - } - case RIGHT: - case WEBKIT_RIGHT: - updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); - break; - case CENTER: - case WEBKIT_CENTER: - updateLogicalWidthForCenterAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); - break; + // Fall through case TASTART: if (style()->isLeftToRightDirection()) updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); @@ -2774,7 +2767,7 @@ LayoutUnit RenderBlock::startAlignedOffsetForLine(RenderBox* child, LayoutUnit p { ETextAlign textAlign = style()->textAlign(); - if (textAlign == TAAUTO) + if (textAlign == TASTART) // FIXME: Handle TAEND here return startOffsetForLine(position, firstLine); // updateLogicalWidthForAlignment() handles the direction of the block so no need to consider it here diff --git a/Source/WebCore/rendering/RenderBox.cpp b/Source/WebCore/rendering/RenderBox.cpp index d6f460eb3..ddca07dd2 100644 --- a/Source/WebCore/rendering/RenderBox.cpp +++ b/Source/WebCore/rendering/RenderBox.cpp @@ -142,7 +142,7 @@ void RenderBox::willBeDestroyed() if (RenderView* view = this->view()) { if (FrameView* frameView = view->frameView()) { if (styleToUse->position() == FixedPosition) - frameView->removeFixedObject(); + frameView->removeFixedObject(this); } } } @@ -221,9 +221,9 @@ void RenderBox::styleWillChange(StyleDifference diff, const RenderStyle* newStyl bool oldStyleIsFixed = oldStyle && oldStyle->position() == FixedPosition; if (newStyleIsFixed != oldStyleIsFixed) { if (newStyleIsFixed) - frameView->addFixedObject(); + frameView->addFixedObject(this); else - frameView->removeFixedObject(); + frameView->removeFixedObject(this); } } @@ -677,14 +677,14 @@ bool RenderBox::hasOverrideWidth() const return gOverrideWidthMap && gOverrideWidthMap->contains(this); } -void RenderBox::setOverrideHeight(LayoutUnit height) +void RenderBox::setOverrideLogicalContentHeight(LayoutUnit height) { if (!gOverrideHeightMap) gOverrideHeightMap = new OverrideSizeMap(); gOverrideHeightMap->set(this, height); } -void RenderBox::setOverrideWidth(LayoutUnit width) +void RenderBox::setOverrideLogicalContentWidth(LayoutUnit width) { if (!gOverrideWidthMap) gOverrideWidthMap = new OverrideSizeMap(); @@ -699,14 +699,14 @@ void RenderBox::clearOverrideSize() gOverrideWidthMap->remove(this); } -LayoutUnit RenderBox::overrideWidth() const +LayoutUnit RenderBox::overrideLogicalContentWidth() const { - return hasOverrideWidth() ? gOverrideWidthMap->get(this) : width(); + return hasOverrideWidth() ? gOverrideWidthMap->get(this) : contentWidth(); } -LayoutUnit RenderBox::overrideHeight() const +LayoutUnit RenderBox::overrideLogicalContentHeight() const { - return hasOverrideHeight() ? gOverrideHeightMap->get(this) : height(); + return hasOverrideHeight() ? gOverrideHeightMap->get(this) : contentHeight(); } LayoutUnit RenderBox::computeBorderBoxLogicalWidth(LayoutUnit width) const @@ -1241,6 +1241,9 @@ LayoutUnit RenderBox::containingBlockAvailableLineWidthInRegion(RenderRegion* re LayoutUnit RenderBox::perpendicularContainingBlockLogicalHeight() const { RenderBlock* cb = containingBlock(); + if (cb->hasOverrideHeight()) + return cb->overrideLogicalContentHeight(); + RenderStyle* containingBlockStyle = cb->style(); Length logicalHeightLength = containingBlockStyle->logicalHeight(); @@ -1649,7 +1652,7 @@ void RenderBox::computeLogicalWidthInRegion(RenderRegion* region, LayoutUnit off // FIXME: Account for block-flow in flexible boxes. // https://bugs.webkit.org/show_bug.cgi?id=46418 if (hasOverrideWidth() && parent()->isFlexibleBoxIncludingDeprecated()) { - setLogicalWidth(overrideWidth()); + setLogicalWidth(overrideLogicalContentWidth() + borderAndPaddingLogicalWidth()); return; } @@ -1689,25 +1692,19 @@ void RenderBox::computeLogicalWidthInRegion(RenderRegion* region, LayoutUnit off // Calculate MaxLogicalWidth if (!styleToUse->logicalMaxWidth().isUndefined()) { LayoutUnit maxLogicalWidth = computeLogicalWidthInRegionUsing(MaxLogicalWidth, containerWidthInInlineDirection, cb, region, offsetFromLogicalTopOfFirstPage); - if (logicalWidth() > maxLogicalWidth) { + if (logicalWidth() > maxLogicalWidth) setLogicalWidth(maxLogicalWidth); - logicalWidthLength = styleToUse->logicalMaxWidth(); - } } // Calculate MinLogicalWidth LayoutUnit minLogicalWidth = computeLogicalWidthInRegionUsing(MinLogicalWidth, containerWidthInInlineDirection, cb, region, offsetFromLogicalTopOfFirstPage); - if (logicalWidth() < minLogicalWidth) { + if (logicalWidth() < minLogicalWidth) setLogicalWidth(minLogicalWidth); - logicalWidthLength = styleToUse->logicalMinWidth(); - } } // Fieldsets are currently the only objects that stretch to their minimum width. - if (stretchesToMinIntrinsicLogicalWidth()) { + if (stretchesToMinIntrinsicLogicalWidth()) setLogicalWidth(max(logicalWidth(), minPreferredLogicalWidth())); - logicalWidthLength = Length(logicalWidth(), Fixed); - } // Margin calculations. if (hasPerpendicularContainingBlock || isFloating() || isInline()) { @@ -1983,7 +1980,7 @@ void RenderBox::computeLogicalHeight() // https://bugs.webkit.org/show_bug.cgi?id=46418 RenderStyle* styleToUse = style(); if (hasOverrideHeight() && parent()->isFlexibleBoxIncludingDeprecated()) - h = Length(overrideHeight() - borderAndPaddingLogicalHeight(), Fixed); + h = Length(overrideLogicalContentHeight(), Fixed); else if (treatAsReplaced) h = Length(computeReplacedLogicalHeight(), Fixed); else { @@ -2122,7 +2119,7 @@ LayoutUnit RenderBox::computePercentageLogicalHeight(const Length& height) return 0; return -1; } - result = cb->overrideHeight(); + result = cb->overrideLogicalContentHeight(); includeBorderPadding = true; } } @@ -2286,7 +2283,7 @@ LayoutUnit RenderBox::availableLogicalHeightUsing(const Length& h) const // artificially. We're going to rely on this cell getting expanded to some new // height, and then when we lay out again we'll use the calculation below. if (isTableCell() && (h.isAuto() || h.isPercent())) - return overrideHeight() - borderAndPaddingLogicalWidth(); + return overrideLogicalContentHeight(); if (h.isPercent()) { LayoutUnit availableHeight; diff --git a/Source/WebCore/rendering/RenderBox.h b/Source/WebCore/rendering/RenderBox.h index c3696ab8d..4bebf7eab 100644 --- a/Source/WebCore/rendering/RenderBox.h +++ b/Source/WebCore/rendering/RenderBox.h @@ -268,12 +268,12 @@ public: virtual LayoutUnit minPreferredLogicalWidth() const; virtual LayoutUnit maxPreferredLogicalWidth() const; - LayoutUnit overrideWidth() const; - LayoutUnit overrideHeight() const; + LayoutUnit overrideLogicalContentWidth() const; + LayoutUnit overrideLogicalContentHeight() const; bool hasOverrideHeight() const; bool hasOverrideWidth() const; - void setOverrideHeight(LayoutUnit); - void setOverrideWidth(LayoutUnit); + void setOverrideLogicalContentHeight(LayoutUnit); + void setOverrideLogicalContentWidth(LayoutUnit); void clearOverrideSize(); virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&, bool* offsetDependsOnPoint = 0) const; diff --git a/Source/WebCore/rendering/RenderBoxModelObject.cpp b/Source/WebCore/rendering/RenderBoxModelObject.cpp index 0cbf9913f..d40fba151 100644 --- a/Source/WebCore/rendering/RenderBoxModelObject.cpp +++ b/Source/WebCore/rendering/RenderBoxModelObject.cpp @@ -811,7 +811,11 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co scrolledPaintRect.width() - bLeft - bRight - (includePadding ? pLeft + pRight : ZERO_LAYOUT_UNIT), scrolledPaintRect.height() - borderTop() - borderBottom() - (includePadding ? paddingTop() + paddingBottom() : ZERO_LAYOUT_UNIT)); backgroundClipStateSaver.save(); - context->clip(clipRect); + if (clipToBorderRadius && includePadding) { + RoundedRect rounded = getBackgroundRoundedRect(clipRect, box, boxSize.width(), boxSize.height(), includeLeftEdge, includeRightEdge); + context->addRoundedRectClip(rounded); + } else + context->clip(clipRect); } else if (bgLayer->clip() == TextFillBox) { // We have to draw our text into a mask that can then be used to clip background drawing. // First figure out how big the mask has to be. It should be no bigger than what we need @@ -977,7 +981,7 @@ static inline IntSize resolveAgainstIntrinsicRatio(const IntSize& size, const Fl return IntSize(size.width(), solutionHeight); } -IntSize RenderBoxModelObject::calculateImageIntrinsicDimensions(StyleImage* image, const IntSize& positioningAreaSize) const +IntSize RenderBoxModelObject::calculateImageIntrinsicDimensions(StyleImage* image, const IntSize& positioningAreaSize, ScaleByEffectiveZoomOrNot shouldScaleOrNot) const { // A generated image without a fixed size, will always return the container size as intrinsic size. if (image->isGeneratedImage() && image->usesImageContainerSize()) @@ -1001,7 +1005,8 @@ IntSize RenderBoxModelObject::calculateImageIntrinsicDimensions(StyleImage* imag IntSize resolvedSize(intrinsicWidth.isFixed() ? intrinsicWidth.value() : 0, intrinsicHeight.isFixed() ? intrinsicHeight.value() : 0); IntSize minimumSize(resolvedSize.width() > 0 ? 1 : 0, resolvedSize.height() > 0 ? 1 : 0); - resolvedSize.scale(style()->effectiveZoom()); + if (shouldScaleOrNot == ScaleByEffectiveZoom) + resolvedSize.scale(style()->effectiveZoom()); resolvedSize.clampToMinimumSize(minimumSize); if (!resolvedSize.isEmpty()) @@ -1030,7 +1035,7 @@ IntSize RenderBoxModelObject::calculateFillTileSize(const FillLayer* fillLayer, StyleImage* image = fillLayer->image(); EFillSizeType type = fillLayer->size().type; - IntSize imageIntrinsicSize = calculateImageIntrinsicDimensions(image, positioningAreaSize); + IntSize imageIntrinsicSize = calculateImageIntrinsicDimensions(image, positioningAreaSize, ScaleByEffectiveZoom); imageIntrinsicSize.scale(1 / image->imageScaleFactor(), 1 / image->imageScaleFactor()); RenderView* renderView = view(); switch (type) { @@ -1241,13 +1246,13 @@ bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext, LayoutUnit rightWithOutset = rect.maxX() + rightOutset; IntRect borderImageRect = pixelSnappedIntRect(leftWithOutset, topWithOutset, rightWithOutset - leftWithOutset, bottomWithOutset - topWithOutset); - IntSize imageSize = calculateImageIntrinsicDimensions(styleImage, borderImageRect.size()); + IntSize imageSize = calculateImageIntrinsicDimensions(styleImage, borderImageRect.size(), DoNotScaleByEffectiveZoom); // If both values are ‘auto’ then the intrinsic width and/or height of the image should be used, if any. styleImage->setContainerSizeForRenderer(this, imageSize, style->effectiveZoom()); - int imageWidth = imageSize.width() / style->effectiveZoom(); - int imageHeight = imageSize.height() / style->effectiveZoom(); + int imageWidth = imageSize.width(); + int imageHeight = imageSize.height(); RenderView* renderView = view(); float imageScaleFactor = styleImage->imageScaleFactor(); @@ -1493,7 +1498,6 @@ static bool allCornersClippedOut(const RoundedRect& border, const LayoutRect& cl return true; } -#if HAVE(PATH_BASED_BORDER_RADIUS_DRAWING) static bool borderWillArcInnerEdge(const LayoutSize& firstRadius, const FloatSize& secondRadius) { return !firstRadius.isZero() || !secondRadius.isZero(); @@ -2100,337 +2104,17 @@ void RenderBoxModelObject::drawBoxSideFromPath(GraphicsContext* graphicsContext, graphicsContext->setFillColor(color, style->colorSpace()); graphicsContext->drawRect(pixelSnappedIntRect(borderRect)); } -#else -void RenderBoxModelObject::paintBorder(const PaintInfo& info, const IntRect& rect, const RenderStyle* style, - BackgroundBleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) -{ - GraphicsContext* graphicsContext = info.context; - // FIXME: This old version of paintBorder should be removed when all ports implement - // GraphicsContext::clipConvexPolygon()!! This should happen soon. - if (paintNinePieceImage(graphicsContext, rect, style, style->borderImage())) - return; - - const Color& topColor = style->visitedDependentColor(CSSPropertyBorderTopColor); - const Color& bottomColor = style->visitedDependentColor(CSSPropertyBorderBottomColor); - const Color& leftColor = style->visitedDependentColor(CSSPropertyBorderLeftColor); - const Color& rightColor = style->visitedDependentColor(CSSPropertyBorderRightColor); - - bool topTransparent = style->borderTopIsTransparent(); - bool bottomTransparent = style->borderBottomIsTransparent(); - bool rightTransparent = style->borderRightIsTransparent(); - bool leftTransparent = style->borderLeftIsTransparent(); - - EBorderStyle topStyle = style->borderTopStyle(); - EBorderStyle bottomStyle = style->borderBottomStyle(); - EBorderStyle leftStyle = style->borderLeftStyle(); - EBorderStyle rightStyle = style->borderRightStyle(); - - bool horizontal = style->isHorizontalWritingMode(); - bool renderTop = topStyle > BHIDDEN && !topTransparent && (horizontal || includeLogicalLeftEdge); - bool renderLeft = leftStyle > BHIDDEN && !leftTransparent && (!horizontal || includeLogicalLeftEdge); - bool renderRight = rightStyle > BHIDDEN && !rightTransparent && (!horizontal || includeLogicalRightEdge); - bool renderBottom = bottomStyle > BHIDDEN && !bottomTransparent && (horizontal || includeLogicalRightEdge); - - - RoundedRect border(rect); - - GraphicsContextStateSaver stateSaver(*graphicsContext, false); - if (style->hasBorderRadius()) { - border.includeLogicalEdges(style->getRoundedBorderFor(border.rect(), view()).radii(), - horizontal, includeLogicalLeftEdge, includeLogicalRightEdge); - if (border.isRounded()) { - stateSaver.save(); - graphicsContext->addRoundedRectClip(border); - } - } - - int firstAngleStart, secondAngleStart, firstAngleSpan, secondAngleSpan; - float thickness; - bool renderRadii = border.isRounded(); - bool upperLeftBorderStylesMatch = renderLeft && (topStyle == leftStyle) && (topColor == leftColor); - bool upperRightBorderStylesMatch = renderRight && (topStyle == rightStyle) && (topColor == rightColor) && (topStyle != OUTSET) && (topStyle != RIDGE) && (topStyle != INSET) && (topStyle != GROOVE); - bool lowerLeftBorderStylesMatch = renderLeft && (bottomStyle == leftStyle) && (bottomColor == leftColor) && (bottomStyle != OUTSET) && (bottomStyle != RIDGE) && (bottomStyle != INSET) && (bottomStyle != GROOVE); - bool lowerRightBorderStylesMatch = renderRight && (bottomStyle == rightStyle) && (bottomColor == rightColor); - - if (renderTop) { - bool ignoreLeft = (renderRadii && border.radii().topLeft().width() > 0) - || (topColor == leftColor && topTransparent == leftTransparent && topStyle >= OUTSET - && (leftStyle == DOTTED || leftStyle == DASHED || leftStyle == SOLID || leftStyle == OUTSET)); - - bool ignoreRight = (renderRadii && border.radii().topRight().width() > 0) - || (topColor == rightColor && topTransparent == rightTransparent && topStyle >= OUTSET - && (rightStyle == DOTTED || rightStyle == DASHED || rightStyle == SOLID || rightStyle == INSET)); - - int x = rect.x(); - int x2 = rect.maxX(); - if (renderRadii) { - x += border.radii().topLeft().width(); - x2 -= border.radii().topRight().width(); - } - - drawLineForBoxSide(graphicsContext, x, rect.y(), x2, rect.y() + style->borderTopWidth(), BSTop, topColor, topStyle, - ignoreLeft ? 0 : style->borderLeftWidth(), ignoreRight ? 0 : style->borderRightWidth()); - - if (renderRadii) { - int leftY = rect.y(); - - // We make the arc double thick and let the clip rect take care of clipping the extra off. - // We're doing this because it doesn't seem possible to match the curve of the clip exactly - // with the arc-drawing function. - thickness = style->borderTopWidth() * 2; - - if (border.radii().topLeft().width()) { - int leftX = rect.x(); - // The inner clip clips inside the arc. This is especially important for 1px borders. - bool applyLeftInnerClip = (style->borderLeftWidth() < border.radii().topLeft().width()) - && (style->borderTopWidth() < border.radii().topLeft().height()) - && (topStyle != DOUBLE || style->borderTopWidth() > 6); - - GraphicsContextStateSaver stateSaver(*graphicsContext, applyLeftInnerClip); - if (applyLeftInnerClip) - graphicsContext->addInnerRoundedRectClip(IntRect(leftX, leftY, border.radii().topLeft().width() * 2, border.radii().topLeft().height() * 2), - style->borderTopWidth()); - - firstAngleStart = 90; - firstAngleSpan = upperLeftBorderStylesMatch ? 90 : 45; - - // Draw upper left arc - drawArcForBoxSide(graphicsContext, leftX, leftY, thickness, border.radii().topLeft(), firstAngleStart, firstAngleSpan, - BSTop, topColor, topStyle, true); - } - - if (border.radii().topRight().width()) { - int rightX = rect.maxX() - border.radii().topRight().width() * 2; - bool applyRightInnerClip = (style->borderRightWidth() < border.radii().topRight().width()) - && (style->borderTopWidth() < border.radii().topRight().height()) - && (topStyle != DOUBLE || style->borderTopWidth() > 6); - - GraphicsContextStateSaver stateSaver(*graphicsContext, applyRightInnerClip); - if (applyRightInnerClip) - graphicsContext->addInnerRoundedRectClip(IntRect(rightX, leftY, border.radii().topRight().width() * 2, border.radii().topRight().height() * 2), - style->borderTopWidth()); - - if (upperRightBorderStylesMatch) { - secondAngleStart = 0; - secondAngleSpan = 90; - } else { - secondAngleStart = 45; - secondAngleSpan = 45; - } - - // Draw upper right arc - drawArcForBoxSide(graphicsContext, rightX, leftY, thickness, border.radii().topRight(), secondAngleStart, secondAngleSpan, - BSTop, topColor, topStyle, false); - } - } - } - - if (renderBottom) { - bool ignoreLeft = (renderRadii && border.radii().bottomLeft().width() > 0) - || (bottomColor == leftColor && bottomTransparent == leftTransparent && bottomStyle >= OUTSET - && (leftStyle == DOTTED || leftStyle == DASHED || leftStyle == SOLID || leftStyle == OUTSET)); - - bool ignoreRight = (renderRadii && border.radii().bottomRight().width() > 0) - || (bottomColor == rightColor && bottomTransparent == rightTransparent && bottomStyle >= OUTSET - && (rightStyle == DOTTED || rightStyle == DASHED || rightStyle == SOLID || rightStyle == INSET)); - - int x = rect.x(); - int x2 = rect.maxX(); - if (renderRadii) { - x += border.radii().bottomLeft().width(); - x2 -= border.radii().bottomRight().width(); - } - - drawLineForBoxSide(graphicsContext, x, rect.maxY() - style->borderBottomWidth(), x2, rect.maxY(), BSBottom, bottomColor, bottomStyle, - ignoreLeft ? 0 : style->borderLeftWidth(), ignoreRight ? 0 : style->borderRightWidth()); - - if (renderRadii) { - thickness = style->borderBottomWidth() * 2; - - if (border.radii().bottomLeft().width()) { - int leftX = rect.x(); - int leftY = rect.maxY() - border.radii().bottomLeft().height() * 2; - bool applyLeftInnerClip = (style->borderLeftWidth() < border.radii().bottomLeft().width()) - && (style->borderBottomWidth() < border.radii().bottomLeft().height()) - && (bottomStyle != DOUBLE || style->borderBottomWidth() > 6); - - GraphicsContextStateSaver stateSaver(*graphicsContext, applyLeftInnerClip); - if (applyLeftInnerClip) - graphicsContext->addInnerRoundedRectClip(IntRect(leftX, leftY, border.radii().bottomLeft().width() * 2, border.radii().bottomLeft().height() * 2), - style->borderBottomWidth()); - - if (lowerLeftBorderStylesMatch) { - firstAngleStart = 180; - firstAngleSpan = 90; - } else { - firstAngleStart = 225; - firstAngleSpan = 45; - } - - // Draw lower left arc - drawArcForBoxSide(graphicsContext, leftX, leftY, thickness, border.radii().bottomLeft(), firstAngleStart, firstAngleSpan, - BSBottom, bottomColor, bottomStyle, true); - } - - if (border.radii().bottomRight().width()) { - int rightY = rect.maxY() - border.radii().bottomRight().height() * 2; - int rightX = rect.maxX() - border.radii().bottomRight().width() * 2; - bool applyRightInnerClip = (style->borderRightWidth() < border.radii().bottomRight().width()) - && (style->borderBottomWidth() < border.radii().bottomRight().height()) - && (bottomStyle != DOUBLE || style->borderBottomWidth() > 6); - - GraphicsContextStateSaver stateSaver(*graphicsContext, applyRightInnerClip); - if (applyRightInnerClip) - graphicsContext->addInnerRoundedRectClip(IntRect(rightX, rightY, border.radii().bottomRight().width() * 2, border.radii().bottomRight().height() * 2), - style->borderBottomWidth()); - - secondAngleStart = 270; - secondAngleSpan = lowerRightBorderStylesMatch ? 90 : 45; - - // Draw lower right arc - drawArcForBoxSide(graphicsContext, rightX, rightY, thickness, border.radii().bottomRight(), secondAngleStart, secondAngleSpan, - BSBottom, bottomColor, bottomStyle, false); - } - } - } - - if (renderLeft) { - bool ignoreTop = (renderRadii && border.radii().topLeft().height() > 0) - || (topColor == leftColor && topTransparent == leftTransparent && leftStyle >= OUTSET - && (topStyle == DOTTED || topStyle == DASHED || topStyle == SOLID || topStyle == OUTSET)); - - bool ignoreBottom = (renderRadii && border.radii().bottomLeft().height() > 0) - || (bottomColor == leftColor && bottomTransparent == leftTransparent && leftStyle >= OUTSET - && (bottomStyle == DOTTED || bottomStyle == DASHED || bottomStyle == SOLID || bottomStyle == INSET)); - - int y = rect.y(); - int y2 = rect.maxY(); - if (renderRadii) { - y += border.radii().topLeft().height(); - y2 -= border.radii().bottomLeft().height(); - } - - drawLineForBoxSide(graphicsContext, rect.x(), y, rect.x() + style->borderLeftWidth(), y2, BSLeft, leftColor, leftStyle, - ignoreTop ? 0 : style->borderTopWidth(), ignoreBottom ? 0 : style->borderBottomWidth()); - - if (renderRadii && (!upperLeftBorderStylesMatch || !lowerLeftBorderStylesMatch)) { - int topX = rect.x(); - thickness = style->borderLeftWidth() * 2; - - if (!upperLeftBorderStylesMatch && border.radii().topLeft().width()) { - int topY = rect.y(); - bool applyTopInnerClip = (style->borderLeftWidth() < border.radii().topLeft().width()) - && (style->borderTopWidth() < border.radii().topLeft().height()) - && (leftStyle != DOUBLE || style->borderLeftWidth() > 6); - - GraphicsContextStateSaver stateSaver(*graphicsContext, applyTopInnerClip); - if (applyTopInnerClip) - graphicsContext->addInnerRoundedRectClip(IntRect(topX, topY, border.radii().topLeft().width() * 2, border.radii().topLeft().height() * 2), - style->borderLeftWidth()); - - firstAngleStart = 135; - firstAngleSpan = 45; - - // Draw top left arc - drawArcForBoxSide(graphicsContext, topX, topY, thickness, border.radii().topLeft(), firstAngleStart, firstAngleSpan, - BSLeft, leftColor, leftStyle, true); - } - - if (!lowerLeftBorderStylesMatch && border.radii().bottomLeft().width()) { - int bottomY = rect.maxY() - border.radii().bottomLeft().height() * 2; - bool applyBottomInnerClip = (style->borderLeftWidth() < border.radii().bottomLeft().width()) - && (style->borderBottomWidth() < border.radii().bottomLeft().height()) - && (leftStyle != DOUBLE || style->borderLeftWidth() > 6); - - GraphicsContextStateSaver stateSaver(*graphicsContext, applyBottomInnerClip); - if (applyBottomInnerClip) - graphicsContext->addInnerRoundedRectClip(IntRect(topX, bottomY, border.radii().bottomLeft().width() * 2, border.radii().bottomLeft().height() * 2), - style->borderLeftWidth()); - - secondAngleStart = 180; - secondAngleSpan = 45; - - // Draw bottom left arc - drawArcForBoxSide(graphicsContext, topX, bottomY, thickness, border.radii().bottomLeft(), secondAngleStart, secondAngleSpan, - BSLeft, leftColor, leftStyle, false); - } - } - } - - if (renderRight) { - bool ignoreTop = (renderRadii && border.radii().topRight().height() > 0) - || ((topColor == rightColor) && (topTransparent == rightTransparent) - && (rightStyle >= DOTTED || rightStyle == INSET) - && (topStyle == DOTTED || topStyle == DASHED || topStyle == SOLID || topStyle == OUTSET)); - - bool ignoreBottom = (renderRadii && border.radii().bottomRight().height() > 0) - || ((bottomColor == rightColor) && (bottomTransparent == rightTransparent) - && (rightStyle >= DOTTED || rightStyle == INSET) - && (bottomStyle == DOTTED || bottomStyle == DASHED || bottomStyle == SOLID || bottomStyle == INSET)); - - int y = rect.y(); - int y2 = rect.maxY(); - if (renderRadii) { - y += border.radii().topRight().height(); - y2 -= border.radii().bottomRight().height(); - } - - drawLineForBoxSide(graphicsContext, rect.maxX() - style->borderRightWidth(), y, rect.maxX(), y2, BSRight, rightColor, rightStyle, - ignoreTop ? 0 : style->borderTopWidth(), ignoreBottom ? 0 : style->borderBottomWidth()); - - if (renderRadii && (!upperRightBorderStylesMatch || !lowerRightBorderStylesMatch)) { - thickness = style->borderRightWidth() * 2; - - if (!upperRightBorderStylesMatch && border.radii().topRight().width()) { - int topX = rect.maxX() - border.radii().topRight().width() * 2; - int topY = rect.y(); - bool applyTopInnerClip = (style->borderRightWidth() < border.radii().topRight().width()) - && (style->borderTopWidth() < border.radii().topRight().height()) - && (rightStyle != DOUBLE || style->borderRightWidth() > 6); - - GraphicsContextStateSaver stateSaver(*graphicsContext, applyTopInnerClip); - if (applyTopInnerClip) - graphicsContext->addInnerRoundedRectClip(IntRect(topX, topY, border.radii().topRight().width() * 2, border.radii().topRight().height() * 2), - style->borderRightWidth()); - - firstAngleStart = 0; - firstAngleSpan = 45; - - // Draw top right arc - drawArcForBoxSide(graphicsContext, topX, topY, thickness, border.radii().topRight(), firstAngleStart, firstAngleSpan, - BSRight, rightColor, rightStyle, true); - } - - if (!lowerRightBorderStylesMatch && border.radii().bottomRight().width()) { - int bottomX = rect.maxX() - border.radii().bottomRight().width() * 2; - int bottomY = rect.maxY() - border.radii().bottomRight().height() * 2; - bool applyBottomInnerClip = (style->borderRightWidth() < border.radii().bottomRight().width()) - && (style->borderBottomWidth() < border.radii().bottomRight().height()) - && (rightStyle != DOUBLE || style->borderRightWidth() > 6); - - GraphicsContextStateSaver stateSaver(*graphicsContext, applyBottomInnerClip); - if (applyBottomInnerClip) - graphicsContext->addInnerRoundedRectClip(IntRect(bottomX, bottomY, border.radii().bottomRight().width() * 2, border.radii().bottomRight().height() * 2), - style->borderRightWidth()); - - secondAngleStart = 315; - secondAngleSpan = 45; - - // Draw bottom right arc - drawArcForBoxSide(graphicsContext, bottomX, bottomY, thickness, border.radii().bottomRight(), secondAngleStart, secondAngleSpan, - BSRight, rightColor, rightStyle, false); - } - } - } -} -#endif static void findInnerVertex(const FloatPoint& outerCorner, const FloatPoint& innerCorner, const FloatPoint& centerPoint, FloatPoint& result) { // If the line between outer and inner corner is towards the horizontal, intersect with a vertical line through the center, // otherwise with a horizontal line through the center. The points that form this line are arbitrary (we use 0, 100). // Note that if findIntersection fails, it will leave result untouched. - if (fabs(outerCorner.x() - innerCorner.x()) > fabs(outerCorner.y() - innerCorner.y())) + float diffInnerOuterX = fabs(innerCorner.x() - outerCorner.x()); + float diffInnerOuterY = fabs(innerCorner.y() - outerCorner.y()); + float diffCenterOuterX = fabs(centerPoint.x() - outerCorner.x()); + float diffCenterOuterY = fabs(centerPoint.y() - outerCorner.y()); + if (diffInnerOuterY * diffCenterOuterX < diffCenterOuterY * diffInnerOuterX) findIntersection(outerCorner, innerCorner, FloatPoint(centerPoint.x(), 0), FloatPoint(centerPoint.x(), 100), result); else findIntersection(outerCorner, innerCorner, FloatPoint(0, centerPoint.y()), FloatPoint(100, centerPoint.y()), result); @@ -2970,6 +2654,72 @@ void RenderBoxModelObject::setFirstLetterRemainingText(RenderObject* remainingTe firstLetterRemainingTextMap->remove(this); } +LayoutRect RenderBoxModelObject::localCaretRectForEmptyElement(LayoutUnit width, LayoutUnit textIndentOffset) +{ + ASSERT(!firstChild()); + + // FIXME: This does not take into account either :first-line or :first-letter + // However, as soon as some content is entered, the line boxes will be + // constructed and this kludge is not called any more. So only the caret size + // of an empty :first-line'd block is wrong. I think we can live with that. + RenderStyle* currentStyle = firstLineStyle(); + LayoutUnit height = lineHeight(true, currentStyle->isHorizontalWritingMode() ? HorizontalLine : VerticalLine); + + enum CaretAlignment { alignLeft, alignRight, alignCenter }; + + CaretAlignment alignment = alignLeft; + + switch (currentStyle->textAlign()) { + case LEFT: + case WEBKIT_LEFT: + break; + case CENTER: + case WEBKIT_CENTER: + alignment = alignCenter; + break; + case RIGHT: + case WEBKIT_RIGHT: + alignment = alignRight; + break; + case JUSTIFY: + case TASTART: + if (!currentStyle->isLeftToRightDirection()) + alignment = alignRight; + break; + case TAEND: + if (currentStyle->isLeftToRightDirection()) + alignment = alignRight; + break; + } + + LayoutUnit x = borderLeft() + paddingLeft(); + LayoutUnit maxX = width - borderRight() - paddingRight(); + + switch (alignment) { + case alignLeft: + if (currentStyle->isLeftToRightDirection()) + x += textIndentOffset; + break; + case alignCenter: + x = (x + maxX) / 2; + if (currentStyle->isLeftToRightDirection()) + x += textIndentOffset / 2; + else + x -= textIndentOffset / 2; + break; + case alignRight: + x = maxX - caretWidth; + if (!currentStyle->isLeftToRightDirection()) + x -= textIndentOffset; + break; + } + x = min(x, max(maxX - caretWidth, ZERO_LAYOUT_UNIT)); + + LayoutUnit y = paddingTop() + borderTop(); + + return LayoutRect(x, y, caretWidth, height); +} + bool RenderBoxModelObject::shouldAntialiasLines(GraphicsContext* context) { // FIXME: We may want to not antialias when scaled by an integral value, diff --git a/Source/WebCore/rendering/RenderBoxModelObject.h b/Source/WebCore/rendering/RenderBoxModelObject.h index 28a50ebdf..6c0bcca64 100644 --- a/Source/WebCore/rendering/RenderBoxModelObject.h +++ b/Source/WebCore/rendering/RenderBoxModelObject.h @@ -237,6 +237,8 @@ protected: RenderBoxModelObject* continuation() const; void setContinuation(RenderBoxModelObject*); + LayoutRect localCaretRectForEmptyElement(LayoutUnit width, LayoutUnit textIndentOffset); + static bool shouldAntialiasLines(GraphicsContext*); public: @@ -272,7 +274,9 @@ private: virtual bool isBoxModelObject() const { return true; } IntSize calculateFillTileSize(const FillLayer*, const IntSize& scaledPositioningAreaSize) const; - IntSize calculateImageIntrinsicDimensions(StyleImage*, const IntSize& scaledPositioningAreaSize) const; + + enum ScaleByEffectiveZoomOrNot { ScaleByEffectiveZoom, DoNotScaleByEffectiveZoom }; + IntSize calculateImageIntrinsicDimensions(StyleImage*, const IntSize& scaledPositioningAreaSize, ScaleByEffectiveZoomOrNot) const; RoundedRect getBackgroundRoundedRect(const LayoutRect&, InlineFlowBox*, LayoutUnit inlineBoxWidth, LayoutUnit inlineBoxHeight, bool includeLogicalLeftEdge, bool includeLogicalRightEdge); diff --git a/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp b/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp index d6165e092..a4c4b8910 100644 --- a/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp +++ b/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp @@ -543,7 +543,7 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren) if (allowedChildFlex(child, expanding, i)) { LayoutUnit spaceAdd = LayoutUnit(spaceAvailableThisPass * (child->style()->boxFlex() / totalFlex)); if (spaceAdd) { - child->setOverrideWidth(child->overrideWidth() + spaceAdd); + child->setOverrideLogicalContentWidth(child->overrideLogicalContentWidth() + spaceAdd); m_flexingChildren = true; relayoutChildren = true; } @@ -560,7 +560,7 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren) LayoutUnit spaceAdd = groupRemainingSpace > 0 ? 1 : -1; for (RenderBox* child = iterator.first(); child && groupRemainingSpace; child = iterator.next()) { if (allowedChildFlex(child, expanding, i)) { - child->setOverrideWidth(child->overrideWidth() + spaceAdd); + child->setOverrideLogicalContentWidth(child->overrideLogicalContentWidth() + spaceAdd); m_flexingChildren = true; relayoutChildren = true; remainingSpace -= spaceAdd; @@ -794,7 +794,7 @@ void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren) if (allowedChildFlex(child, expanding, i)) { LayoutUnit spaceAdd = static_cast<LayoutUnit>(spaceAvailableThisPass * (child->style()->boxFlex() / totalFlex)); if (spaceAdd) { - child->setOverrideHeight(child->overrideHeight() + spaceAdd); + child->setOverrideLogicalContentHeight(child->overrideLogicalContentHeight() + spaceAdd); m_flexingChildren = true; relayoutChildren = true; } @@ -811,7 +811,7 @@ void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren) LayoutUnit spaceAdd = groupRemainingSpace > 0 ? 1 : -1; for (RenderBox* child = iterator.first(); child && groupRemainingSpace; child = iterator.next()) { if (allowedChildFlex(child, expanding, i)) { - child->setOverrideHeight(child->overrideHeight() + spaceAdd); + child->setOverrideLogicalContentHeight(child->overrideLogicalContentHeight() + spaceAdd); m_flexingChildren = true; relayoutChildren = true; remainingSpace -= spaceAdd; @@ -925,7 +925,7 @@ void RenderDeprecatedFlexibleBox::applyLineClamp(FlexBoxIterator& iterator, bool continue; child->setChildNeedsLayout(true, MarkOnlyThis); - child->setOverrideHeight(newHeight); + child->setOverrideLogicalContentHeight(newHeight - child->borderAndPaddingHeight()); m_flexingChildren = true; child->layoutIfNeeded(); m_flexingChildren = false; @@ -1026,7 +1026,7 @@ LayoutUnit RenderDeprecatedFlexibleBox::allowedChildFlex(RenderBox* child, bool if (isHorizontal()) { // FIXME: For now just handle fixed values. LayoutUnit maxWidth = MAX_LAYOUT_UNIT; - LayoutUnit width = child->overrideWidth() - child->borderAndPaddingWidth(); + LayoutUnit width = child->overrideLogicalContentWidth(); if (!child->style()->maxWidth().isUndefined() && child->style()->maxWidth().isFixed()) maxWidth = child->style()->maxWidth().value(); else if (child->style()->maxWidth().type() == Intrinsic) @@ -1039,7 +1039,7 @@ LayoutUnit RenderDeprecatedFlexibleBox::allowedChildFlex(RenderBox* child, bool } else { // FIXME: For now just handle fixed values. LayoutUnit maxHeight = MAX_LAYOUT_UNIT; - LayoutUnit height = child->overrideHeight() - child->borderAndPaddingHeight(); + LayoutUnit height = child->overrideLogicalContentHeight(); if (!child->style()->maxHeight().isUndefined() && child->style()->maxHeight().isFixed()) maxHeight = child->style()->maxHeight().value(); if (maxHeight == MAX_LAYOUT_UNIT) @@ -1051,7 +1051,7 @@ LayoutUnit RenderDeprecatedFlexibleBox::allowedChildFlex(RenderBox* child, bool // FIXME: For now just handle fixed values. if (isHorizontal()) { LayoutUnit minWidth = child->minPreferredLogicalWidth(); - LayoutUnit width = child->overrideWidth() - child->borderAndPaddingWidth(); + LayoutUnit width = child->overrideLogicalContentWidth(); if (child->style()->minWidth().isFixed()) minWidth = child->style()->minWidth().value(); else if (child->style()->minWidth().type() == Intrinsic) @@ -1064,7 +1064,7 @@ LayoutUnit RenderDeprecatedFlexibleBox::allowedChildFlex(RenderBox* child, bool } else { if (child->style()->minHeight().isFixed()) { LayoutUnit minHeight = child->style()->minHeight().value(); - LayoutUnit height = child->overrideHeight() - child->borderAndPaddingHeight(); + LayoutUnit height = child->overrideLogicalContentHeight(); LayoutUnit allowedShrinkage = min<LayoutUnit>(0, minHeight - height); return allowedShrinkage; } diff --git a/Source/WebCore/rendering/RenderFieldset.cpp b/Source/WebCore/rendering/RenderFieldset.cpp index 8870a872f..3138f22fc 100644 --- a/Source/WebCore/rendering/RenderFieldset.cpp +++ b/Source/WebCore/rendering/RenderFieldset.cpp @@ -101,10 +101,24 @@ RenderObject* RenderFieldset::layoutSpecialExcludedChild(bool relayoutChildren) setLogicalLeftForChild(legend, logicalLeft); - LayoutUnit b = borderBefore(); - LayoutUnit h = logicalHeightForChild(legend); - setLogicalTopForChild(legend, max<LayoutUnit>((b - h) / 2, 0)); - setLogicalHeight(max(b, h) + paddingBefore()); + LayoutUnit fieldsetBorderBefore = borderBefore(); + LayoutUnit legendLogicalHeight = logicalHeightForChild(legend); + + LayoutUnit legendLogicalTop; + LayoutUnit collapsedLegendExtent; + // FIXME: We need to account for the legend's margin before too. + if (fieldsetBorderBefore > legendLogicalHeight) { + // The <legend> is smaller than the associated fieldset before border + // so the latter determines positioning of the <legend>. The sizing depends + // on the legend's margins as we want to still follow the author's cues. + // Firefox completely ignores the margins in this case which seems wrong. + legendLogicalTop = (fieldsetBorderBefore - legendLogicalHeight) / 2; + collapsedLegendExtent = max<LayoutUnit>(fieldsetBorderBefore, legendLogicalTop + legendLogicalHeight + marginAfterForChild(legend)); + } else + collapsedLegendExtent = legendLogicalHeight + marginAfterForChild(legend); + + setLogicalTopForChild(legend, legendLogicalTop); + setLogicalHeight(paddingBefore() + collapsedLegendExtent); } return legend; } diff --git a/Source/WebCore/rendering/RenderFileUploadControl.cpp b/Source/WebCore/rendering/RenderFileUploadControl.cpp index db4e6c5cd..3b880ccf1 100644 --- a/Source/WebCore/rendering/RenderFileUploadControl.cpp +++ b/Source/WebCore/rendering/RenderFileUploadControl.cpp @@ -109,8 +109,8 @@ void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, const LayoutPoin // Push a clip. GraphicsContextStateSaver stateSaver(*paintInfo.context, false); if (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseChildBlockBackgrounds) { - IntRect clipRect = pixelSnappedIntRect(paintOffset.x() + borderLeft(), paintOffset.y() + borderTop(), - width() - borderLeft() - borderRight(), height() - borderBottom() - borderTop() + buttonShadowHeight); + IntRect clipRect = enclosingIntRect(LayoutRect(paintOffset.x() + borderLeft(), paintOffset.y() + borderTop(), + width() - borderLeft() - borderRight(), height() - borderBottom() - borderTop() + buttonShadowHeight)); if (clipRect.isEmpty()) return; stateSaver.save(); diff --git a/Source/WebCore/rendering/RenderFlexibleBox.cpp b/Source/WebCore/rendering/RenderFlexibleBox.cpp index e62554062..8aba6d9a0 100644 --- a/Source/WebCore/rendering/RenderFlexibleBox.cpp +++ b/Source/WebCore/rendering/RenderFlexibleBox.cpp @@ -39,16 +39,6 @@ namespace WebCore { -// Normally, -1 and 0 are not valid in a HashSet, but these are relatively likely flex-order values. Instead, -// we make the two smallest int values invalid flex-order values (in the css parser code we clamp them to -// int min + 2). -struct RenderFlexibleBox::OrderHashTraits : WTF::GenericHashTraits<int> { - static const bool emptyValueIsZero = false; - static int emptyValue() { return std::numeric_limits<int>::min(); } - static void constructDeletedValue(int& slot) { slot = std::numeric_limits<int>::min() + 1; } - static bool isDeletedValue(int value) { return value == std::numeric_limits<int>::min() + 1; } -}; - class RenderFlexibleBox::OrderIterator { public: OrderIterator(RenderFlexibleBox* flexibleBox, const OrderHashSet& orderValues) @@ -99,8 +89,8 @@ public: private: RenderFlexibleBox* m_flexibleBox; RenderBox* m_currentChild; - Vector<int> m_orderValues; - Vector<int>::const_iterator m_orderValuesIterator; + Vector<float> m_orderValues; + Vector<float>::const_iterator m_orderValuesIterator; }; struct RenderFlexibleBox::LineContext { @@ -299,7 +289,7 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit) void RenderFlexibleBox::repositionLogicalHeightDependentFlexItems(OrderIterator& iterator, WTF::Vector<LineContext>& lineContexts, LayoutUnit& oldClientAfterEdge) { LayoutUnit crossAxisStartEdge = lineContexts.isEmpty() ? ZERO_LAYOUT_UNIT : lineContexts[0].crossAxisOffset; - packFlexLines(iterator, lineContexts); + alignFlexLines(iterator, lineContexts); // If we have a single line flexbox, the line height is all the available space. // For flex-direction: row, this means we need to use the height, so we do this after calling computeLogicalHeight. @@ -347,9 +337,9 @@ bool RenderFlexibleBox::isMultiline() const return style()->flexWrap() != FlexWrapNone; } -Length RenderFlexibleBox::preferredLengthForChild(RenderBox* child) const +Length RenderFlexibleBox::flexBasisForChild(RenderBox* child) const { - Length flexLength = child->style()->flexPreferredSize(); + Length flexLength = child->style()->flexBasis(); if (flexLength.isAuto()) flexLength = isHorizontalFlow() ? child->style()->width() : child->style()->height(); return flexLength; @@ -589,12 +579,12 @@ LayoutUnit RenderFlexibleBox::mainAxisScrollbarExtentForChild(RenderBox* child) LayoutUnit RenderFlexibleBox::preferredMainAxisContentExtentForChild(RenderBox* child) const { - Length mainAxisLength = preferredLengthForChild(child); - if (mainAxisLength.isAuto()) { + Length flexBasis = flexBasisForChild(child); + if (flexBasis.isAuto()) { LayoutUnit mainAxisExtent = hasOrthogonalFlow(child) ? child->logicalHeight() : child->maxPreferredLogicalWidth(); return mainAxisExtent - mainAxisBorderAndPaddingExtentForChild(child); } - return std::max(LayoutUnit(0), minimumValueForLength(mainAxisLength, mainAxisContentExtent(), view())); + return std::max(LayoutUnit(0), minimumValueForLength(flexBasis, mainAxisContentExtent(), view())); } LayoutUnit RenderFlexibleBox::computeAvailableFreeSpace(LayoutUnit preferredMainAxisExtent) @@ -603,7 +593,7 @@ LayoutUnit RenderFlexibleBox::computeAvailableFreeSpace(LayoutUnit preferredMain if (!isColumnFlow()) contentExtent = mainAxisContentExtent(); else if (hasOverrideHeight()) - contentExtent = overrideHeight() - (logicalHeight() - contentLogicalHeight()); + contentExtent = overrideLogicalContentHeight(); else { LayoutUnit heightResult = computeContentLogicalHeightUsing(style()->logicalHeight()); if (heightResult == -1) @@ -624,18 +614,18 @@ void RenderFlexibleBox::layoutFlexItems(OrderIterator& iterator, WTF::Vector<Lin { OrderedFlexItemList orderedChildren; LayoutUnit preferredMainAxisExtent; - float totalPositiveFlexibility; - float totalWeightedNegativeFlexibility; + float totalFlexGrow; + float totalWeightedFlexShrink; LayoutUnit minMaxAppliedMainAxisExtent; LayoutUnit crossAxisOffset = flowAwareBorderBefore() + flowAwarePaddingBefore(); - while (computeNextFlexLine(iterator, orderedChildren, preferredMainAxisExtent, totalPositiveFlexibility, totalWeightedNegativeFlexibility, minMaxAppliedMainAxisExtent)) { + while (computeNextFlexLine(iterator, orderedChildren, preferredMainAxisExtent, totalFlexGrow, totalWeightedFlexShrink, minMaxAppliedMainAxisExtent)) { LayoutUnit availableFreeSpace = computeAvailableFreeSpace(preferredMainAxisExtent); FlexSign flexSign = (minMaxAppliedMainAxisExtent < preferredMainAxisExtent + availableFreeSpace) ? PositiveFlexibility : NegativeFlexibility; InflexibleFlexItemSize inflexibleItems; WTF::Vector<LayoutUnit> childSizes; - while (!resolveFlexibleLengths(flexSign, orderedChildren, availableFreeSpace, totalPositiveFlexibility, totalWeightedNegativeFlexibility, inflexibleItems, childSizes)) { - ASSERT(totalPositiveFlexibility >= 0 && totalWeightedNegativeFlexibility >= 0); + while (!resolveFlexibleLengths(flexSign, orderedChildren, availableFreeSpace, totalFlexGrow, totalWeightedFlexShrink, inflexibleItems, childSizes)) { + ASSERT(totalFlexGrow >= 0 && totalWeightedFlexShrink >= 0); ASSERT(inflexibleItems.size() > 0); } @@ -758,7 +748,7 @@ void RenderFlexibleBox::computeMainAxisPreferredSizes(bool relayoutChildren, Ord child->clearOverrideSize(); // Only need to layout here if we will need to get the logicalHeight of the child in computeNextFlexLine. - if (hasOrthogonalFlow(child) && preferredLengthForChild(child).isAuto()) { + if (hasOrthogonalFlow(child) && flexBasisForChild(child).isAuto()) { if (!relayoutChildren) child->setChildNeedsLayout(true); child->layoutIfNeeded(); @@ -804,11 +794,11 @@ LayoutUnit RenderFlexibleBox::adjustChildSizeForMinAndMax(RenderBox* child, Layo return childSize; } -bool RenderFlexibleBox::computeNextFlexLine(OrderIterator& iterator, OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, float& totalPositiveFlexibility, float& totalWeightedNegativeFlexibility, LayoutUnit& minMaxAppliedMainAxisExtent) +bool RenderFlexibleBox::computeNextFlexLine(OrderIterator& iterator, OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, float& totalFlexGrow, float& totalWeightedFlexShrink, LayoutUnit& minMaxAppliedMainAxisExtent) { orderedChildren.clear(); preferredMainAxisExtent = 0; - totalPositiveFlexibility = totalWeightedNegativeFlexibility = 0; + totalFlexGrow = totalWeightedFlexShrink = 0; minMaxAppliedMainAxisExtent = 0; if (!iterator.currentChild()) @@ -831,8 +821,8 @@ bool RenderFlexibleBox::computeNextFlexLine(OrderIterator& iterator, OrderedFlex break; orderedChildren.append(child); preferredMainAxisExtent += childMainAxisMarginBoxExtent; - totalPositiveFlexibility += child->style()->positiveFlex(); - totalWeightedNegativeFlexibility += child->style()->negativeFlex() * childMainAxisExtent; + totalFlexGrow += child->style()->flexGrow(); + totalWeightedFlexShrink += child->style()->flexShrink() * childMainAxisExtent; LayoutUnit childMinMaxAppliedMainAxisExtent = adjustChildSizeForMinAndMax(child, childMainAxisExtent, flexboxAvailableContentExtent); minMaxAppliedMainAxisExtent += childMinMaxAppliedMainAxisExtent - childMainAxisExtent + childMainAxisMarginBoxExtent; @@ -840,21 +830,21 @@ bool RenderFlexibleBox::computeNextFlexLine(OrderIterator& iterator, OrderedFlex return true; } -void RenderFlexibleBox::freezeViolations(const WTF::Vector<Violation>& violations, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalWeightedNegativeFlexibility, InflexibleFlexItemSize& inflexibleItems) +void RenderFlexibleBox::freezeViolations(const WTF::Vector<Violation>& violations, LayoutUnit& availableFreeSpace, float& totalFlexGrow, float& totalWeightedFlexShrink, InflexibleFlexItemSize& inflexibleItems) { for (size_t i = 0; i < violations.size(); ++i) { RenderBox* child = violations[i].child; LayoutUnit childSize = violations[i].childSize; LayoutUnit preferredChildSize = preferredMainAxisContentExtentForChild(child); availableFreeSpace -= childSize - preferredChildSize; - totalPositiveFlexibility -= child->style()->positiveFlex(); - totalWeightedNegativeFlexibility -= child->style()->negativeFlex() * preferredChildSize; + totalFlexGrow -= child->style()->flexGrow(); + totalWeightedFlexShrink -= child->style()->flexShrink() * preferredChildSize; inflexibleItems.set(child, childSize); } } // Returns true if we successfully ran the algorithm and sized the flex items. -bool RenderFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedFlexItemList& children, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalWeightedNegativeFlexibility, InflexibleFlexItemSize& inflexibleItems, WTF::Vector<LayoutUnit>& childSizes) +bool RenderFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedFlexItemList& children, LayoutUnit& availableFreeSpace, float& totalFlexGrow, float& totalWeightedFlexShrink, InflexibleFlexItemSize& inflexibleItems, WTF::Vector<LayoutUnit>& childSizes) { childSizes.clear(); LayoutUnit flexboxAvailableContentExtent = mainAxisContentExtent(); @@ -874,10 +864,10 @@ bool RenderFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedF else { LayoutUnit preferredChildSize = preferredMainAxisContentExtentForChild(child); LayoutUnit childSize = preferredChildSize; - if (availableFreeSpace > 0 && totalPositiveFlexibility > 0 && flexSign == PositiveFlexibility && isfinite(totalPositiveFlexibility)) - childSize += lroundf(availableFreeSpace * child->style()->positiveFlex() / totalPositiveFlexibility); - else if (availableFreeSpace < 0 && totalWeightedNegativeFlexibility > 0 && flexSign == NegativeFlexibility && isfinite(totalWeightedNegativeFlexibility)) - childSize += lroundf(availableFreeSpace * child->style()->negativeFlex() * preferredChildSize / totalWeightedNegativeFlexibility); + if (availableFreeSpace > 0 && totalFlexGrow > 0 && flexSign == PositiveFlexibility && isfinite(totalFlexGrow)) + childSize += static_cast<int>(lroundf(availableFreeSpace * child->style()->flexGrow() / totalFlexGrow)); + else if (availableFreeSpace < 0 && totalWeightedFlexShrink > 0 && flexSign == NegativeFlexibility && isfinite(totalWeightedFlexShrink)) + childSize += static_cast<int>(lroundf(availableFreeSpace * child->style()->flexShrink() * preferredChildSize / totalWeightedFlexShrink)); LayoutUnit adjustedChildSize = adjustChildSizeForMinAndMax(child, childSize, flexboxAvailableContentExtent); childSizes.append(adjustedChildSize); @@ -893,20 +883,20 @@ bool RenderFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedF } if (totalViolation) - freezeViolations(totalViolation < 0 ? maxViolations : minViolations, availableFreeSpace, totalPositiveFlexibility, totalWeightedNegativeFlexibility, inflexibleItems); + freezeViolations(totalViolation < 0 ? maxViolations : minViolations, availableFreeSpace, totalFlexGrow, totalWeightedFlexShrink, inflexibleItems); else availableFreeSpace -= usedFreeSpace; return !totalViolation; } -static LayoutUnit initialPackingOffset(LayoutUnit availableFreeSpace, EFlexPack flexPack, unsigned numberOfChildren) +static LayoutUnit initialJustifyContentOffset(LayoutUnit availableFreeSpace, EJustifyContent justifyContent, unsigned numberOfChildren) { - if (flexPack == PackEnd) + if (justifyContent == JustifyFlexEnd) return availableFreeSpace; - if (flexPack == PackCenter) + if (justifyContent == JustifyCenter) return availableFreeSpace / 2; - if (flexPack == PackSpaceAround) { + if (justifyContent == JustifySpaceAround) { if (availableFreeSpace > 0 && numberOfChildren) return availableFreeSpace / (2 * numberOfChildren); if (availableFreeSpace < 0) @@ -915,12 +905,12 @@ static LayoutUnit initialPackingOffset(LayoutUnit availableFreeSpace, EFlexPack return 0; } -static LayoutUnit packingSpaceBetweenChildren(LayoutUnit availableFreeSpace, EFlexPack flexPack, unsigned numberOfChildren) +static LayoutUnit justifyContentSpaceBetweenChildren(LayoutUnit availableFreeSpace, EJustifyContent justifyContent, unsigned numberOfChildren) { if (availableFreeSpace > 0 && numberOfChildren > 1) { - if (flexPack == PackSpaceBetween) + if (justifyContent == JustifySpaceBetween) return availableFreeSpace / (numberOfChildren - 1); - if (flexPack == PackSpaceAround) + if (justifyContent == JustifySpaceAround) return availableFreeSpace / numberOfChildren; } return 0; @@ -928,11 +918,10 @@ static LayoutUnit packingSpaceBetweenChildren(LayoutUnit availableFreeSpace, EFl void RenderFlexibleBox::setLogicalOverrideSize(RenderBox* child, LayoutUnit childPreferredSize) { - // FIXME: Rename setOverrideWidth/setOverrideHeight to setOverrideLogicalWidth/setOverrideLogicalHeight. if (hasOrthogonalFlow(child)) - child->setOverrideHeight(childPreferredSize); + child->setOverrideLogicalContentHeight(childPreferredSize - child->borderAndPaddingLogicalHeight()); else - child->setOverrideWidth(childPreferredSize); + child->setOverrideLogicalContentWidth(childPreferredSize - child->borderAndPaddingLogicalWidth()); } void RenderFlexibleBox::prepareChildForPositionedLayout(RenderBox* child, LayoutUnit mainAxisOffset, LayoutUnit crossAxisOffset, PositionedLayoutMode layoutMode) @@ -960,10 +949,10 @@ static EAlignItems alignmentForChild(RenderBox* child) align = child->parent()->style()->alignItems(); if (child->parent()->style()->flexWrap() == FlexWrapReverse) { - if (align == AlignStart) - align = AlignEnd; - else if (align == AlignEnd) - align = AlignStart; + if (align == AlignFlexStart) + align = AlignFlexEnd; + else if (align == AlignFlexEnd) + align = AlignFlexStart; } return align; @@ -975,7 +964,7 @@ void RenderFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, cons LayoutUnit autoMarginOffset = autoMarginOffsetInMainAxis(children, availableFreeSpace); LayoutUnit mainAxisOffset = flowAwareBorderStart() + flowAwarePaddingStart(); - mainAxisOffset += initialPackingOffset(availableFreeSpace, style()->flexPack(), childSizes.size()); + mainAxisOffset += initialJustifyContentOffset(availableFreeSpace, style()->justifyContent(), childSizes.size()); if (style()->flexDirection() == FlowRowReverse) mainAxisOffset += isHorizontalFlow() ? verticalScrollbarWidth() : horizontalScrollbarHeight(); @@ -987,7 +976,7 @@ void RenderFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, cons RenderBox* child = children[i]; if (child->isPositioned()) { prepareChildForPositionedLayout(child, mainAxisOffset, crossAxisOffset, FlipForRowReverse); - mainAxisOffset += packingSpaceBetweenChildren(availableFreeSpace, style()->flexPack(), childSizes.size()); + mainAxisOffset += justifyContentSpaceBetweenChildren(availableFreeSpace, style()->justifyContent(), childSizes.size()); continue; } LayoutUnit childPreferredSize = childSizes[i] + mainAxisBorderAndPaddingExtentForChild(child); @@ -1023,7 +1012,7 @@ void RenderFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, cons setFlowAwareLocationForChild(child, childLocation); mainAxisOffset += childMainExtent + flowAwareMarginEndForChild(child); - mainAxisOffset += packingSpaceBetweenChildren(availableFreeSpace, style()->flexPack(), childSizes.size()); + mainAxisOffset += justifyContentSpaceBetweenChildren(availableFreeSpace, style()->justifyContent(), childSizes.size()); } if (isColumnFlow()) @@ -1046,14 +1035,14 @@ void RenderFlexibleBox::layoutColumnReverse(const OrderedFlexItemList& children, // starting from the end of the flexbox. We also don't need to layout anything since we're // just moving the children to a new position. LayoutUnit mainAxisOffset = logicalHeight() - flowAwareBorderEnd() - flowAwarePaddingEnd(); - mainAxisOffset -= initialPackingOffset(availableFreeSpace, style()->flexPack(), childSizes.size()); + mainAxisOffset -= initialJustifyContentOffset(availableFreeSpace, style()->justifyContent(), childSizes.size()); mainAxisOffset -= isHorizontalFlow() ? verticalScrollbarWidth() : horizontalScrollbarHeight(); for (size_t i = 0; i < children.size(); ++i) { RenderBox* child = children[i]; if (child->isPositioned()) { child->layer()->setStaticBlockPosition(mainAxisOffset); - mainAxisOffset -= packingSpaceBetweenChildren(availableFreeSpace, style()->flexPack(), childSizes.size()); + mainAxisOffset -= justifyContentSpaceBetweenChildren(availableFreeSpace, style()->justifyContent(), childSizes.size()); continue; } mainAxisOffset -= mainAxisExtentForChild(child) + flowAwareMarginEndForChild(child); @@ -1064,17 +1053,17 @@ void RenderFlexibleBox::layoutColumnReverse(const OrderedFlexItemList& children, child->repaintDuringLayoutIfMoved(oldRect); mainAxisOffset -= flowAwareMarginStartForChild(child); - mainAxisOffset -= packingSpaceBetweenChildren(availableFreeSpace, style()->flexPack(), childSizes.size()); + mainAxisOffset -= justifyContentSpaceBetweenChildren(availableFreeSpace, style()->justifyContent(), childSizes.size()); } } -static LayoutUnit initialLinePackingOffset(LayoutUnit availableFreeSpace, EFlexLinePack linePack, unsigned numberOfLines) +static LayoutUnit initialAlignContentOffset(LayoutUnit availableFreeSpace, EAlignContent alignContent, unsigned numberOfLines) { - if (linePack == LinePackEnd) + if (alignContent == AlignContentFlexEnd) return availableFreeSpace; - if (linePack == LinePackCenter) + if (alignContent == AlignContentCenter) return availableFreeSpace / 2; - if (linePack == LinePackSpaceAround) { + if (alignContent == AlignContentSpaceAround) { if (availableFreeSpace > 0 && numberOfLines) return availableFreeSpace / (2 * numberOfLines); if (availableFreeSpace < 0) @@ -1083,20 +1072,20 @@ static LayoutUnit initialLinePackingOffset(LayoutUnit availableFreeSpace, EFlexL return 0; } -static LayoutUnit linePackingSpaceBetweenChildren(LayoutUnit availableFreeSpace, EFlexLinePack linePack, unsigned numberOfLines) +static LayoutUnit alignContentSpaceBetweenChildren(LayoutUnit availableFreeSpace, EAlignContent alignContent, unsigned numberOfLines) { if (availableFreeSpace > 0 && numberOfLines > 1) { - if (linePack == LinePackSpaceBetween) + if (alignContent == AlignContentSpaceBetween) return availableFreeSpace / (numberOfLines - 1); - if (linePack == LinePackSpaceAround || linePack == LinePackStretch) + if (alignContent == AlignContentSpaceAround || alignContent == AlignContentStretch) return availableFreeSpace / numberOfLines; } return 0; } -void RenderFlexibleBox::packFlexLines(OrderIterator& iterator, WTF::Vector<LineContext>& lineContexts) +void RenderFlexibleBox::alignFlexLines(OrderIterator& iterator, WTF::Vector<LineContext>& lineContexts) { - if (!isMultiline() || style()->flexLinePack() == LinePackStart) + if (!isMultiline() || style()->alignContent() == AlignContentFlexStart) return; LayoutUnit availableCrossAxisSpace = crossAxisContentExtent(); @@ -1104,16 +1093,16 @@ void RenderFlexibleBox::packFlexLines(OrderIterator& iterator, WTF::Vector<LineC availableCrossAxisSpace -= lineContexts[i].crossAxisExtent; RenderBox* child = iterator.first(); - LayoutUnit lineOffset = initialLinePackingOffset(availableCrossAxisSpace, style()->flexLinePack(), lineContexts.size()); + LayoutUnit lineOffset = initialAlignContentOffset(availableCrossAxisSpace, style()->alignContent(), lineContexts.size()); for (unsigned lineNumber = 0; lineNumber < lineContexts.size(); ++lineNumber) { lineContexts[lineNumber].crossAxisOffset += lineOffset; for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = iterator.next()) adjustAlignmentForChild(child, lineOffset); - if (style()->flexLinePack() == LinePackStretch && availableCrossAxisSpace > 0) + if (style()->alignContent() == AlignContentStretch && availableCrossAxisSpace > 0) lineContexts[lineNumber].crossAxisExtent += availableCrossAxisSpace / static_cast<unsigned>(lineContexts.size()); - lineOffset += linePackingSpaceBetweenChildren(availableCrossAxisSpace, style()->flexLinePack(), lineContexts.size()); + lineOffset += alignContentSpaceBetweenChildren(availableCrossAxisSpace, style()->alignContent(), lineContexts.size()); } } @@ -1166,9 +1155,9 @@ void RenderFlexibleBox::alignChildren(OrderIterator& iterator, const WTF::Vector adjustAlignmentForChild(child, availableAlignmentSpaceForChild(lineCrossAxisExtent, child)); break; } - case AlignStart: + case AlignFlexStart: break; - case AlignEnd: + case AlignFlexEnd: adjustAlignmentForChild(child, availableAlignmentSpaceForChild(lineCrossAxisExtent, child)); break; case AlignCenter: @@ -1217,7 +1206,7 @@ void RenderFlexibleBox::applyStretchAlignmentToChild(RenderBox* child, LayoutUni // FIXME: Can avoid laying out here in some cases. See https://webkit.org/b/87905. if (child->logicalHeight() != logicalHeightBefore) { - child->setOverrideHeight(child->logicalHeight()); + child->setOverrideLogicalContentHeight(child->logicalHeight() - child->borderAndPaddingLogicalHeight()); child->setLogicalHeight(0); child->setChildNeedsLayout(true); child->layoutIfNeeded(); @@ -1225,7 +1214,7 @@ void RenderFlexibleBox::applyStretchAlignmentToChild(RenderBox* child, LayoutUni } else if (isColumnFlow() && child->style()->logicalWidth().isAuto() && isMultiline()) { // FIXME: Handle min-width and max-width. LayoutUnit childWidth = lineCrossAxisExtent - crossAxisMarginExtentForChild(child); - child->setOverrideWidth(std::max(ZERO_LAYOUT_UNIT, childWidth)); + child->setOverrideLogicalContentWidth(std::max(ZERO_LAYOUT_UNIT, childWidth)); child->setChildNeedsLayout(true); child->layoutIfNeeded(); } diff --git a/Source/WebCore/rendering/RenderFlexibleBox.h b/Source/WebCore/rendering/RenderFlexibleBox.h index fd469d328..64b1adbed 100644 --- a/Source/WebCore/rendering/RenderFlexibleBox.h +++ b/Source/WebCore/rendering/RenderFlexibleBox.h @@ -59,8 +59,7 @@ private: NoFlipForRowReverse, }; - struct OrderHashTraits; - typedef HashSet<int, DefaultHash<int>::Hash, OrderHashTraits> OrderHashSet; + typedef HashSet<float> OrderHashSet; class OrderIterator; typedef WTF::HashMap<const RenderBox*, LayoutUnit> InflexibleFlexItemSize; @@ -74,7 +73,7 @@ private: bool isLeftToRightFlow() const; bool isMultiline() const; Length crossAxisLength() const; - Length preferredLengthForChild(RenderBox* child) const; + Length flexBasisForChild(RenderBox* child) const; void setCrossAxisExtent(LayoutUnit); LayoutUnit crossAxisExtentForChild(RenderBox* child); LayoutUnit mainAxisExtentForChild(RenderBox* child); @@ -118,17 +117,17 @@ private: void computeMainAxisPreferredSizes(bool relayoutChildren, OrderHashSet&); LayoutUnit lineBreakLength(); LayoutUnit adjustChildSizeForMinAndMax(RenderBox*, LayoutUnit childSize, LayoutUnit flexboxAvailableContentExtent); - bool computeNextFlexLine(OrderIterator&, OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, float& totalPositiveFlexibility, float& totalWeightedNegativeFlexibility, LayoutUnit& minMaxAppliedMainAxisExtent); + bool computeNextFlexLine(OrderIterator&, OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, float& totalFlexGrow, float& totalWeightedFlexShrink, LayoutUnit& minMaxAppliedMainAxisExtent); LayoutUnit computeAvailableFreeSpace(LayoutUnit preferredMainAxisExtent); - bool resolveFlexibleLengths(FlexSign, const OrderedFlexItemList&, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalWeightedNegativeFlexibility, InflexibleFlexItemSize&, WTF::Vector<LayoutUnit>& childSizes); - void freezeViolations(const WTF::Vector<Violation>&, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalWeightedNegativeFlexibility, InflexibleFlexItemSize&); + bool resolveFlexibleLengths(FlexSign, const OrderedFlexItemList&, LayoutUnit& availableFreeSpace, float& totalFlexGrow, float& totalWeightedFlexShrink, InflexibleFlexItemSize&, WTF::Vector<LayoutUnit>& childSizes); + void freezeViolations(const WTF::Vector<Violation>&, LayoutUnit& availableFreeSpace, float& totalFlexGrow, float& totalWeightedFlexShrink, InflexibleFlexItemSize&); void setLogicalOverrideSize(RenderBox* child, LayoutUnit childPreferredSize); void prepareChildForPositionedLayout(RenderBox* child, LayoutUnit mainAxisOffset, LayoutUnit crossAxisOffset, PositionedLayoutMode); void layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, const OrderedFlexItemList&, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace, WTF::Vector<LineContext>&); void layoutColumnReverse(const OrderedFlexItemList&, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit crossAxisOffset, LayoutUnit availableFreeSpace); - void packFlexLines(OrderIterator&, WTF::Vector<LineContext>&); + void alignFlexLines(OrderIterator&, WTF::Vector<LineContext>&); void alignChildren(OrderIterator&, const WTF::Vector<LineContext>&); void applyStretchAlignmentToChild(RenderBox*, LayoutUnit lineCrossAxisExtent); void flipForRightToLeftColumn(OrderIterator&); diff --git a/Source/WebCore/rendering/RenderFlowThread.cpp b/Source/WebCore/rendering/RenderFlowThread.cpp index 507d3b395..fdc2e6bff 100644 --- a/Source/WebCore/rendering/RenderFlowThread.cpp +++ b/Source/WebCore/rendering/RenderFlowThread.cpp @@ -51,7 +51,7 @@ RenderFlowThread::RenderFlowThread(Node* node) , m_regionsInvalidated(false) , m_regionsHaveUniformLogicalWidth(true) , m_regionsHaveUniformLogicalHeight(true) - , m_overset(false) + , m_overset(true) , m_regionLayoutUpdateEventTimer(this, &RenderFlowThread::regionLayoutUpdateEventTimerFired) { ASSERT(node->document()->cssRegionsEnabled()); @@ -717,9 +717,10 @@ void RenderFlowThread::computeOverflowStateForRegions(LayoutUnit oldClientAfterE region->setDispatchRegionLayoutUpdateEvent(true); } - // With the regions overflow state computed we can also set the overflow for the named flow. + // With the regions overflow state computed we can also set the overset flag for the named flow. + // If there are no valid regions in the chain, overset is true RenderRegion* lastReg = lastRegion(); - m_overset = lastReg && (lastReg->regionState() == RenderRegion::RegionOverflow); + m_overset = lastReg ? lastReg->regionState() == RenderRegion::RegionOverflow : true; } void RenderFlowThread::regionLayoutUpdateEventTimerFired(Timer<RenderFlowThread>*) diff --git a/Source/WebCore/rendering/RenderImage.cpp b/Source/WebCore/rendering/RenderImage.cpp index 7049f8b50..093880e99 100644 --- a/Source/WebCore/rendering/RenderImage.cpp +++ b/Source/WebCore/rendering/RenderImage.cpp @@ -137,6 +137,12 @@ void RenderImage::styleDidChange(StyleDifference diff, const RenderStyle* oldSty imageDimensionsChanged(true /* imageSizeChanged */); m_needsToSetSizeForAltText = false; } +#if ENABLE(CSS_IMAGE_RESOLUTION) + if (diff == StyleDifferenceLayout + && (oldStyle->imageResolution() != style()->imageResolution() + || oldStyle->imageResolutionSource() != style()->imageResolutionSource())) + imageDimensionsChanged(true /* imageSizeChanged */); +#endif } void RenderImage::imageChanged(WrappedImagePtr newImage, const IntRect* rect) @@ -191,7 +197,11 @@ bool RenderImage::updateIntrinsicSizeIfNeeded(const IntSize& newSize, bool image void RenderImage::imageDimensionsChanged(bool imageSizeChanged, const IntRect* rect) { +#if ENABLE(CSS_IMAGE_RESOLUTION) + bool intrinsicSizeChanged = updateIntrinsicSizeIfNeeded(m_imageResource->imageSize(style()->effectiveZoom() / style()->imageResolution()), imageSizeChanged); +#else bool intrinsicSizeChanged = updateIntrinsicSizeIfNeeded(m_imageResource->imageSize(style()->effectiveZoom()), imageSizeChanged); +#endif // In the case of generated image content using :before/:after/content, we might not be // in the render tree yet. In that case, we just need to update our intrinsic size. diff --git a/Source/WebCore/rendering/RenderInline.cpp b/Source/WebCore/rendering/RenderInline.cpp index b45bdc338..0e0b45321 100644 --- a/Source/WebCore/rendering/RenderInline.cpp +++ b/Source/WebCore/rendering/RenderInline.cpp @@ -233,6 +233,30 @@ void RenderInline::updateAlwaysCreateLineBoxes(bool fullLayout) } } +LayoutRect RenderInline::localCaretRect(InlineBox* inlineBox, int, LayoutUnit* extraWidthToEndOfLine) +{ + if (firstChild()) { + // This condition is possible if the RenderInline is at an editing boundary, + // i.e. the VisiblePosition is: + // <RenderInline editingBoundary=true>|<RenderText> </RenderText></RenderInline> + // FIXME: need to figure out how to make this return a valid rect, note that + // there are no line boxes created in the above case. + return LayoutRect(); + } + + ASSERT_UNUSED(inlineBox, !inlineBox); + + if (extraWidthToEndOfLine) + *extraWidthToEndOfLine = 0; + + LayoutRect caretRect = localCaretRectForEmptyElement(borderAndPaddingWidth(), 0); + + if (InlineBox* firstBox = firstLineBox()) + caretRect.moveBy(roundedLayoutPoint(firstBox->topLeft())); + + return caretRect; +} + void RenderInline::addChild(RenderObject* newChild, RenderObject* beforeChild) { if (continuation()) diff --git a/Source/WebCore/rendering/RenderInline.h b/Source/WebCore/rendering/RenderInline.h index 4187f3187..a707a64df 100644 --- a/Source/WebCore/rendering/RenderInline.h +++ b/Source/WebCore/rendering/RenderInline.h @@ -84,6 +84,8 @@ public: void setAlwaysCreateLineBoxes() { m_alwaysCreateLineBoxes = true; } void updateAlwaysCreateLineBoxes(bool fullLayout); + virtual LayoutRect localCaretRect(InlineBox*, int, LayoutUnit* extraWidthToEndOfLine) OVERRIDE; + protected: virtual void willBeDestroyed(); diff --git a/Source/WebCore/rendering/RenderLayer.cpp b/Source/WebCore/rendering/RenderLayer.cpp index e0b56e7e5..94a837800 100644 --- a/Source/WebCore/rendering/RenderLayer.cpp +++ b/Source/WebCore/rendering/RenderLayer.cpp @@ -129,6 +129,9 @@ RenderLayer::RenderLayer(RenderBoxModelObject* renderer) : m_inResizeMode(false) , m_scrollDimensionsDirty(true) , m_normalFlowListDirty(true) + , m_hasSelfPaintingLayerDescendant(false) + , m_hasSelfPaintingLayerDescendantDirty(false) + , m_isRootLayer(renderer->isRenderView()) , m_usedTransparency(false) , m_paintingInsideReflection(false) , m_inOverflowRelayout(false) @@ -142,7 +145,7 @@ RenderLayer::RenderLayer(RenderBoxModelObject* renderer) , m_has3DTransformedDescendant(false) #if USE(ACCELERATED_COMPOSITING) , m_hasCompositingDescendant(false) - , m_mustOverlapCompositedLayers(false) + , m_indirectCompositingReason(NoIndirectCompositingReason) #endif , m_containsDirtyOverlayScrollbars(false) #if !ASSERT_DISABLED @@ -169,6 +172,8 @@ RenderLayer::RenderLayer(RenderBoxModelObject* renderer) , m_resizer(0) { m_isNormalFlowOnly = shouldBeNormalFlowOnly(); + m_isSelfPaintingLayer = shouldBeSelfPaintingLayer(); + // Non-stacking contexts should have empty z-order lists. As this is already the case, // there is no need to dirty / recompute these lists. m_zOrderListsDirty = isStackingContext(); @@ -360,7 +365,7 @@ void RenderLayer::updateLayerPositions(LayoutPoint* offsetFromRoot, UpdateLayerP } positionOverflowControls(toSize(roundedIntPoint(offset))); - updateVisibilityStatus(); + updateDescendantDependentFlags(); if (flags & UpdatePagination) updatePagination(); @@ -439,6 +444,30 @@ LayoutRect RenderLayer::repaintRectIncludingNonCompositingDescendants() const return repaintRect; } +void RenderLayer::setAncestorChainHasSelfPaintingLayerDescendant() +{ + for (RenderLayer* layer = this; layer; layer = layer->parent()) { + if (!layer->m_hasSelfPaintingLayerDescendantDirty && layer->hasSelfPaintingLayerDescendant()) + break; + + layer->m_hasSelfPaintingLayerDescendantDirty = false; + layer->m_hasSelfPaintingLayerDescendant = true; + } +} + +void RenderLayer::dirtyAncestorChainHasSelfPaintingLayerDescendantStatus() +{ + for (RenderLayer* layer = this; layer; layer = layer->parent()) { + layer->m_hasSelfPaintingLayerDescendantDirty = true; + // If we have reached a self-painting layer, we know our parent should have a self-painting descendant + // in this case, there is no need to dirty our ancestors further. + if (layer->isSelfPaintingLayer()) { + ASSERT(!parent() || parent()->m_hasSelfPaintingLayerDescendantDirty || parent()->hasSelfPaintingLayerDescendant()); + break; + } + } +} + void RenderLayer::computeRepaintRects(LayoutPoint* offsetFromRoot) { ASSERT(!m_visibleContentStatusDirty); @@ -461,7 +490,7 @@ void RenderLayer::updateLayerPositionsAfterScroll(UpdateLayerPositionsAfterScrol { // FIXME: This shouldn't be needed, but there are some corner cases where // these flags are still dirty. Update so that the check below is valid. - updateVisibilityStatus(); + updateDescendantDependentFlags(); // If we have no visible content and no visible descendants, there is no point recomputing // our rectangles as they will be empty. If our visibility changes, we are expected to @@ -603,68 +632,78 @@ void RenderLayer::updatePagination() } } -void RenderLayer::setHasVisibleContent(bool b) +void RenderLayer::setHasVisibleContent() { - if (m_hasVisibleContent == b && !m_visibleContentStatusDirty) + if (m_hasVisibleContent && !m_visibleContentStatusDirty) { + ASSERT(!parent() || parent()->hasVisibleDescendant()); return; + } + m_visibleContentStatusDirty = false; - m_hasVisibleContent = b; - if (m_hasVisibleContent) { - computeRepaintRects(); - if (!isNormalFlowOnly()) { - for (RenderLayer* sc = stackingContext(); sc; sc = sc->stackingContext()) { - sc->dirtyZOrderLists(); - if (sc->hasVisibleContent()) - break; - } + m_hasVisibleContent = true; + computeRepaintRects(); + if (!isNormalFlowOnly()) { + // We don't collect invisible layers in z-order lists if we are not in compositing mode. + // As we became visible, we need to dirty our stacking contexts ancestors to be properly + // collected. FIXME: When compositing, we could skip this dirtying phase. + for (RenderLayer* sc = stackingContext(); sc; sc = sc->stackingContext()) { + sc->dirtyZOrderLists(); + if (sc->hasVisibleContent()) + break; } } + if (parent()) - parent()->childVisibilityChanged(m_hasVisibleContent); + parent()->setAncestorChainHasVisibleDescendant(); } void RenderLayer::dirtyVisibleContentStatus() { m_visibleContentStatusDirty = true; if (parent()) - parent()->dirtyVisibleDescendantStatus(); + parent()->dirtyAncestorChainVisibleDescendantStatus(); } -void RenderLayer::childVisibilityChanged(bool newVisibility) -{ - if (m_hasVisibleDescendant == newVisibility || m_visibleDescendantStatusDirty) - return; - if (newVisibility) { - RenderLayer* l = this; - while (l && !l->m_visibleDescendantStatusDirty && !l->m_hasVisibleDescendant) { - l->m_hasVisibleDescendant = true; - l = l->parent(); - } - } else - dirtyVisibleDescendantStatus(); +void RenderLayer::dirtyAncestorChainVisibleDescendantStatus() +{ + for (RenderLayer* layer = this; layer; layer = layer->parent()) { + if (layer->m_visibleDescendantStatusDirty) + break; + + layer->m_visibleDescendantStatusDirty = true; + } } -void RenderLayer::dirtyVisibleDescendantStatus() +void RenderLayer::setAncestorChainHasVisibleDescendant() { - RenderLayer* l = this; - while (l && !l->m_visibleDescendantStatusDirty) { - l->m_visibleDescendantStatusDirty = true; - l = l->parent(); + for (RenderLayer* layer = this; layer; layer = layer->parent()) { + if (!layer->m_visibleDescendantStatusDirty && layer->hasVisibleDescendant()) + break; + + layer->m_hasVisibleDescendant = true; + layer->m_visibleDescendantStatusDirty = false; } } -void RenderLayer::updateVisibilityStatus() +void RenderLayer::updateDescendantDependentFlags() { - if (m_visibleDescendantStatusDirty) { + if (m_visibleDescendantStatusDirty || m_hasSelfPaintingLayerDescendantDirty) { m_hasVisibleDescendant = false; + m_hasSelfPaintingLayerDescendant = false; for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) { - child->updateVisibilityStatus(); - if (child->m_hasVisibleContent || child->m_hasVisibleDescendant) { - m_hasVisibleDescendant = true; + child->updateDescendantDependentFlags(); + + bool hasVisibleDescendant = child->m_hasVisibleContent || child->m_hasVisibleDescendant; + bool hasSelfPaintingLayerDescendant = child->isSelfPaintingLayer() || child->hasSelfPaintingLayerDescendant(); + + m_hasVisibleDescendant |= hasVisibleDescendant; + m_hasSelfPaintingLayerDescendant |= hasSelfPaintingLayerDescendant; + + if (m_hasVisibleDescendant && m_hasSelfPaintingLayerDescendant) break; - } } m_visibleDescendantStatusDirty = false; + m_hasSelfPaintingLayerDescendantDirty = false; } if (m_visibleContentStatusDirty) { @@ -863,21 +902,20 @@ FloatPoint RenderLayer::perspectiveOrigin() const RenderLayer* RenderLayer::stackingContext() const { RenderLayer* layer = parent(); - while (layer && !layer->renderer()->isRenderView() && !layer->renderer()->isRoot() && layer->renderer()->style()->hasAutoZIndex()) + while (layer && !layer->isRootLayer() && !layer->renderer()->isRoot() && layer->renderer()->style()->hasAutoZIndex()) layer = layer->parent(); return layer; } static inline bool isPositionedContainer(RenderLayer* layer) { - RenderObject* o = layer->renderer(); - return o->isRenderView() || o->isPositioned() || o->isRelPositioned() || layer->hasTransform(); + RenderBoxModelObject* layerRenderer = layer->renderer(); + return layer->isRootLayer() || layerRenderer->isPositioned() || layerRenderer->isRelPositioned() || layer->hasTransform(); } static inline bool isFixedPositionedContainer(RenderLayer* layer) { - RenderObject* o = layer->renderer(); - return o->isRenderView() || layer->hasTransform(); + return layer->isRootLayer() || layer->hasTransform(); } RenderLayer* RenderLayer::enclosingPositionedAncestor() const @@ -907,7 +945,7 @@ IntRect RenderLayer::scrollableAreaBoundingBox() const RenderLayer* RenderLayer::enclosingTransformedAncestor() const { RenderLayer* curr = parent(); - while (curr && !curr->renderer()->isRenderView() && !curr->transform()) + while (curr && !curr->isRootLayer() && !curr->transform()) curr = curr->parent(); return curr; @@ -1056,7 +1094,7 @@ RenderLayer* RenderLayer::clippingRootForPainting() const const RenderLayer* current = this; while (current) { - if (current->renderer()->isRenderView()) + if (current->isRootLayer()) return const_cast<RenderLayer*>(current); current = compositingContainer(current); @@ -1240,10 +1278,13 @@ void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild) child->dirtyStackingContextZOrderLists(); } - child->updateVisibilityStatus(); + child->updateDescendantDependentFlags(); if (child->m_hasVisibleContent || child->m_hasVisibleDescendant) - childVisibilityChanged(true); - + setAncestorChainHasVisibleDescendant(); + + if (child->isSelfPaintingLayer() || child->hasSelfPaintingLayerDescendant()) + setAncestorChainHasSelfPaintingLayerDescendant(); + #if USE(ACCELERATED_COMPOSITING) compositor()->layerWasAdded(this, child); #endif @@ -1280,10 +1321,13 @@ RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild) oldChild->setNextSibling(0); oldChild->setParent(0); - oldChild->updateVisibilityStatus(); + oldChild->updateDescendantDependentFlags(); if (oldChild->m_hasVisibleContent || oldChild->m_hasVisibleDescendant) - childVisibilityChanged(false); - + dirtyAncestorChainVisibleDescendantStatus(); + + if (oldChild->isSelfPaintingLayer() || oldChild->hasSelfPaintingLayerDescendant()) + dirtyAncestorChainHasSelfPaintingLayerDescendantStatus(); + return oldChild; } @@ -2849,7 +2893,7 @@ static inline bool shouldSuppressPaintingLayer(RenderLayer* layer) // Avoid painting descendants of the root layer when stylesheets haven't loaded. This eliminates FOUC. // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document // will do a full repaint(). - if (layer->renderer()->document()->didLayoutWithPendingStylesheets() && !layer->renderer()->isRenderView() && !layer->renderer()->isRoot()) + if (layer->renderer()->document()->didLayoutWithPendingStylesheets() && !layer->isRootLayer() && !layer->renderer()->isRoot()) return true; // Avoid painting all layers if the document is in a state where visual updates aren't allowed. @@ -2879,6 +2923,10 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* context, } #endif + // Non self-painting leaf layers don't need to be painted as their renderer() should properly paint itself. + if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant()) + return; + if (shouldSuppressPaintingLayer(this)) return; @@ -2886,10 +2934,6 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* context, if (!renderer()->opacity()) return; - // Non self-painting leaf layers don't need to be painted as their renderer() should properly paint itself. - if (!isSelfPaintingLayer() && !firstChild()) - return; - if (paintsWithTransparency(paintBehavior)) paintFlags |= PaintLayerHaveTransparency; @@ -2950,6 +2994,8 @@ void RenderLayer::paintLayerContentsAndReflection(RenderLayer* rootLayer, Graphi RenderObject* paintingRoot, RenderRegion* region, OverlapTestRequestMap* overlapTestRequests, PaintLayerFlags paintFlags) { + ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant()); + PaintLayerFlags localPaintFlags = paintFlags & ~(PaintLayerAppliedTransform); // Paint the reflection first if we have one. @@ -2969,6 +3015,8 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co RenderObject* paintingRoot, RenderRegion* region, OverlapTestRequestMap* overlapTestRequests, PaintLayerFlags paintFlags) { + ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant()); + PaintLayerFlags localPaintFlags = paintFlags & ~(PaintLayerAppliedTransform); bool haveTransparency = localPaintFlags & PaintLayerHaveTransparency; bool isSelfPaintingLayer = this->isSelfPaintingLayer(); @@ -3163,6 +3211,9 @@ void RenderLayer::paintList(Vector<RenderLayer*>* list, RenderLayer* rootLayer, if (!list) return; + if (!hasSelfPaintingLayerDescendant()) + return; + #if !ASSERT_DISABLED LayerListMutationDetector mutationChecker(this); #endif @@ -3220,12 +3271,12 @@ void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLaye ColumnInfo* colInfo = columnBlock->columnInfo(); unsigned colCount = columnBlock->columnCount(colInfo); - int currLogicalTopOffset = 0; + LayoutUnit currLogicalTopOffset = 0; for (unsigned i = 0; i < colCount; i++) { // For each rect, we clip to the rect, and then we adjust our coords. LayoutRect colRect = columnBlock->columnRectAt(colInfo, i); columnBlock->flipForWritingMode(colRect); - int logicalLeftOffset = (isHorizontal ? colRect.x() : colRect.y()) - columnBlock->logicalLeftOffsetForContent(); + LayoutUnit logicalLeftOffset = (isHorizontal ? colRect.x() : colRect.y()) - columnBlock->logicalLeftOffsetForContent(); LayoutSize offset; if (isHorizontal) { if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) @@ -3249,7 +3300,7 @@ void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLaye // Each strip pushes a clip, since column boxes are specified as being // like overflow:hidden. - context->clip(colRect); + context->clip(pixelSnappedIntRect(colRect)); if (!colIndex) { // Apply a translation transform to change where the layer paints. @@ -3258,7 +3309,7 @@ void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLaye if (oldHasTransform) oldTransform = *childLayer->transform(); TransformationMatrix newTransform(oldTransform); - newTransform.translateRight(offset.width(), offset.height()); + newTransform.translateRight(roundToInt(offset.width()), roundToInt(offset.height())); childLayer->m_transform = adoptPtr(new TransformationMatrix(newTransform)); childLayer->paintLayer(rootLayer, context, localDirtyRect, paintBehavior, paintingRoot, region, overlapTestRequests, paintFlags); @@ -3272,7 +3323,7 @@ void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLaye LayoutPoint childOffset; columnLayers[colIndex - 1]->convertToLayerCoords(rootLayer, childOffset); TransformationMatrix transform; - transform.translateRight(childOffset.x() + offset.width(), childOffset.y() + offset.height()); + transform.translateRight(roundToInt(childOffset.x() + offset.width()), roundToInt(childOffset.y() + offset.height())); // Apply the transform. context->concatCTM(transform.toAffineTransform()); @@ -3285,7 +3336,7 @@ void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLaye } // Move to the next position. - int blockDelta = isHorizontal ? colRect.height() : colRect.width(); + LayoutUnit blockDelta = isHorizontal ? colRect.height() : colRect.width(); if (columnBlock->style()->isFlippedBlocksWritingMode()) currLogicalTopOffset += blockDelta; else @@ -3315,7 +3366,7 @@ bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result) // We didn't hit any layer. If we are the root layer and the mouse is -- or just was -- down, // return ourselves. We do this so mouse events continue getting delivered after a drag has // exited the WebView, and so hit testing over a scrollbar hits the content document. - if ((request.active() || request.release()) && renderer()->isRenderView()) { + if ((request.active() || request.release()) && isRootLayer()) { renderer()->updateHitTestResult(result, result.point()); insideLayer = this; } @@ -3794,7 +3845,6 @@ void RenderLayer::updateClipRects(const RenderLayer* rootLayer, RenderRegion* re else m_clipRectsCache->m_clipRects[clipRectsType] = ClipRects::create(clipRects); - m_clipRectsCache->m_clipRects[clipRectsType]->ref(); #ifndef NDEBUG m_clipRectsCache->m_clipRectsRoot[clipRectsType] = rootLayer; #endif @@ -3901,7 +3951,7 @@ ClipRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, RenderReg // Note: infinite clipRects should not be scrolled here, otherwise they will accidentally no longer be considered infinite. if (parentRects.fixed() && rootLayer->renderer() == view && backgroundClipRect != PaintInfo::infiniteRect()) - backgroundClipRect.move(view->frameView()->scrollXForFixedPosition(), view->frameView()->scrollYForFixedPosition()); + backgroundClipRect.move(view->frameView()->scrollOffsetForFixedPosition()); return backgroundClipRect; } @@ -4037,7 +4087,7 @@ bool RenderLayer::intersectsDamageRect(const LayoutRect& layerBounds, const Layo // Always examine the canvas and the root. // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView // paints the root's background. - if (renderer()->isRenderView() || renderer()->isRoot()) + if (isRootLayer() || renderer()->isRoot()) return true; // If we aren't an inline flow, and our layer bounds do intersect the damage rect, then we @@ -4537,7 +4587,7 @@ void RenderLayer::updateNormalFlowList() void RenderLayer::collectLayers(bool includeHiddenLayers, Vector<RenderLayer*>*& posBuffer, Vector<RenderLayer*>*& negBuffer) { - updateVisibilityStatus(); + updateDescendantDependentFlags(); // Overflow layers are just painted by their enclosing layers, so they don't get put in zorder lists. bool includeHiddenLayer = includeHiddenLayers || (m_hasVisibleContent || (m_hasVisibleDescendant && isStackingContext())); @@ -4660,7 +4710,7 @@ bool RenderLayer::shouldBeNormalFlowOnly() const && !isTransparent(); } -bool RenderLayer::isSelfPaintingLayer() const +bool RenderLayer::shouldBeSelfPaintingLayer() const { return !isNormalFlowOnly() || renderer()->hasReflection() @@ -4673,6 +4723,21 @@ bool RenderLayer::isSelfPaintingLayer() const || renderer()->isRenderIFrame(); } +void RenderLayer::updateSelfPaintingLayerAfterStyleChange(const RenderStyle*) +{ + bool isSelfPaintingLayer = shouldBeSelfPaintingLayer(); + if (m_isSelfPaintingLayer == isSelfPaintingLayer) + return; + + m_isSelfPaintingLayer = isSelfPaintingLayer; + if (!parent()) + return; + if (isSelfPaintingLayer) + parent()->setAncestorChainHasSelfPaintingLayerDescendant(); + else + parent()->dirtyAncestorChainHasSelfPaintingLayerDescendantStatus(); +} + void RenderLayer::updateStackingContextsAfterStyleChange(const RenderStyle* oldStyle) { if (!oldStyle) @@ -4753,6 +4818,7 @@ void RenderLayer::styleChanged(StyleDifference, const RenderStyle* oldStyle) m_marquee = 0; } + updateSelfPaintingLayerAfterStyleChange(oldStyle); updateStackingContextsAfterStyleChange(oldStyle); updateScrollbarsAfterStyleChange(oldStyle); @@ -4778,7 +4844,7 @@ void RenderLayer::styleChanged(StyleDifference, const RenderStyle* oldStyle) #endif #if USE(ACCELERATED_COMPOSITING) - updateVisibilityStatus(); + updateDescendantDependentFlags(); updateTransform(); if (compositor()->updateLayerCompositingState(this)) diff --git a/Source/WebCore/rendering/RenderLayer.h b/Source/WebCore/rendering/RenderLayer.h index ad23af708..28d7e5627 100644 --- a/Source/WebCore/rendering/RenderLayer.h +++ b/Source/WebCore/rendering/RenderLayer.h @@ -111,6 +111,7 @@ public: m_hasRadius = true; } void move(LayoutUnit x, LayoutUnit y) { m_rect.move(x, y); } + void move(const LayoutSize& size) { m_rect.move(size); } bool isEmpty() const { return m_rect.isEmpty(); } bool intersects(const LayoutRect& rect) { return m_rect.intersects(rect); } @@ -140,7 +141,7 @@ public: } ClipRects() - : m_refCnt(0) + : m_refCnt(1) , m_fixed(false) { } @@ -194,7 +195,7 @@ private: : m_overflowClipRect(r) , m_fixedClipRect(r) , m_posClipRect(r) - , m_refCnt(0) + , m_refCnt(1) , m_fixed(false) { } @@ -203,7 +204,7 @@ private: : m_overflowClipRect(other.overflowClipRect()) , m_fixedClipRect(other.fixedClipRect()) , m_posClipRect(other.posClipRect()) - , m_refCnt(0) + , m_refCnt(1) , m_fixed(other.fixed()) { } @@ -275,7 +276,7 @@ public: RenderMarquee* marquee() const { return m_marquee; } bool isNormalFlowOnly() const { return m_isNormalFlowOnly; } - bool isSelfPaintingLayer() const; + bool isSelfPaintingLayer() const { return m_isSelfPaintingLayer; } bool cannotBlitToWindow() const; @@ -367,8 +368,8 @@ public: bool inResizeMode() const { return m_inResizeMode; } void setInResizeMode(bool b) { m_inResizeMode = b; } - bool isRootLayer() const { return renderer()->isRenderView(); } - + bool isRootLayer() const { return m_isRootLayer; } + #if USE(ACCELERATED_COMPOSITING) RenderLayerCompositor* compositor() const; @@ -392,6 +393,8 @@ public: // Providing |cachedOffset| prevents a outlineBoxForRepaint from walking back to the root for each layer in our subtree. // This is an optimistic optimization that is not guaranteed to succeed. void updateLayerPositions(LayoutPoint* offsetFromRoot, UpdateLayerPositionsFlags = defaultFlags); + + bool isPaginated() const { return m_isPaginated; } void updateTransform(); @@ -438,9 +441,14 @@ public: // ditto for hasVisibleDescendant(), see https://bugs.webkit.org/show_bug.cgi?id=71277 bool hasVisibleContent() const { return m_hasVisibleContent; } bool hasVisibleDescendant() const { return m_hasVisibleDescendant; } - void setHasVisibleContent(bool); + + void setHasVisibleContent(); void dirtyVisibleContentStatus(); + // FIXME: We should ASSERT(!m_hasSelfPaintingLayerDescendantDirty); here but we hit the same bugs as visible content above. + // Part of the issue is with subtree relayout: we don't check if our ancestors have some descendant flags dirty, missing some updates. + bool hasSelfPaintingLayerDescendant() const { return m_hasSelfPaintingLayerDescendant; } + // Gets the nearest enclosing positioned ancestor layer (also includes // the <html> layer and the root layer). RenderLayer* enclosingPositionedAncestor() const; @@ -645,9 +653,12 @@ private: void updateNormalFlowList(); - bool isStackingContext(const RenderStyle* style) const { return !style->hasAutoZIndex() || renderer()->isRenderView(); } + bool isStackingContext(const RenderStyle* style) const { return !style->hasAutoZIndex() || isRootLayer(); } bool isDirtyStackingContext() const { return m_zOrderListsDirty && isStackingContext(); } + void setAncestorChainHasSelfPaintingLayerDescendant(); + void dirtyAncestorChainHasSelfPaintingLayerDescendantStatus(); + void computeRepaintRects(LayoutPoint* offsetFromRoot = 0); void clearRepaintRects(); @@ -657,6 +668,7 @@ private: bool shouldRepaintAfterLayout() const; + void updateSelfPaintingLayerAfterStyleChange(const RenderStyle* oldStyle); void updateStackingContextsAfterStyleChange(const RenderStyle* oldStyle); void updateScrollbarsAfterStyleChange(const RenderStyle* oldStyle); @@ -729,7 +741,9 @@ private: bool hasHorizontalOverflow() const; bool hasVerticalOverflow() const; - bool shouldBeNormalFlowOnly() const; + bool shouldBeNormalFlowOnly() const; + + bool shouldBeSelfPaintingLayer() const; int scrollPosition(Scrollbar*) const; @@ -769,9 +783,10 @@ private: void updateScrollableAreaSet(bool hasOverflow); - void childVisibilityChanged(bool newVisibility); - void dirtyVisibleDescendantStatus(); - void updateVisibilityStatus(); + void dirtyAncestorChainVisibleDescendantStatus(); + void setAncestorChainHasVisibleDescendant(); + + void updateDescendantDependentFlags(); // This flag is computed by RenderLayerCompositor, which knows more about 3d hierarchies than we do. void setHas3DTransformedDescendant(bool b) { m_has3DTransformedDescendant = b; } @@ -810,14 +825,23 @@ private: void drawPlatformResizerImage(GraphicsContext*, IntRect resizerCornerRect); void updatePagination(); - bool isPaginated() const { return m_isPaginated; } - + #if USE(ACCELERATED_COMPOSITING) bool hasCompositingDescendant() const { return m_hasCompositingDescendant; } void setHasCompositingDescendant(bool b) { m_hasCompositingDescendant = b; } - bool mustOverlapCompositedLayers() const { return m_mustOverlapCompositedLayers; } - void setMustOverlapCompositedLayers(bool b) { m_mustOverlapCompositedLayers = b; } + enum IndirectCompositingReason { + NoIndirectCompositingReason, + IndirectCompositingForOverlap, + IndirectCompositingForBackgroundLayer, + IndirectCompositingForGraphicalEffect, // opacity, mask, filter, transform etc. + IndirectCompositingForPerspective, + IndirectCompositingForPreserve3D + }; + + void setIndirectCompositingReason(IndirectCompositingReason reason) { m_indirectCompositingReason = reason; } + IndirectCompositingReason indirectCompositingReason() const { return static_cast<IndirectCompositingReason>(m_indirectCompositingReason); } + bool mustCompositeForIndirectReasons() const { return m_indirectCompositingReason; } #endif friend class RenderLayerBacking; @@ -856,6 +880,15 @@ protected: bool m_normalFlowListDirty: 1; bool m_isNormalFlowOnly : 1; + bool m_isSelfPaintingLayer : 1; + + // If have no self-painting descendants, we don't have to walk our children during painting. This can lead to + // significant savings, especially if the tree has lots of non-self-painting layers grouped together (e.g. table cells). + bool m_hasSelfPaintingLayerDescendant : 1; + bool m_hasSelfPaintingLayerDescendantDirty : 1; + + const bool m_isRootLayer : 1; + bool m_usedTransparency : 1; // Tracks whether we need to close a transparent layer, i.e., whether // we ended up painting this layer or any descendants (and therefore need to // blend). @@ -875,7 +908,7 @@ protected: // in a preserves3D hierarchy. Hint to do 3D-aware hit testing. #if USE(ACCELERATED_COMPOSITING) bool m_hasCompositingDescendant : 1; // In the z-order tree. - bool m_mustOverlapCompositedLayers : 1; + unsigned m_indirectCompositingReason : 3; #endif bool m_containsDirtyOverlayScrollbars : 1; @@ -885,7 +918,7 @@ protected: // This is an optimization added for <table>. // Currently cells do not need to update their repaint rectangles when scrolling. This also // saves a lot of time when scrolling on a table. - bool m_canSkipRepaintRectsUpdateOnScroll : 1; + const bool m_canSkipRepaintRectsUpdateOnScroll : 1; #if ENABLE(CSS_FILTERS) bool m_hasFilterInfo : 1; diff --git a/Source/WebCore/rendering/RenderLayerBacking.cpp b/Source/WebCore/rendering/RenderLayerBacking.cpp index adce4c7ee..f9a818a15 100644 --- a/Source/WebCore/rendering/RenderLayerBacking.cpp +++ b/Source/WebCore/rendering/RenderLayerBacking.cpp @@ -51,6 +51,7 @@ #include "RenderEmbeddedObject.h" #include "RenderVideo.h" #include "RenderView.h" +#include "ScrollingCoordinator.h" #include "StyleResolver.h" #include "TiledBacking.h" @@ -165,7 +166,11 @@ void RenderLayerBacking::createPrimaryGraphicsLayer() m_graphicsLayer = createGraphicsLayer(layerName); if (m_isMainFrameRenderViewLayer) { - m_graphicsLayer->setContentsOpaque(true); + bool isTransparent = false; + if (FrameView* frameView = toRenderView(renderer())->frameView()) + isTransparent = frameView->isTransparent(); + + m_graphicsLayer->setContentsOpaque(!isTransparent); m_graphicsLayer->setAppliesPageScale(); } @@ -239,6 +244,10 @@ static bool layerOrAncestorIsTransformed(RenderLayer* layer) bool RenderLayerBacking::shouldClipCompositedBounds() const { + // Scrollbar layers use this layer for relative positioning, so don't clip. + if (layerForHorizontalScrollbar() || layerForVerticalScrollbar()) + return false; + if (m_usingTiledCacheLayer) return true; @@ -423,7 +432,7 @@ void RenderLayerBacking::updateGraphicsLayerGeometry() updateLayerFilters(renderer()->style()); #endif - m_owningLayer->updateVisibilityStatus(); + m_owningLayer->updateDescendantDependentFlags(); // m_graphicsLayer is the corresponding GraphicsLayer for this RenderLayer and its non-compositing // descendants. So, the visibility flag for m_graphicsLayer should be true if there are any @@ -434,6 +443,20 @@ void RenderLayerBacking::updateGraphicsLayerGeometry() m_graphicsLayer->setPreserves3D(style->transformStyle3D() == TransformStyle3DPreserve3D && !renderer()->hasReflection()); m_graphicsLayer->setBackfaceVisibility(style->backfaceVisibility() == BackfaceVisibilityVisible); + // Register fixed position layers and their containers with the scrolling coordinator. + if (Page* page = renderer()->frame()->page()) { + if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) { + if (style->position() == FixedPosition || compositor()->fixedPositionedByAncestor(m_owningLayer)) + scrollingCoordinator->setLayerIsFixedToContainerLayer(childForSuperlayers(), true); + else { + if (m_ancestorClippingLayer) + scrollingCoordinator->setLayerIsFixedToContainerLayer(m_ancestorClippingLayer.get(), false); + scrollingCoordinator->setLayerIsFixedToContainerLayer(m_graphicsLayer.get(), false); + } + bool isContainer = m_owningLayer->hasTransform(); + scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(childForSuperlayers(), isContainer); + } + } RenderLayer* compAncestor = m_owningLayer->ancestorCompositingLayer(); // We compute everything relative to the enclosing compositing layer. @@ -591,22 +614,22 @@ void RenderLayerBacking::updateInternalHierarchy() if (m_clippingLayer) { m_clippingLayer->removeFromParent(); m_graphicsLayer->addChild(m_clippingLayer.get()); + } - // The clip for child layers does not include space for overflow controls, so they exist as - // siblings of the clipping layer if we have one. Normal children of this layer are set as - // children of the clipping layer. - if (m_layerForHorizontalScrollbar) { - m_layerForHorizontalScrollbar->removeFromParent(); - m_graphicsLayer->addChild(m_layerForHorizontalScrollbar.get()); - } - if (m_layerForVerticalScrollbar) { - m_layerForVerticalScrollbar->removeFromParent(); - m_graphicsLayer->addChild(m_layerForVerticalScrollbar.get()); - } - if (m_layerForScrollCorner) { - m_layerForScrollCorner->removeFromParent(); - m_graphicsLayer->addChild(m_layerForScrollCorner.get()); - } + // The clip for child layers does not include space for overflow controls, so they exist as + // siblings of the clipping layer if we have one. Normal children of this layer are set as + // children of the clipping layer. + if (m_layerForHorizontalScrollbar) { + m_layerForHorizontalScrollbar->removeFromParent(); + m_graphicsLayer->addChild(m_layerForHorizontalScrollbar.get()); + } + if (m_layerForVerticalScrollbar) { + m_layerForVerticalScrollbar->removeFromParent(); + m_graphicsLayer->addChild(m_layerForVerticalScrollbar.get()); + } + if (m_layerForScrollCorner) { + m_layerForScrollCorner->removeFromParent(); + m_graphicsLayer->addChild(m_layerForScrollCorner.get()); } } @@ -1564,4 +1587,3 @@ double RenderLayerBacking::backingStoreArea() const } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING) - diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp index c20db84e8..1466e39ba 100644 --- a/Source/WebCore/rendering/RenderLayerCompositor.cpp +++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp @@ -401,11 +401,12 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update // FIXME: we could maybe do this and the hierarchy udpate in one pass, but the parenting logic would be more complex. CompositingState compState(updateRoot, m_compositingConsultsOverlap); bool layersChanged = false; + bool saw3DTransform = false; if (m_compositingConsultsOverlap) { OverlapMap overlapTestRequestMap; - computeCompositingRequirements(0, updateRoot, &overlapTestRequestMap, compState, layersChanged); + computeCompositingRequirements(0, updateRoot, &overlapTestRequestMap, compState, layersChanged, saw3DTransform); } else - computeCompositingRequirements(0, updateRoot, 0, compState, layersChanged); + computeCompositingRequirements(0, updateRoot, 0, compState, layersChanged, saw3DTransform); needHierarchyUpdate |= layersChanged; } @@ -546,6 +547,11 @@ bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeR if (layerChanged) layer->clearClipRectsIncludingDescendants(PaintingClipRects); + // If a fixed position layer gained/lost a backing, the scrolling coordinator needs to recalculate whether it can do fast scrolling. + if (layerChanged && layer->renderer()->style()->position() == FixedPosition) { + if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) + scrollingCoordinator->frameViewFixedObjectsDidChange(m_renderView->frameView()); + } return layerChanged; } @@ -716,7 +722,7 @@ void RenderLayerCompositor::addToOverlapMapRecursive(OverlapMap& overlapMap, Ren // must be compositing so that its contents render over that child. // This implies that its positive z-index children must also be compositing. // -void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestorLayer, RenderLayer* layer, OverlapMap* overlapMap, CompositingState& compositingState, bool& layersChanged) +void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestorLayer, RenderLayer* layer, OverlapMap* overlapMap, CompositingState& compositingState, bool& layersChanged, bool& descendantHas3DTransform) { layer->updateLayerListsIfNeeded(); @@ -741,7 +747,7 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor mustOverlapCompositedLayers = overlapMap->overlapsLayers(absBounds); } - layer->setMustOverlapCompositedLayers(mustOverlapCompositedLayers); + layer->setIndirectCompositingReason(mustOverlapCompositedLayers ? RenderLayer::IndirectCompositingForOverlap : RenderLayer::NoIndirectCompositingReason); // The children of this layer don't need to composite, unless there is // a compositing layer among them, so start by inheriting the compositing @@ -777,18 +783,20 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor LayerListMutationDetector mutationChecker(layer); #endif + bool anyDescendantHas3DTransform = false; + if (layer->isStackingContext()) { if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) { size_t listSize = negZOrderList->size(); for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = negZOrderList->at(i); - computeCompositingRequirements(layer, curLayer, overlapMap, childState, layersChanged); + computeCompositingRequirements(layer, curLayer, overlapMap, childState, layersChanged, anyDescendantHas3DTransform); // If we have to make a layer for this child, make one now so we can have a contents layer // (since we need to ensure that the -ve z-order child renders underneath our contents). if (!willBeComposited && childState.m_subtreeIsCompositing) { // make layer compositing - layer->setMustOverlapCompositedLayers(true); + layer->setIndirectCompositingReason(RenderLayer::IndirectCompositingForBackgroundLayer); childState.m_compositingAncestor = layer; if (overlapMap) overlapMap->pushCompositingContainer(); @@ -802,7 +810,7 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor size_t listSize = normalFlowList->size(); for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = normalFlowList->at(i); - computeCompositingRequirements(layer, curLayer, overlapMap, childState, layersChanged); + computeCompositingRequirements(layer, curLayer, overlapMap, childState, layersChanged, anyDescendantHas3DTransform); } } @@ -811,7 +819,7 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor size_t listSize = posZOrderList->size(); for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = posZOrderList->at(i); - computeCompositingRequirements(layer, curLayer, overlapMap, childState, layersChanged); + computeCompositingRequirements(layer, curLayer, overlapMap, childState, layersChanged, anyDescendantHas3DTransform); } } } @@ -830,11 +838,11 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor if (overlapMap && childState.m_compositingAncestor && !childState.m_compositingAncestor->isRootLayer()) addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds); - // 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 (!willBeComposited && canBeComposited(layer) && childState.m_subtreeIsCompositing && requiresCompositingWhenDescendantsAreCompositing(layer->renderer())) { - layer->setMustOverlapCompositedLayers(true); + // Now check for reasons to become composited that depend on the state of descendant layers. + RenderLayer::IndirectCompositingReason indirectCompositingReason; + if (!willBeComposited && canBeComposited(layer) + && requiresCompositingForIndirectReason(layer->renderer(), childState.m_subtreeIsCompositing, anyDescendantHas3DTransform, indirectCompositingReason)) { + layer->setIndirectCompositingReason(indirectCompositingReason); childState.m_compositingAncestor = layer; if (overlapMap) { overlapMap->pushCompositingContainer(); @@ -842,11 +850,11 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor } willBeComposited = true; } - + ASSERT(willBeComposited == needsToBeComposited(layer)); if (layer->reflectionLayer()) { // FIXME: Shouldn't we call computeCompositingRequirements to handle a reflection overlapping with another renderer? - layer->reflectionLayer()->setMustOverlapCompositedLayers(willBeComposited); + layer->reflectionLayer()->setIndirectCompositingReason(willBeComposited ? RenderLayer::IndirectCompositingForOverlap : RenderLayer::NoIndirectCompositingReason); } // Subsequent layers in the parent stacking context also need to composite. @@ -899,6 +907,8 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor if (layer->reflectionLayer() && updateLayerCompositingState(layer->reflectionLayer(), CompositingChangeRepaintNow)) layersChanged = true; + descendantHas3DTransform |= anyDescendantHas3DTransform || layer->has3DTransform(); + if (overlapMap) overlapMap->geometryMap().popMappingsToAncestor(ancestorLayer ? ancestorLayer->renderer() : 0); } @@ -1417,7 +1427,7 @@ bool RenderLayerCompositor::needsToBeComposited(const RenderLayer* layer) const if (!canBeComposited(layer)) return false; - return requiresCompositingLayer(layer) || layer->mustOverlapCompositedLayers() || (inCompositingMode() && layer->isRootLayer()); + return requiresCompositingLayer(layer) || layer->mustCompositeForIndirectReasons() || (inCompositingMode() && layer->isRootLayer()); } // Note: this specifies whether the RL needs a compositing layer for intrinsic reasons. @@ -1460,7 +1470,7 @@ bool RenderLayerCompositor::requiresOwnBackingStore(const RenderLayer* layer, co || compositingAncestorLayer->backing()->paintsIntoCompositedAncestor())) return true; - return layer->isRootLayer() + if (layer->isRootLayer() || layer->transform() // note: excludes perspective and transformStyle3D. || requiresCompositingForVideo(renderer) || requiresCompositingForCanvas(renderer) @@ -1473,8 +1483,18 @@ bool RenderLayerCompositor::requiresOwnBackingStore(const RenderLayer* layer, co || renderer->isTransparent() || renderer->hasMask() || renderer->hasReflection() - || renderer->hasFilter() - || layer->mustOverlapCompositedLayers(); + || renderer->hasFilter()) + return true; + + + if (layer->mustCompositeForIndirectReasons()) { + RenderLayer::IndirectCompositingReason reason = layer->indirectCompositingReason(); + return reason == RenderLayer::IndirectCompositingForOverlap + || reason == RenderLayer::IndirectCompositingForBackgroundLayer + || reason == RenderLayer::IndirectCompositingForGraphicalEffect + || reason == RenderLayer::IndirectCompositingForPreserve3D; // preserve-3d has to create backing store to ensure that 3d-transformed elements intersect. + } + return false; } #if !LOG_DISABLED @@ -1486,14 +1506,8 @@ const char* RenderLayerCompositor::reasonForCompositing(const RenderLayer* layer layer = toRenderBoxModelObject(renderer)->layer(); } - if (renderer->hasTransform() && renderer->style()->hasPerspective()) - return "perspective"; - - if (renderer->hasTransform() && (renderer->style()->transformStyle3D() == TransformStyle3DPreserve3D)) - return "preserve-3d"; - - if (renderer->hasTransform()) - return "transform"; + if (requiresCompositingForTransform(renderer)) + return "3D transform"; if (requiresCompositingForVideo(renderer)) return "video"; @@ -1523,9 +1537,35 @@ const char* RenderLayerCompositor::reasonForCompositing(const RenderLayer* layer return "position: fixed"; // This includes layers made composited by requiresCompositingWhenDescendantsAreCompositing(). - if (layer->mustOverlapCompositedLayers()) + if (layer->indirectCompositingReason() == RenderLayer::IndirectCompositingForOverlap) return "overlap/stacking"; + if (layer->indirectCompositingReason() == RenderLayer::IndirectCompositingForBackgroundLayer) + return "negative z-index children"; + + if (layer->indirectCompositingReason() == RenderLayer::IndirectCompositingForGraphicalEffect) { + if (layer->transform()) + return "transform with composited descendants"; + + if (renderer->isTransparent()) + return "opacity with composited descendants"; + + if (renderer->hasMask()) + return "mask with composited descendants"; + + if (renderer->hasReflection()) + return "reflection with composited descendants"; + + if (renderer->hasFilter()) + return "filter with composited descendants"; + } + + if (layer->indirectCompositingReason() == RenderLayer::IndirectCompositingForPerspective) + return "perspective"; + + if (layer->indirectCompositingReason() == RenderLayer::IndirectCompositingForPreserve3D) + return "preserve-3d"; + if (inCompositingMode() && layer->isRootLayer()) return "root"; @@ -1576,6 +1616,31 @@ bool RenderLayerCompositor::clipsCompositingDescendants(const RenderLayer* layer (layer->renderer()->hasOverflowClip() || layer->renderer()->hasClip()); } +// Return true if there is an ancestor layer that is fixed positioned to the view. +// Note that if the ancestor has a stacking context and is fixed position then this method +// will return false. +bool RenderLayerCompositor::fixedPositionedByAncestor(const RenderLayer* layer) const +{ + if (!layer->isComposited() || !layer->parent()) + return false; + + const RenderLayer* compositingAncestor = layer->ancestorCompositingLayer(); + if (!compositingAncestor) + return false; + + const RenderLayer* curr = layer; + while (curr) { + const RenderLayer* next = curr->parent(); + if (next == compositingAncestor) + return false; + + if (next && next->renderer()->style()->position() == FixedPosition) + return true; + curr = next; + } + return false; +} + bool RenderLayerCompositor::requiresCompositingForScrollableFrame() const { // Need this done first to determine overflow. @@ -1593,7 +1658,7 @@ bool RenderLayerCompositor::requiresCompositingForTransform(RenderObject* render RenderStyle* style = renderer->style(); // Note that we ask the renderer if it has a transform, because the style may have transforms, // but the renderer may be an inline that doesn't suppport them. - return renderer->hasTransform() && (style->transform().has3DOperation() || style->transformStyle3D() == TransformStyle3DPreserve3D || style->hasPerspective()); + return renderer->hasTransform() && style->transform().has3DOperation(); } bool RenderLayerCompositor::requiresCompositingForVideo(RenderObject* renderer) const @@ -1701,11 +1766,35 @@ bool RenderLayerCompositor::requiresCompositingForAnimation(RenderObject* render return false; } -bool RenderLayerCompositor::requiresCompositingWhenDescendantsAreCompositing(RenderObject* renderer) const +bool RenderLayerCompositor::requiresCompositingForIndirectReason(RenderObject* renderer, bool hasCompositedDescendants, bool has3DTransformedDescendants, RenderLayer::IndirectCompositingReason& reason) const { - return renderer->hasTransform() || renderer->isTransparent() || renderer->hasMask() || renderer->hasReflection() || renderer->hasFilter(); -} + RenderLayer* layer = toRenderBoxModelObject(renderer)->layer(); + + // When a layer has composited descendants, some effects, like 2d transforms, filters, masks etc must be implemented + // via compositing so that they also apply to those composited descdendants. + if (hasCompositedDescendants && (layer->transform() || renderer->isTransparent() || renderer->hasMask() || renderer->hasReflection() || renderer->hasFilter())) { + reason = RenderLayer::IndirectCompositingForGraphicalEffect; + return true; + } + + // A layer with preserve-3d or perspective only needs to be composited if there are descendant layers that + // will be affected by the preserve-3d or perspective. + if (has3DTransformedDescendants) { + if (renderer->style()->transformStyle3D() == TransformStyle3DPreserve3D) { + reason = RenderLayer::IndirectCompositingForPreserve3D; + return true; + } + if (renderer->style()->hasPerspective()) { + reason = RenderLayer::IndirectCompositingForPerspective; + return true; + } + } + + reason = RenderLayer::NoIndirectCompositingReason; + return false; +} + bool RenderLayerCompositor::requiresCompositingForFilters(RenderObject* renderer) const { #if ENABLE(CSS_FILTERS) @@ -1745,7 +1834,7 @@ bool RenderLayerCompositor::requiresCompositingForPosition(RenderObject* rendere // Fixed position elements that are invisible in the current view don't get their own layer. FrameView* frameView = m_renderView->frameView(); - if (frameView && !layer->absoluteBoundingBox().intersects(IntRect(frameView->scrollXForFixedPosition(), frameView->scrollYForFixedPosition(), frameView->layoutWidth(), frameView->layoutHeight()))) + if (frameView && !layer->absoluteBoundingBox().intersects(IntRect(IntPoint(frameView->scrollOffsetForFixedPosition()), frameView->layoutSize()))) return false; return true; @@ -2099,6 +2188,8 @@ void RenderLayerCompositor::ensureRootLayer() #ifndef NDEBUG m_scrollLayer->setName("frame scrolling"); #endif + if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) + scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(m_scrollLayer.get(), true); // Hook them up m_overflowControlsHostLayer->addChild(m_clipLayer.get()); diff --git a/Source/WebCore/rendering/RenderLayerCompositor.h b/Source/WebCore/rendering/RenderLayerCompositor.h index 7aa725e03..ff24c9648 100644 --- a/Source/WebCore/rendering/RenderLayerCompositor.h +++ b/Source/WebCore/rendering/RenderLayerCompositor.h @@ -116,6 +116,9 @@ public: // Whether layer's backing needs a graphics layer to clip z-order children of the given layer. bool clipsCompositingDescendants(const RenderLayer*) const; + // Whether the layer is fixed positioned to the view by an ancestor layer. + bool fixedPositionedByAncestor(const RenderLayer*) const; + // Whether the given layer needs an extra 'contents' layer. bool needsContentsCompositingLayer(const RenderLayer*) const; // Return the bounding box required for compositing layer and its childern, relative to ancestorLayer. @@ -246,7 +249,7 @@ private: void updateCompositingLayersTimerFired(Timer<RenderLayerCompositor>*); // Returns true if any layer's compositing changed - void computeCompositingRequirements(RenderLayer* ancestorLayer, RenderLayer*, OverlapMap*, struct CompositingState&, bool& layersChanged); + void computeCompositingRequirements(RenderLayer* ancestorLayer, RenderLayer*, OverlapMap*, struct CompositingState&, bool& layersChanged, bool& descendantHas3DTransform); // Recurses down the tree, parenting descendant compositing layers and collecting an array of child layers for the current compositing layer. void rebuildCompositingLayerTree(RenderLayer*, Vector<GraphicsLayer*>& childGraphicsLayersOfEnclosingLayer, int depth); @@ -286,10 +289,10 @@ private: bool requiresCompositingForCanvas(RenderObject*) const; bool requiresCompositingForPlugin(RenderObject*) const; bool requiresCompositingForFrame(RenderObject*) const; - bool requiresCompositingWhenDescendantsAreCompositing(RenderObject*) const; bool requiresCompositingForFilters(RenderObject*) const; bool requiresCompositingForScrollableFrame() const; bool requiresCompositingForPosition(RenderObject*, const RenderLayer*) const; + bool requiresCompositingForIndirectReason(RenderObject*, bool hasCompositedDescendants, bool has3DTransformedDescendants, RenderLayer::IndirectCompositingReason&) const; bool requiresScrollLayer(RootLayerAttachment) const; bool requiresHorizontalScrollbarLayer() const; diff --git a/Source/WebCore/rendering/RenderListBox.cpp b/Source/WebCore/rendering/RenderListBox.cpp index aa591de66..516449fc5 100644 --- a/Source/WebCore/rendering/RenderListBox.cpp +++ b/Source/WebCore/rendering/RenderListBox.cpp @@ -358,7 +358,8 @@ static LayoutSize itemOffsetForAlignment(TextRun textRun, RenderStyle* itemStyle { ETextAlign actualAlignment = itemStyle->textAlign(); // FIXME: Firefox doesn't respect JUSTIFY. Should we? - if (actualAlignment == TAAUTO || actualAlignment == JUSTIFY) + // FIXME: Handle TAEND here + if (actualAlignment == TASTART || actualAlignment == JUSTIFY) actualAlignment = itemStyle->isLeftToRightDirection() ? LEFT : RIGHT; LayoutSize offset = LayoutSize(0, itemFont.fontMetrics().ascent()); diff --git a/Source/WebCore/rendering/RenderMarquee.cpp b/Source/WebCore/rendering/RenderMarquee.cpp index 7cb69e928..2ddffc56f 100644 --- a/Source/WebCore/rendering/RenderMarquee.cpp +++ b/Source/WebCore/rendering/RenderMarquee.cpp @@ -230,7 +230,7 @@ void RenderMarquee::updateMarqueeStyle() // FIXME: Bring these up with the CSS WG. if (isHorizontal() && m_layer->renderer()->childrenInline()) { s->setWhiteSpace(NOWRAP); - s->setTextAlign(TAAUTO); + s->setTextAlign(TASTART); } } diff --git a/Source/WebCore/rendering/RenderMediaControlsChromium.cpp b/Source/WebCore/rendering/RenderMediaControlsChromium.cpp index 72e12c881..7fa55271a 100644 --- a/Source/WebCore/rendering/RenderMediaControlsChromium.cpp +++ b/Source/WebCore/rendering/RenderMediaControlsChromium.cpp @@ -74,14 +74,25 @@ static bool paintMediaMuteButton(RenderObject* object, const PaintInfo& paintInf if (!mediaElement) return false; - static Image* soundFull = platformResource("mediaSoundFull"); - static Image* soundNone = platformResource("mediaSoundNone"); - static Image* soundDisabled = platformResource("mediaSoundDisabled"); + static Image* soundLevel3 = platformResource("mediaplayerSoundLevel3"); + static Image* soundLevel2 = platformResource("mediaplayerSoundLevel2"); + static Image* soundLevel1 = platformResource("mediaplayerSoundLevel1"); + static Image* soundLevel0 = platformResource("mediaplayerSoundLevel0"); + static Image* soundDisabled = platformResource("mediaplayerSoundDisabled"); if (!hasSource(mediaElement) || !mediaElement->hasAudio()) return paintMediaButton(paintInfo.context, rect, soundDisabled); - return paintMediaButton(paintInfo.context, rect, mediaElement->muted() ? soundNone: soundFull); + if (mediaElement->muted() || mediaElement->volume() <= 0) + return paintMediaButton(paintInfo.context, rect, soundLevel0); + + if (mediaElement->volume() <= 0.33) + return paintMediaButton(paintInfo.context, rect, soundLevel1); + + if (mediaElement->volume() <= 0.66) + return paintMediaButton(paintInfo.context, rect, soundLevel2); + + return paintMediaButton(paintInfo.context, rect, soundLevel3); } static bool paintMediaPlayButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) @@ -90,9 +101,9 @@ static bool paintMediaPlayButton(RenderObject* object, const PaintInfo& paintInf if (!mediaElement) return false; - static Image* mediaPlay = platformResource("mediaPlay"); - static Image* mediaPause = platformResource("mediaPause"); - static Image* mediaPlayDisabled = platformResource("mediaPlayDisabled"); + static Image* mediaPlay = platformResource("mediaplayerPlay"); + static Image* mediaPause = platformResource("mediaplayerPause"); + static Image* mediaPlayDisabled = platformResource("mediaplayerPlayDisabled"); if (!hasSource(mediaElement)) return paintMediaButton(paintInfo.context, rect, mediaPlayDisabled); @@ -102,10 +113,75 @@ static bool paintMediaPlayButton(RenderObject* object, const PaintInfo& paintInf static Image* getMediaSliderThumb() { - static Image* mediaSliderThumb = platformResource("mediaSliderThumb"); + static Image* mediaSliderThumb = platformResource("mediaplayerSliderThumb"); return mediaSliderThumb; } +static void paintRoundedSliderBackground(const IntRect& rect, const RenderStyle* style, GraphicsContext* context) +{ + int borderRadius = rect.height() / 2; + IntSize radii(borderRadius, borderRadius); + Color sliderBackgroundColor = Color(29, 29, 29); + context->save(); + context->fillRoundedRect(rect, radii, radii, radii, radii, sliderBackgroundColor, ColorSpaceDeviceRGB); + context->restore(); +} + +static void paintSliderRangeHighlight(const IntRect& rect, const RenderStyle* style, GraphicsContext* context, float startFraction, float widthFraction) +{ + if (startFraction < 0) + startFraction = 0; + if (widthFraction > 1) + widthFraction = 1; + float endFraction = startFraction + widthFraction; + if (endFraction > 1) { + widthFraction = widthFraction - startFraction; + endFraction = startFraction + widthFraction; + } + + // Set rectangle to highlight range. + IntRect highlightRect = rect; + int startOffset = startFraction * rect.width(); + int endOffset = rect.width() - endFraction * rect.width(); + int rangeWidth = widthFraction * rect.width(); + highlightRect.move(startOffset, 0); + highlightRect.setWidth(rangeWidth); + + // Don't bother drawing an empty area. + if (highlightRect.isEmpty()) + return; + + // Calculate border radius; need to avoid being smaller than half the slider height + // because of https://bugs.webkit.org/show_bug.cgi?id=30143. + int borderRadius = rect.height() / 2; + IntSize radii(borderRadius, borderRadius); + + // Calculate white-grey gradient. + IntPoint sliderTopLeft = highlightRect.location(); + IntPoint sliderBottomLeft = sliderTopLeft; + sliderBottomLeft.move(0, highlightRect.height()); + Color startColor = Color(220, 220, 220); + Color endColor = Color(240, 240, 240); + RefPtr<Gradient> gradient = Gradient::create(sliderTopLeft, sliderBottomLeft); + gradient->addColorStop(0.0, startColor); + gradient->addColorStop(1.0, endColor); + + // Fill highlight rectangle with gradient, potentially rounded if on left or right edge. + context->save(); + context->setFillGradient(gradient); + + if (startOffset < borderRadius && endOffset < borderRadius) + context->fillRoundedRect(highlightRect, radii, radii, radii, radii, startColor, ColorSpaceDeviceRGB); + else if (startOffset < borderRadius) + context->fillRoundedRect(highlightRect, radii, IntSize(0, 0), radii, IntSize(0, 0), startColor, ColorSpaceDeviceRGB); + else if (endOffset < borderRadius) + context->fillRoundedRect(highlightRect, IntSize(0, 0), radii, IntSize(0, 0), radii, startColor, ColorSpaceDeviceRGB); + else + context->fillRect(highlightRect); + + context->restore(); +} + static bool paintMediaSlider(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) { HTMLMediaElement* mediaElement = toParentMediaElement(object); @@ -115,23 +191,10 @@ static bool paintMediaSlider(RenderObject* object, const PaintInfo& paintInfo, c 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->setShouldAntialias(true); - context->setStrokeStyle(SolidStroke); - context->setStrokeColor(style->visitedDependentColor(CSSPropertyBorderLeftColor), ColorSpaceDeviceRGB); - context->setStrokeThickness(style->borderLeftWidth()); - context->setFillColor(style->visitedDependentColor(CSSPropertyBackgroundColor), ColorSpaceDeviceRGB); - context->drawRect(rect); - context->restore(); + paintRoundedSliderBackground(rect, style, context); // Draw the buffered range. Since the element may have multiple buffered ranges and it'd be // distracting/'busy' to show all of them, show only the buffered range containing the current play head. - IntRect bufferedRect = rect; - bufferedRect.inflate(-style->borderLeftWidth()); - RefPtr<TimeRanges> bufferedTimeRanges = mediaElement->buffered(); float duration = mediaElement->duration(); float currentTime = mediaElement->currentTime(); @@ -146,27 +209,8 @@ static bool paintMediaSlider(RenderObject* object, const PaintInfo& paintInfo, c float startFraction = start / duration; float endFraction = end / duration; float widthFraction = endFraction - startFraction; - bufferedRect.move(startFraction * bufferedRect.width(), 0); - bufferedRect.setWidth(widthFraction * bufferedRect.width()); - - // Don't bother drawing an empty area. - if (bufferedRect.isEmpty()) - return true; - - IntPoint sliderTopLeft = bufferedRect.location(); - IntPoint sliderBottomLeft = sliderTopLeft; - sliderBottomLeft.move(0, bufferedRect.height()); - - RefPtr<Gradient> gradient = Gradient::create(sliderTopLeft, sliderBottomLeft); - Color startColor = object->style()->visitedDependentColor(CSSPropertyColor); - 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->fillRect(bufferedRect); - context->restore(); + + paintSliderRangeHighlight(rect, style, context, startFraction, widthFraction); return true; } @@ -189,6 +233,8 @@ static bool paintMediaSliderThumb(RenderObject* object, const PaintInfo& paintIn return paintMediaButton(paintInfo.context, rect, mediaSliderThumb); } +const int mediaVolumeSliderThumbWidth = 24; + static bool paintMediaVolumeSlider(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) { HTMLMediaElement* mediaElement = toParentMediaElement(object); @@ -196,55 +242,47 @@ static bool paintMediaVolumeSlider(RenderObject* object, const PaintInfo& paintI return false; GraphicsContext* context = paintInfo.context; - Color originalColor = context->strokeColor(); - if (originalColor != Color::white) - context->setStrokeColor(Color::white, ColorSpaceDeviceRGB); + RenderStyle* style = object->style(); + + paintRoundedSliderBackground(rect, style, context); - int x = rect.x() + rect.width() / 2; - context->drawLine(IntPoint(x, rect.y()), IntPoint(x, rect.y() + rect.height())); + // Calculate volume position for white background rectangle. + float volume = mediaElement->volume(); + if (isnan(volume) || volume < 0) + return true; + if (volume > 1) + volume = 1; + if (!hasSource(mediaElement) || !mediaElement->hasAudio() || mediaElement->muted()) + volume = 0; + + // Calculate the position relative to the center of the thumb. + float fillWidth = 0; + if (volume > 0) { + float thumbCenter = mediaVolumeSliderThumbWidth / 2; + float zoomLevel = style->effectiveZoom(); + float positionWidth = volume * (rect.width() - (zoomLevel * thumbCenter)); + fillWidth = positionWidth + (zoomLevel * thumbCenter / 2); + } + + paintSliderRangeHighlight(rect, style, context, 0.0, fillWidth / rect.width()); - if (originalColor != Color::white) - context->setStrokeColor(originalColor, ColorSpaceDeviceRGB); return true; } static bool paintMediaVolumeSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) { - static Image* mediaVolumeSliderThumb = platformResource("mediaVolumeSliderThumb"); - return paintMediaButton(paintInfo.context, rect, mediaVolumeSliderThumb); -} - -static bool paintMediaTimelineContainer(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) -{ - HTMLMediaElement* mediaElement = toParentMediaElement(object); + ASSERT(object->node()); + Node* hostNode = object->node()->shadowAncestorNode(); + ASSERT(hostNode); + HTMLMediaElement* mediaElement = toParentMediaElement(hostNode); 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()->visitedDependentColor(CSSPropertyBorderLeftColor).rgb(), ColorSpaceDeviceRGB); - 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()->visitedDependentColor(CSSPropertyBorderRightColor).rgb(), ColorSpaceDeviceRGB); - context->drawLine(IntPoint(rect.x() + rect.width() - 1, rect.y()), - IntPoint(rect.x() + rect.width() - 1, rect.y() + rect.height())); - - context->setStrokeColor(originalColor, ColorSpaceDeviceRGB); - context->setStrokeThickness(originalThickness); - context->setStrokeStyle(originalStyle); - } - return true; + if (!hasSource(mediaElement) || !mediaElement->hasAudio()) + return true; + + static Image* mediaVolumeSliderThumb = platformResource("mediaplayerVolumeSliderThumb"); + return paintMediaButton(paintInfo.context, rect, mediaVolumeSliderThumb); } static bool paintMediaFullscreenButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) @@ -253,8 +291,8 @@ static bool paintMediaFullscreenButton(RenderObject* object, const PaintInfo& pa if (!mediaElement) return false; - DEFINE_STATIC_LOCAL(Image*, mediaFullscreen, (platformResource("mediaFullscreen"))); - return paintMediaButton(paintInfo.context, rect, mediaFullscreen); + static Image* mediaFullscreenButton = platformResource("mediaplayerFullscreen"); + return paintMediaButton(paintInfo.context, rect, mediaFullscreenButton); } bool RenderMediaControlsChromium::paintMediaControlsPart(MediaControlElementType part, RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) @@ -274,8 +312,6 @@ bool RenderMediaControlsChromium::paintMediaControlsPart(MediaControlElementType return paintMediaVolumeSlider(object, paintInfo, rect); case MediaVolumeSliderThumb: return paintMediaVolumeSliderThumb(object, paintInfo, rect); - case MediaTimelineContainer: - return paintMediaTimelineContainer(object, paintInfo, rect); case MediaEnterFullscreenButton: case MediaExitFullscreenButton: return paintMediaFullscreenButton(object, paintInfo, rect); @@ -283,6 +319,7 @@ bool RenderMediaControlsChromium::paintMediaControlsPart(MediaControlElementType case MediaSeekBackButton: case MediaSeekForwardButton: case MediaVolumeSliderContainer: + case MediaTimelineContainer: case MediaCurrentTimeDisplay: case MediaTimeRemainingDisplay: case MediaControlsPanel: @@ -301,24 +338,74 @@ bool RenderMediaControlsChromium::paintMediaControlsPart(MediaControlElementType return false; } +const int mediaSliderThumbWidth = 32; +const int mediaSliderThumbHeight = 24; +const int mediaVolumeSliderThumbHeight = 24; + void RenderMediaControlsChromium::adjustMediaSliderThumbSize(RenderStyle* style) { - static Image* mediaSliderThumb = platformResource("mediaSliderThumb"); - static Image* mediaVolumeSliderThumb = platformResource("mediaVolumeSliderThumb"); + static Image* mediaSliderThumb = platformResource("mediaplayerSliderThumb"); + static Image* mediaVolumeSliderThumb = platformResource("mediaplayerVolumeSliderThumb"); + int width = 0; + int height = 0; Image* thumbImage = 0; - if (style->appearance() == MediaSliderThumbPart) + if (style->appearance() == MediaSliderThumbPart) { thumbImage = mediaSliderThumb; - else if (style->appearance() == MediaVolumeSliderThumbPart) + width = mediaSliderThumbWidth; + height = mediaSliderThumbHeight; + } else if (style->appearance() == MediaVolumeSliderThumbPart) { thumbImage = mediaVolumeSliderThumb; + width = mediaVolumeSliderThumbWidth; + height = mediaVolumeSliderThumbHeight; + } float zoomLevel = style->effectiveZoom(); if (thumbImage) { - style->setWidth(Length(static_cast<int>(thumbImage->width() * zoomLevel), Fixed)); - style->setHeight(Length(static_cast<int>(thumbImage->height() * zoomLevel), Fixed)); + style->setWidth(Length(static_cast<int>(width * zoomLevel), Fixed)); + style->setHeight(Length(static_cast<int>(height * zoomLevel), Fixed)); } } +static String formatChromiumMediaControlsTime(float time, float duration) +{ + if (!isfinite(time)) + time = 0; + if (!isfinite(duration)) + duration = 0; + int seconds = static_cast<int>(fabsf(time)); + int hours = seconds / (60 * 60); + int minutes = (seconds / 60) % 60; + seconds %= 60; + + // duration defines the format of how the time is rendered + int durationSecs = static_cast<int>(fabsf(duration)); + int durationHours = durationSecs / (60 * 60); + int durationMins = (durationSecs / 60) % 60; + + if (durationHours || hours) + return String::format("%s%01d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds); + if (durationMins > 9) + return String::format("%s%02d:%02d", (time < 0 ? "-" : ""), minutes, seconds); + + return String::format("%s%01d:%02d", (time < 0 ? "-" : ""), minutes, seconds); +} + +String RenderMediaControlsChromium::formatMediaControlsTime(float time) +{ + return formatChromiumMediaControlsTime(time, time); +} + +String RenderMediaControlsChromium::formatMediaControlsCurrentTime(float currentTime, float duration) +{ + return formatChromiumMediaControlsTime(currentTime, duration); +} + +String RenderMediaControlsChromium::formatMediaControlsRemainingTime(float currentTime, float duration) +{ + return formatChromiumMediaControlsTime(currentTime - duration, duration); +} + #endif // #if ENABLE(VIDEO) } // namespace WebCore diff --git a/Source/WebCore/rendering/RenderMediaControlsChromium.h b/Source/WebCore/rendering/RenderMediaControlsChromium.h index 9af93960f..c3b801bf0 100644 --- a/Source/WebCore/rendering/RenderMediaControlsChromium.h +++ b/Source/WebCore/rendering/RenderMediaControlsChromium.h @@ -38,6 +38,9 @@ class RenderMediaControlsChromium { public: static bool paintMediaControlsPart(MediaControlElementType, RenderObject*, const PaintInfo&, const IntRect&); static void adjustMediaSliderThumbSize(RenderStyle*); + static String formatMediaControlsTime(float time); + static String formatMediaControlsCurrentTime(float currentTime, float duration); + static String formatMediaControlsRemainingTime(float currentTime, float duration); }; } // namespace WebCore diff --git a/Source/WebCore/rendering/RenderMenuList.cpp b/Source/WebCore/rendering/RenderMenuList.cpp index 48146e266..56eccf8a1 100644 --- a/Source/WebCore/rendering/RenderMenuList.cpp +++ b/Source/WebCore/rendering/RenderMenuList.cpp @@ -312,9 +312,6 @@ void RenderMenuList::showPopup() // the actual width of the element to size the popup. FloatPoint absTopLeft = localToAbsolute(FloatPoint(), false, true); IntRect absBounds = absoluteBoundingBoxRectIgnoringTransforms(); - int scale = document()->page()->settings()->defaultDeviceScaleFactor(); - if (scale && scale != 1) - absBounds.scale(scale); absBounds.setLocation(roundedIntPoint(absTopLeft)); HTMLSelectElement* select = toHTMLSelectElement(node()); m_popup->show(absBounds, document()->view(), select->optionToListIndex(select->selectedIndex())); diff --git a/Source/WebCore/rendering/RenderObject.cpp b/Source/WebCore/rendering/RenderObject.cpp index 258477659..be90dd6ba 100755 --- a/Source/WebCore/rendering/RenderObject.cpp +++ b/Source/WebCore/rendering/RenderObject.cpp @@ -389,6 +389,14 @@ RenderObject* RenderObject::previousInPreOrder() const return parent(); } +RenderObject* RenderObject::previousInPreOrder(const RenderObject* stayWithin) const +{ + if (this == stayWithin) + return 0; + + return previousInPreOrder(); +} + RenderObject* RenderObject::childAt(unsigned index) const { RenderObject* child = firstChild(); @@ -716,20 +724,36 @@ RenderBlock* RenderObject::containingBlock() const if (!o && isRenderScrollbarPart()) o = toRenderScrollbarPart(this)->rendererOwningScrollbar(); if (!isText() && m_style->position() == FixedPosition) { - while (o && !o->isRenderView() && !(o->hasTransform() && o->isRenderBlock())) + while (o) { + if (o->isRenderView()) + break; + if (o->hasTransform() && o->isRenderBlock()) + break; +#if ENABLE(SVG) + // foreignObject is the containing block for its contents. + if (o->isSVGForeignObject()) + break; +#endif o = o->parent(); + } + ASSERT(!o->isAnonymousBlock()); } else if (!isText() && m_style->position() == AbsolutePosition) { - while (o && (o->style()->position() == StaticPosition || (o->isInline() && !o->isReplaced())) && !o->isRenderView() && !(o->hasTransform() && o->isRenderBlock())) { + while (o) { // For relpositioned inlines, we return the nearest non-anonymous enclosing block. We don't try // to return the inline itself. This allows us to avoid having a positioned objects // list in all RenderInlines and lets us return a strongly-typed RenderBlock* result // from this method. The container() method can actually be used to obtain the // inline directly. + if (!o->style()->position() == StaticPosition && !(o->isInline() && !o->isReplaced())) + break; + if (o->isRenderView()) + break; + if (o->hasTransform() && o->isRenderBlock()) + break; + if (o->style()->position() == RelativePosition && o->isInline() && !o->isReplaced()) { - RenderBlock* relPositionedInlineContainingBlock = o->containingBlock(); - while (relPositionedInlineContainingBlock->isAnonymousBlock()) - relPositionedInlineContainingBlock = relPositionedInlineContainingBlock->containingBlock(); - return relPositionedInlineContainingBlock; + o = o->containingBlock(); + break; } #if ENABLE(SVG) if (o->isSVGForeignObject()) //foreignObject is the containing block for contents inside it @@ -738,6 +762,9 @@ RenderBlock* RenderObject::containingBlock() const o = o->parent(); } + + while (o && o->isAnonymousBlock()) + o = o->containingBlock(); } else { while (o && ((o->isInline() && !o->isReplaced()) || !o->isRenderBlock())) o = o->parent(); @@ -1014,91 +1041,6 @@ void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1, } } -#if !HAVE(PATH_BASED_BORDER_RADIUS_DRAWING) -void RenderObject::drawArcForBoxSide(GraphicsContext* graphicsContext, int x, int y, float thickness, const IntSize& radius, - int angleStart, int angleSpan, BoxSide s, Color color, - EBorderStyle style, bool firstCorner) -{ - // FIXME: This function should be removed when all ports implement GraphicsContext::clipConvexPolygon()!! - // At that time, everyone can use RenderObject::drawBoxSideFromPath() instead. This should happen soon. - if ((style == DOUBLE && thickness / 2 < 3) || ((style == RIDGE || style == GROOVE) && thickness / 2 < 2)) - style = SOLID; - - switch (style) { - case BNONE: - case BHIDDEN: - return; - case DOTTED: - case DASHED: - graphicsContext->setStrokeColor(color, m_style->colorSpace()); - graphicsContext->setStrokeStyle(style == DOTTED ? DottedStroke : DashedStroke); - graphicsContext->setStrokeThickness(thickness); - graphicsContext->strokeArc(IntRect(x, y, radius.width() * 2, radius.height() * 2), angleStart, angleSpan); - break; - case DOUBLE: { - float third = thickness / 3.0f; - float innerThird = (thickness + 1.0f) / 6.0f; - int shiftForInner = static_cast<int>(innerThird * 2.5f); - - int outerY = y; - int outerHeight = radius.height() * 2; - int innerX = x + shiftForInner; - int innerY = y + shiftForInner; - int innerWidth = (radius.width() - shiftForInner) * 2; - int innerHeight = (radius.height() - shiftForInner) * 2; - if (innerThird > 1 && (s == BSTop || (firstCorner && (s == BSLeft || s == BSRight)))) { - outerHeight += 2; - innerHeight += 2; - } - - graphicsContext->setStrokeStyle(SolidStroke); - graphicsContext->setStrokeColor(color, m_style->colorSpace()); - graphicsContext->setStrokeThickness(third); - graphicsContext->strokeArc(IntRect(x, outerY, radius.width() * 2, outerHeight), angleStart, angleSpan); - graphicsContext->setStrokeThickness(innerThird > 2 ? innerThird - 1 : innerThird); - graphicsContext->strokeArc(IntRect(innerX, innerY, innerWidth, innerHeight), angleStart, angleSpan); - break; - } - case GROOVE: - case RIDGE: { - Color c2; - if ((style == RIDGE && (s == BSTop || s == BSLeft)) || - (style == GROOVE && (s == BSBottom || s == BSRight))) - c2 = color.dark(); - else { - c2 = color; - color = color.dark(); - } - - graphicsContext->setStrokeStyle(SolidStroke); - graphicsContext->setStrokeColor(color, m_style->colorSpace()); - graphicsContext->setStrokeThickness(thickness); - graphicsContext->strokeArc(IntRect(x, y, radius.width() * 2, radius.height() * 2), angleStart, angleSpan); - - float halfThickness = (thickness + 1.0f) / 4.0f; - int shiftForInner = static_cast<int>(halfThickness * 1.5f); - graphicsContext->setStrokeColor(c2, m_style->colorSpace()); - graphicsContext->setStrokeThickness(halfThickness > 2 ? halfThickness - 1 : halfThickness); - graphicsContext->strokeArc(IntRect(x + shiftForInner, y + shiftForInner, (radius.width() - shiftForInner) * 2, - (radius.height() - shiftForInner) * 2), angleStart, angleSpan); - break; - } - case INSET: - if (s == BSTop || s == BSLeft) - color = color.dark(); - case OUTSET: - if (style == OUTSET && (s == BSBottom || s == BSRight)) - color = color.dark(); - case SOLID: - graphicsContext->setStrokeStyle(SolidStroke); - graphicsContext->setStrokeColor(color, m_style->colorSpace()); - graphicsContext->setStrokeThickness(thickness); - graphicsContext->strokeArc(IntRect(x, y, radius.width() * 2, radius.height() * 2), angleStart, angleSpan); - break; - } -} -#endif - void RenderObject::paintFocusRing(GraphicsContext* context, const LayoutPoint& paintOffset, RenderStyle* style) { Vector<IntRect> focusRingRects; @@ -1107,7 +1049,7 @@ void RenderObject::paintFocusRing(GraphicsContext* context, const LayoutPoint& p context->drawFocusRing(focusRingRects, style->outlineWidth(), style->outlineOffset(), style->visitedDependentColor(CSSPropertyOutlineColor)); else addPDFURLRect(context, unionRect(focusRingRects)); -} +} void RenderObject::addPDFURLRect(GraphicsContext* context, const LayoutRect& rect) { @@ -1847,7 +1789,7 @@ void RenderObject::styleWillChange(StyleDifference diff, const RenderStyle* newS if (m_style->visibility() != newStyle->visibility()) { if (RenderLayer* l = enclosingLayer()) { if (newStyle->visibility() == VISIBLE) - l->setHasVisibleContent(true); + l->setHasVisibleContent(); else if (l->hasVisibleContent() && (this == l->renderer() || l->renderer()->style()->visibility() != VISIBLE)) { l->dirtyVisibleContentStatus(); if (diff > StyleDifferenceRepaintLayer) @@ -2272,8 +2214,14 @@ RenderObject* RenderObject::container(const RenderBoxModelObject* repaintContain // 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())) { +#if ENABLE(SVG) + // foreignObject is the containing block for its contents. + if (o->isSVGForeignObject()) + break; +#endif if (repaintContainerSkipped && o == repaintContainer) *repaintContainerSkipped = true; + o = o->parent(); } } else if (pos == AbsolutePosition) { @@ -2281,12 +2229,13 @@ RenderObject* RenderObject::container(const RenderBoxModelObject* repaintContain // 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())) { - if (repaintContainerSkipped && o == repaintContainer) - *repaintContainerSkipped = true; #if ENABLE(SVG) if (o->isSVGForeignObject()) // foreignObject is the containing block for contents inside it break; #endif + if (repaintContainerSkipped && o == repaintContainer) + *repaintContainerSkipped = true; + o = o->parent(); } } diff --git a/Source/WebCore/rendering/RenderObject.h b/Source/WebCore/rendering/RenderObject.h index 58de96b31..23cdbc88c 100644 --- a/Source/WebCore/rendering/RenderObject.h +++ b/Source/WebCore/rendering/RenderObject.h @@ -41,10 +41,6 @@ #include <wtf/HashSet.h> #include <wtf/UnusedParam.h> -#if USE(CG) || USE(CAIRO) || USE(SKIA) || PLATFORM(QT) || PLATFORM(WX) -#define HAVE_PATH_BASED_BORDER_RADIUS_DRAWING 1 -#endif - namespace WebCore { class AffineTransform; @@ -197,6 +193,7 @@ public: RenderObject* nextInPreOrderAfterChildren() const; RenderObject* nextInPreOrderAfterChildren(const RenderObject* stayWithin) const; RenderObject* previousInPreOrder() const; + RenderObject* previousInPreOrder(const RenderObject* stayWithin) const; RenderObject* childAt(unsigned) const; RenderObject* firstLeafChild() const; @@ -489,6 +486,9 @@ public: && !isRenderFullScreen() && !isRenderFullScreenPlaceholder() #endif +#if ENABLE(MATHML) + && !isRenderMathMLBlock() +#endif ; } bool isAnonymousColumnsBlock() const { return style()->specifiesColumns() && isAnonymousBlock(); } @@ -552,13 +552,6 @@ public: inline bool preservesNewline() const; -#if !HAVE(PATH_BASED_BORDER_RADIUS_DRAWING) - // FIXME: This function should be removed when all ports implement GraphicsContext::clipConvexPolygon()!! - // At that time, everyone can use RenderObject::drawBoxSideFromPath() instead. This should happen soon. - void drawArcForBoxSide(GraphicsContext*, int x, int y, float thickness, const IntSize& radius, int angleStart, - int angleSpan, BoxSide, Color, EBorderStyle, bool firstCorner); -#endif - // The pseudo element style can be cached or uncached. Use the cached method if the pseudo element doesn't respect // any pseudo classes (and therefore has no concept of changing state). RenderStyle* getCachedPseudoStyle(PseudoId, RenderStyle* parentStyle = 0) const; @@ -1214,18 +1207,6 @@ inline void adjustFloatRectForAbsoluteZoom(FloatRect& rect, RenderObject* render rect.scale(1 / zoom, 1 / zoom); } -inline void adjustFloatQuadForPageScale(FloatQuad& quad, float pageScale) -{ - if (pageScale != 1) - quad.scale(1 / pageScale, 1 / pageScale); -} - -inline void adjustFloatRectForPageScale(FloatRect& rect, float pageScale) -{ - if (pageScale != 1) - rect.scale(1 / pageScale, 1 / pageScale); -} - } // namespace WebCore #ifndef NDEBUG diff --git a/Source/WebCore/rendering/RenderObjectChildList.cpp b/Source/WebCore/rendering/RenderObjectChildList.cpp index f0cf6aff8..f545297d9 100644 --- a/Source/WebCore/rendering/RenderObjectChildList.cpp +++ b/Source/WebCore/rendering/RenderObjectChildList.cpp @@ -194,7 +194,7 @@ void RenderObjectChildList::appendChildNode(RenderObject* owner, RenderObject* n if (!layer) layer = owner->enclosingLayer(); if (layer) - layer->setHasVisibleContent(true); + layer->setHasVisibleContent(); } if (newChild->isListItem()) @@ -261,7 +261,7 @@ void RenderObjectChildList::insertChildNode(RenderObject* owner, RenderObject* c if (!layer) layer = owner->enclosingLayer(); if (layer) - layer->setHasVisibleContent(true); + layer->setHasVisibleContent(); } if (child->isListItem()) diff --git a/Source/WebCore/rendering/RenderReplaced.cpp b/Source/WebCore/rendering/RenderReplaced.cpp index d290959e1..2555fcd6a 100644 --- a/Source/WebCore/rendering/RenderReplaced.cpp +++ b/Source/WebCore/rendering/RenderReplaced.cpp @@ -287,10 +287,9 @@ void RenderReplaced::computeIntrinsicRatioInformationForRenderBox(RenderBox* con intrinsicRatio = 1; return; } - - // This code path can't yield percentage intrinsic sizes, assert that. computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize); - ASSERT(!isPercentageIntrinsicSize); + if (intrinsicRatio) + ASSERT(!isPercentageIntrinsicSize); } void RenderReplaced::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const diff --git a/Source/WebCore/rendering/RenderRubyText.cpp b/Source/WebCore/rendering/RenderRubyText.cpp index c49b4f694..e9765f28d 100644 --- a/Source/WebCore/rendering/RenderRubyText.cpp +++ b/Source/WebCore/rendering/RenderRubyText.cpp @@ -54,7 +54,8 @@ bool RenderRubyText::isChildAllowed(RenderObject* child, RenderStyle*) const ETextAlign RenderRubyText::textAlignmentForLine(bool endsWithSoftBreak) const { ETextAlign textAlign = style()->textAlign(); - if (textAlign != TAAUTO) + // FIXME: This check is bogus since user can set the initial value. + if (textAlign != RenderStyle::initialTextAlign()) return RenderBlock::textAlignmentForLine(endsWithSoftBreak); // The default behavior is to allow ruby text to expand if it is shorter than the ruby base. @@ -64,7 +65,8 @@ ETextAlign RenderRubyText::textAlignmentForLine(bool endsWithSoftBreak) const void RenderRubyText::adjustInlineDirectionLineBounds(int expansionOpportunityCount, float& logicalLeft, float& logicalWidth) const { ETextAlign textAlign = style()->textAlign(); - if (textAlign != TAAUTO) + // FIXME: This check is bogus since user can set the initial value. + if (textAlign != RenderStyle::initialTextAlign()) return RenderBlock::adjustInlineDirectionLineBounds(expansionOpportunityCount, logicalLeft, logicalWidth); int maxPreferredLogicalWidth = this->maxPreferredLogicalWidth(); diff --git a/Source/WebCore/rendering/RenderSearchField.cpp b/Source/WebCore/rendering/RenderSearchField.cpp new file mode 100644 index 000000000..2704cdc03 --- /dev/null +++ b/Source/WebCore/rendering/RenderSearchField.cpp @@ -0,0 +1,385 @@ +/** + * Copyright (C) 2006, 2007, 2010 Apple Inc. All rights reserved. + * (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * 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. + * + */ + +#include "config.h" +#include "RenderSearchField.h" + +#include "CSSFontSelector.h" +#include "CSSValueKeywords.h" +#include "Chrome.h" +#include "Frame.h" +#include "FrameSelection.h" +#include "FrameView.h" +#include "HTMLInputElement.h" +#include "HTMLNames.h" +#include "HitTestResult.h" +#include "LocalizedStrings.h" +#include "Page.h" +#include "PlatformKeyboardEvent.h" +#include "RenderLayer.h" +#include "RenderScrollbar.h" +#include "RenderTheme.h" +#include "SearchPopupMenu.h" +#include "Settings.h" +#include "SimpleFontData.h" +#include "StyleResolver.h" +#include "TextControlInnerElements.h" + +using namespace std; + +namespace WebCore { + +using namespace HTMLNames; + +// ---------------------------- + +RenderSearchField::RenderSearchField(Node* node) + : RenderTextControlSingleLine(node) + , m_searchPopupIsVisible(false) + , m_searchPopup(0) +{ + ASSERT(node->isHTMLElement()); + ASSERT(node->toInputElement()); + ASSERT(node->toInputElement()->isSearchField()); +} + +RenderSearchField::~RenderSearchField() +{ + if (m_searchPopup) { + m_searchPopup->popupMenu()->disconnectClient(); + m_searchPopup = 0; + } +} + +inline HTMLElement* RenderSearchField::resultsButtonElement() const +{ + return inputElement()->resultsButtonElement(); +} + +inline HTMLElement* RenderSearchField::cancelButtonElement() const +{ + return inputElement()->cancelButtonElement(); +} + +void RenderSearchField::addSearchResult() +{ + HTMLInputElement* input = inputElement(); + if (input->maxResults() <= 0) + return; + + String value = input->value(); + if (value.isEmpty()) + return; + + Settings* settings = document()->settings(); + if (!settings || settings->privateBrowsingEnabled()) + return; + + int size = static_cast<int>(m_recentSearches.size()); + for (int i = size - 1; i >= 0; --i) { + if (m_recentSearches[i] == value) + m_recentSearches.remove(i); + } + + m_recentSearches.insert(0, value); + while (static_cast<int>(m_recentSearches.size()) > input->maxResults()) + m_recentSearches.removeLast(); + + const AtomicString& name = autosaveName(); + if (!m_searchPopup) + m_searchPopup = document()->page()->chrome()->createSearchPopupMenu(this); + + m_searchPopup->saveRecentSearches(name, m_recentSearches); +} + +void RenderSearchField::showPopup() +{ + if (m_searchPopupIsVisible) + return; + + if (!m_searchPopup) + m_searchPopup = document()->page()->chrome()->createSearchPopupMenu(this); + + if (!m_searchPopup->enabled()) + return; + + m_searchPopupIsVisible = true; + + const AtomicString& name = autosaveName(); + m_searchPopup->loadRecentSearches(name, m_recentSearches); + + // Trim the recent searches list if the maximum size has changed since we last saved. + HTMLInputElement* input = inputElement(); + if (static_cast<int>(m_recentSearches.size()) > input->maxResults()) { + do { + m_recentSearches.removeLast(); + } while (static_cast<int>(m_recentSearches.size()) > input->maxResults()); + + m_searchPopup->saveRecentSearches(name, m_recentSearches); + } + + m_searchPopup->popupMenu()->show(pixelSnappedIntRect(absoluteBoundingBoxRect()), document()->view(), -1); +} + +void RenderSearchField::hidePopup() +{ + if (m_searchPopup) + m_searchPopup->popupMenu()->hide(); +} + +LayoutUnit RenderSearchField::computeControlHeight(LayoutUnit lineHeight, LayoutUnit nonContentHeight) const +{ + HTMLElement* resultsButton = resultsButtonElement(); + if (RenderBox* resultsRenderer = resultsButton ? resultsButton->renderBox() : 0) { + resultsRenderer->computeLogicalHeight(); + nonContentHeight = max(nonContentHeight, resultsRenderer->borderAndPaddingHeight() + resultsRenderer->marginHeight()); + lineHeight = max(lineHeight, resultsRenderer->height()); + } + HTMLElement* cancelButton = cancelButtonElement(); + if (RenderBox* cancelRenderer = cancelButton ? cancelButton->renderBox() : 0) { + cancelRenderer->computeLogicalHeight(); + nonContentHeight = max(nonContentHeight, cancelRenderer->borderAndPaddingHeight() + cancelRenderer->marginHeight()); + lineHeight = max(lineHeight, cancelRenderer->height()); + } + + return lineHeight + nonContentHeight; +} + +void RenderSearchField::updateFromElement() +{ + RenderTextControlSingleLine::updateFromElement(); + + if (cancelButtonElement()) + updateCancelButtonVisibility(); + + if (m_searchPopupIsVisible) + m_searchPopup->popupMenu()->updateFromElement(); +} + +void RenderSearchField::updateCancelButtonVisibility() const +{ + RenderObject* cancelButtonRenderer = cancelButtonElement()->renderer(); + if (!cancelButtonRenderer) + return; + + const RenderStyle* curStyle = cancelButtonRenderer->style(); + EVisibility buttonVisibility = visibilityForCancelButton(); + if (curStyle->visibility() == buttonVisibility) + return; + + RefPtr<RenderStyle> cancelButtonStyle = RenderStyle::clone(curStyle); + cancelButtonStyle->setVisibility(buttonVisibility); + cancelButtonRenderer->setStyle(cancelButtonStyle); +} + +EVisibility RenderSearchField::visibilityForCancelButton() const +{ + return (style()->visibility() == HIDDEN || inputElement()->value().isEmpty()) ? HIDDEN : VISIBLE; +} + +const AtomicString& RenderSearchField::autosaveName() const +{ + return static_cast<Element*>(node())->getAttribute(autosaveAttr); +} + +// PopupMenuClient methods +void RenderSearchField::valueChanged(unsigned listIndex, bool fireEvents) +{ + ASSERT(static_cast<int>(listIndex) < listSize()); + HTMLInputElement* input = inputElement(); + if (static_cast<int>(listIndex) == (listSize() - 1)) { + if (fireEvents) { + m_recentSearches.clear(); + const AtomicString& name = autosaveName(); + if (!name.isEmpty()) { + if (!m_searchPopup) + m_searchPopup = document()->page()->chrome()->createSearchPopupMenu(this); + m_searchPopup->saveRecentSearches(name, m_recentSearches); + } + } + } else { + input->setValue(itemText(listIndex)); + if (fireEvents) + input->onSearch(); + input->select(); + } +} + +String RenderSearchField::itemText(unsigned listIndex) const +{ + int size = listSize(); + if (size == 1) { + ASSERT(!listIndex); + return searchMenuNoRecentSearchesText(); + } + if (!listIndex) + return searchMenuRecentSearchesText(); + if (itemIsSeparator(listIndex)) + return String(); + if (static_cast<int>(listIndex) == (size - 1)) + return searchMenuClearRecentSearchesText(); + return m_recentSearches[listIndex - 1]; +} + +String RenderSearchField::itemLabel(unsigned) const +{ + return String(); +} + +String RenderSearchField::itemIcon(unsigned) const +{ + return String(); +} + +bool RenderSearchField::itemIsEnabled(unsigned listIndex) const +{ + if (!listIndex || itemIsSeparator(listIndex)) + return false; + return true; +} + +PopupMenuStyle RenderSearchField::itemStyle(unsigned) const +{ + return menuStyle(); +} + +PopupMenuStyle RenderSearchField::menuStyle() const +{ + return PopupMenuStyle(style()->visitedDependentColor(CSSPropertyColor), style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->font(), style()->visibility() == VISIBLE, + style()->display() == NONE, style()->textIndent(), style()->direction(), isOverride(style()->unicodeBidi())); +} + +int RenderSearchField::clientInsetLeft() const +{ + // Inset the menu by the radius of the cap on the left so that + // it only runs along the straight part of the bezel. + return height() / 2; +} + +int RenderSearchField::clientInsetRight() const +{ + // Inset the menu by the radius of the cap on the right so that + // it only runs along the straight part of the bezel (unless it needs + // to be wider). + return height() / 2; +} + +LayoutUnit RenderSearchField::clientPaddingLeft() const +{ + LayoutUnit padding = paddingLeft(); + if (RenderBox* box = innerBlockElement() ? innerBlockElement()->renderBox() : 0) + padding += box->x(); + return padding; +} + +LayoutUnit RenderSearchField::clientPaddingRight() const +{ + LayoutUnit padding = paddingRight(); + if (RenderBox* containerBox = containerElement() ? containerElement()->renderBox() : 0) { + if (RenderBox* innerBlockBox = innerBlockElement() ? innerBlockElement()->renderBox() : 0) + padding += containerBox->width() - (innerBlockBox->x() + innerBlockBox->width()); + } + return padding; +} + +int RenderSearchField::listSize() const +{ + // If there are no recent searches, then our menu will have 1 "No recent searches" item. + if (!m_recentSearches.size()) + return 1; + // Otherwise, leave room in the menu for a header, a separator, and the "Clear recent searches" item. + return m_recentSearches.size() + 3; +} + +int RenderSearchField::selectedIndex() const +{ + return -1; +} + +void RenderSearchField::popupDidHide() +{ + m_searchPopupIsVisible = false; +} + +bool RenderSearchField::itemIsSeparator(unsigned listIndex) const +{ + // The separator will be the second to last item in our list. + return static_cast<int>(listIndex) == (listSize() - 2); +} + +bool RenderSearchField::itemIsLabel(unsigned listIndex) const +{ + return !listIndex; +} + +bool RenderSearchField::itemIsSelected(unsigned) const +{ + return false; +} + +void RenderSearchField::setTextFromItem(unsigned listIndex) +{ + inputElement()->setValue(itemText(listIndex)); +} + +FontSelector* RenderSearchField::fontSelector() const +{ + return document()->styleResolver()->fontSelector(); +} + +HostWindow* RenderSearchField::hostWindow() const +{ + return document()->view()->hostWindow(); +} + +PassRefPtr<Scrollbar> RenderSearchField::createScrollbar(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, ScrollbarControlSize controlSize) +{ + RefPtr<Scrollbar> widget; + bool hasCustomScrollbarStyle = style()->hasPseudoStyle(SCROLLBAR); + if (hasCustomScrollbarStyle) + widget = RenderScrollbar::createCustomScrollbar(scrollableArea, orientation, this->node()); + else + widget = Scrollbar::createNativeScrollbar(scrollableArea, orientation, controlSize); + return widget.release(); +} + +LayoutUnit RenderSearchField::computeHeightLimit() const +{ + return height(); +} + +void RenderSearchField::centerContainerIfNeeded(RenderBox* containerRenderer) const +{ + if (!containerRenderer) + return; + + if (containerRenderer->height() <= contentHeight()) + return; + + // A quirk for find-in-page box on Safari Windows. + // http://webkit.org/b/63157 + LayoutUnit heightDiff = containerRenderer->height() - contentHeight(); + containerRenderer->setY(containerRenderer->y() - (heightDiff / 2 + layoutMod(heightDiff, 2))); +} + +} diff --git a/Source/WebCore/rendering/RenderSearchField.h b/Source/WebCore/rendering/RenderSearchField.h new file mode 100644 index 000000000..967335d34 --- /dev/null +++ b/Source/WebCore/rendering/RenderSearchField.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * 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 RenderSearchField_h +#define RenderSearchField_h + +#include "PopupMenuClient.h" +#include "RenderTextControlSingleLine.h" + +namespace WebCore { + +class HTMLInputElement; +class SearchPopupMenu; + +class RenderSearchField : public RenderTextControlSingleLine, private PopupMenuClient { +public: + RenderSearchField(Node*); + virtual ~RenderSearchField(); + + void updateCancelButtonVisibility() const; + + void addSearchResult(); + void stopSearchEventTimer(); + + bool popupIsVisible() const { return m_searchPopupIsVisible; } + void showPopup(); + void hidePopup(); + +private: + virtual void centerContainerIfNeeded(RenderBox*) const OVERRIDE; + virtual LayoutUnit computeControlHeight(LayoutUnit lineHeight, LayoutUnit nonContentHeight) const OVERRIDE; + virtual LayoutUnit computeHeightLimit() const OVERRIDE; + virtual void updateFromElement() OVERRIDE; + EVisibility visibilityForCancelButton() const; + const AtomicString& autosaveName() const; + + // PopupMenuClient methods + virtual void valueChanged(unsigned listIndex, bool fireEvents = true) OVERRIDE; + virtual void selectionChanged(unsigned, bool) OVERRIDE { } + virtual void selectionCleared() OVERRIDE { } + virtual String itemText(unsigned listIndex) const OVERRIDE; + virtual String itemLabel(unsigned listIndex) const OVERRIDE; + virtual String itemIcon(unsigned listIndex) const OVERRIDE; + virtual String itemToolTip(unsigned) const OVERRIDE { return String(); } + virtual String itemAccessibilityText(unsigned) const OVERRIDE { return String(); } + virtual bool itemIsEnabled(unsigned listIndex) const OVERRIDE; + virtual PopupMenuStyle itemStyle(unsigned listIndex) const OVERRIDE; + virtual PopupMenuStyle menuStyle() const OVERRIDE; + virtual int clientInsetLeft() const OVERRIDE; + virtual int clientInsetRight() const OVERRIDE; + virtual LayoutUnit clientPaddingLeft() const OVERRIDE; + virtual LayoutUnit clientPaddingRight() const OVERRIDE; + virtual int listSize() const OVERRIDE; + virtual int selectedIndex() const OVERRIDE; + virtual void popupDidHide() OVERRIDE; + virtual bool itemIsSeparator(unsigned listIndex) const OVERRIDE; + virtual bool itemIsLabel(unsigned listIndex) const OVERRIDE; + virtual bool itemIsSelected(unsigned listIndex) const OVERRIDE; + virtual bool shouldPopOver() const OVERRIDE { return false; } + virtual bool valueShouldChangeOnHotTrack() const OVERRIDE { return false; } + virtual void setTextFromItem(unsigned listIndex) OVERRIDE; + virtual FontSelector* fontSelector() const OVERRIDE; + virtual HostWindow* hostWindow() const OVERRIDE; + virtual PassRefPtr<Scrollbar> createScrollbar(ScrollableArea*, ScrollbarOrientation, ScrollbarControlSize) OVERRIDE; + + HTMLElement* resultsButtonElement() const; + HTMLElement* cancelButtonElement() const; + + bool m_searchPopupIsVisible; + RefPtr<SearchPopupMenu> m_searchPopup; + Vector<String> m_recentSearches; +}; + +inline RenderSearchField* toRenderSearchField(RenderObject* object) +{ + ASSERT(!object || object->isTextField()); + return static_cast<RenderSearchField*>(object); +} + +// This will catch anyone doing an unnecessary cast. +void toRenderSearchField(const RenderSearchField*); + +} + +#endif diff --git a/Source/WebCore/rendering/RenderTable.cpp b/Source/WebCore/rendering/RenderTable.cpp index 541ef37b5..479e3d6ee 100644 --- a/Source/WebCore/rendering/RenderTable.cpp +++ b/Source/WebCore/rendering/RenderTable.cpp @@ -592,11 +592,10 @@ void RenderTable::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffs size_t count = m_collapsedBorders.size(); for (size_t i = 0; i < count; ++i) { m_currentBorder = &m_collapsedBorders[i]; - for (RenderObject* child = firstChild(); child; child = child->nextSibling()) - if (child->isTableSection()) { - LayoutPoint childPoint = flipForWritingModeForChild(toRenderTableSection(child), paintOffset); - child->paint(info, childPoint); - } + for (RenderTableSection* section = bottomSection(); section; section = sectionAbove(section)) { + LayoutPoint childPoint = flipForWritingModeForChild(section, paintOffset); + section->paint(info, childPoint); + } } m_currentBorder = 0; } @@ -842,113 +841,116 @@ void RenderTable::recalcSections() const int RenderTable::calcBorderStart() const { - if (collapseBorders()) { - // Determined by the first cell of the first row. See the CSS 2.1 spec, section 17.6.2. - if (!numEffCols()) - return 0; + if (!collapseBorders()) + return RenderBlock::borderStart(); + + // Determined by the first cell of the first row. See the CSS 2.1 spec, section 17.6.2. + if (!numEffCols()) + return 0; - unsigned borderWidth = 0; + unsigned borderWidth = 0; - const BorderValue& tb = style()->borderStart(); - if (tb.style() == BHIDDEN) + const BorderValue& tableStartBorder = style()->borderStart(); + if (tableStartBorder.style() == BHIDDEN) + return 0; + if (tableStartBorder.style() > BHIDDEN) + borderWidth = tableStartBorder.width(); + + if (RenderTableCol* column = colElement(0)) { + // FIXME: We don't account for direction on columns and column groups. + const BorderValue& columnAdjoiningBorder = column->style()->borderStart(); + if (columnAdjoiningBorder.style() == BHIDDEN) return 0; - if (tb.style() > BHIDDEN) - borderWidth = tb.width(); + if (columnAdjoiningBorder.style() > BHIDDEN) + borderWidth = max(borderWidth, columnAdjoiningBorder.width()); + // FIXME: This logic doesn't properly account for the first column in the first column-group case. + } - if (RenderTableCol* colGroup = colElement(0)) { - const BorderValue& gb = colGroup->style()->borderStart(); - if (gb.style() == BHIDDEN) - return 0; - if (gb.style() > BHIDDEN) - borderWidth = max(borderWidth, gb.width()); - } - - if (const RenderTableSection* topNonEmptySection = this->topNonEmptySection()) { - const BorderValue& sb = topNonEmptySection->style()->borderStart(); - if (sb.style() == BHIDDEN) - return 0; + if (const RenderTableSection* topNonEmptySection = this->topNonEmptySection()) { + const BorderValue& sectionAdjoiningBorder = topNonEmptySection->borderAdjoiningTableStart(); + if (sectionAdjoiningBorder.style() == BHIDDEN) + return 0; - if (sb.style() > BHIDDEN) - borderWidth = max(borderWidth, sb.width()); + if (sectionAdjoiningBorder.style() > BHIDDEN) + borderWidth = max(borderWidth, sectionAdjoiningBorder.width()); - const RenderTableSection::CellStruct& cs = topNonEmptySection->cellAt(0, 0); - - if (cs.hasCells()) { - const BorderValue& cb = cs.primaryCell()->style()->borderStart(); // FIXME: Make this work with perpendicualr and flipped cells. - if (cb.style() == BHIDDEN) - return 0; + if (const RenderTableCell* adjoiningStartCell = topNonEmptySection->firstRowCellAdjoiningTableStart()) { + // FIXME: Make this work with perpendicular and flipped cells. + const BorderValue& startCellAdjoiningBorder = adjoiningStartCell->borderAdjoiningTableStart(); + if (startCellAdjoiningBorder.style() == BHIDDEN) + return 0; - const BorderValue& rb = cs.primaryCell()->parent()->style()->borderStart(); - if (rb.style() == BHIDDEN) - return 0; + const BorderValue& firstRowAdjoiningBorder = adjoiningStartCell->row()->borderAdjoiningTableStart(); + if (firstRowAdjoiningBorder.style() == BHIDDEN) + return 0; - if (cb.style() > BHIDDEN) - borderWidth = max(borderWidth, cb.width()); - if (rb.style() > BHIDDEN) - borderWidth = max(borderWidth, rb.width()); - } + if (startCellAdjoiningBorder.style() > BHIDDEN) + borderWidth = max(borderWidth, startCellAdjoiningBorder.width()); + if (firstRowAdjoiningBorder.style() > BHIDDEN) + borderWidth = max(borderWidth, firstRowAdjoiningBorder.width()); } - return (borderWidth + (style()->isLeftToRightDirection() ? 0 : 1)) / 2; } - return RenderBlock::borderStart(); + return (borderWidth + (style()->isLeftToRightDirection() ? 0 : 1)) / 2; } int RenderTable::calcBorderEnd() const { - if (collapseBorders()) { - // Determined by the last cell of the first row. See the CSS 2.1 spec, section 17.6.2. - if (!numEffCols()) - return 0; + if (!collapseBorders()) + return RenderBlock::borderEnd(); - unsigned borderWidth = 0; + // Determined by the last cell of the first row. See the CSS 2.1 spec, section 17.6.2. + if (!numEffCols()) + return 0; - const BorderValue& tb = style()->borderEnd(); - if (tb.style() == BHIDDEN) - return 0; - if (tb.style() > BHIDDEN) - borderWidth = tb.width(); + unsigned borderWidth = 0; - unsigned endColumn = numEffCols() - 1; - if (RenderTableCol* colGroup = colElement(endColumn)) { - const BorderValue& gb = colGroup->style()->borderEnd(); - if (gb.style() == BHIDDEN) - return 0; - if (gb.style() > BHIDDEN) - borderWidth = max(borderWidth, gb.width()); - } + const BorderValue& tableEndBorder = style()->borderEnd(); + if (tableEndBorder.style() == BHIDDEN) + return 0; + if (tableEndBorder.style() > BHIDDEN) + borderWidth = tableEndBorder.width(); + + unsigned endColumn = numEffCols() - 1; + if (RenderTableCol* column = colElement(endColumn)) { + // FIXME: We don't account for direction on columns and column groups. + const BorderValue& columnAdjoiningBorder = column->style()->borderEnd(); + if (columnAdjoiningBorder.style() == BHIDDEN) + return 0; + if (columnAdjoiningBorder.style() > BHIDDEN) + borderWidth = max(borderWidth, columnAdjoiningBorder.width()); + // FIXME: This logic doesn't properly account for the last column in the last column-group case. + } - if (const RenderTableSection* topNonEmptySection = this->topNonEmptySection()) { - const BorderValue& sb = topNonEmptySection->style()->borderEnd(); - if (sb.style() == BHIDDEN) - return 0; + if (const RenderTableSection* topNonEmptySection = this->topNonEmptySection()) { + const BorderValue& sectionAdjoiningBorder = topNonEmptySection->borderAdjoiningTableEnd(); + if (sectionAdjoiningBorder.style() == BHIDDEN) + return 0; - if (sb.style() > BHIDDEN) - borderWidth = max(borderWidth, sb.width()); + if (sectionAdjoiningBorder.style() > BHIDDEN) + borderWidth = max(borderWidth, sectionAdjoiningBorder.width()); - const RenderTableSection::CellStruct& cs = topNonEmptySection->cellAt(0, endColumn); - - if (cs.hasCells()) { - const BorderValue& cb = cs.primaryCell()->style()->borderEnd(); // FIXME: Make this work with perpendicular and flipped cells. - if (cb.style() == BHIDDEN) - return 0; + if (const RenderTableCell* adjoiningEndCell = topNonEmptySection->firstRowCellAdjoiningTableEnd()) { + // FIXME: Make this work with perpendicular and flipped cells. + const BorderValue& endCellAdjoiningBorder = adjoiningEndCell->borderAdjoiningTableEnd(); + if (endCellAdjoiningBorder.style() == BHIDDEN) + return 0; - const BorderValue& rb = cs.primaryCell()->parent()->style()->borderEnd(); - if (rb.style() == BHIDDEN) - return 0; + const BorderValue& firstRowAdjoiningBorder = adjoiningEndCell->row()->borderAdjoiningTableEnd(); + if (firstRowAdjoiningBorder.style() == BHIDDEN) + return 0; - if (cb.style() > BHIDDEN) - borderWidth = max(borderWidth, cb.width()); - if (rb.style() > BHIDDEN) - borderWidth = max(borderWidth, rb.width()); - } + if (endCellAdjoiningBorder.style() > BHIDDEN) + borderWidth = max(borderWidth, endCellAdjoiningBorder.width()); + if (firstRowAdjoiningBorder.style() > BHIDDEN) + borderWidth = max(borderWidth, firstRowAdjoiningBorder.width()); } - return (borderWidth + (style()->isLeftToRightDirection() ? 1 : 0)) / 2; } - return RenderBlock::borderEnd(); + return (borderWidth + (style()->isLeftToRightDirection() ? 1 : 0)) / 2; } void RenderTable::recalcBordersInRowDirection() { + // FIXME: We need to compute the collapsed before / after borders in the same fashion. m_borderStart = calcBorderStart(); m_borderEnd = calcBorderEnd(); } @@ -1109,6 +1111,21 @@ RenderTableSection* RenderTable::sectionBelow(const RenderTableSection* section, return toRenderTableSection(nextSection); } +RenderTableSection* RenderTable::bottomSection() const +{ + recalcSectionsIfNeeded(); + + if (m_foot) + return m_foot; + + for (RenderObject* child = lastChild(); child; child = child->previousSibling()) { + if (child->isTableSection()) + return toRenderTableSection(child); + } + + return 0; +} + RenderTableCell* RenderTable::cellAbove(const RenderTableCell* cell) const { recalcSectionsIfNeeded(); @@ -1294,4 +1311,22 @@ RenderTable* RenderTable::createAnonymousWithParentRenderer(const RenderObject* return newTable; } +const BorderValue& RenderTable::tableStartBorderAdjoiningCell(const RenderTableCell* cell) const +{ + ASSERT(cell->isFirstOrLastCellInRow()); + if (cell->section()->hasSameDirectionAsTable()) + return style()->borderStart(); + + return style()->borderEnd(); +} + +const BorderValue& RenderTable::tableEndBorderAdjoiningCell(const RenderTableCell* cell) const +{ + ASSERT(cell->isFirstOrLastCellInRow()); + if (cell->section()->hasSameDirectionAsTable()) + return style()->borderEnd(); + + return style()->borderStart(); +} + } diff --git a/Source/WebCore/rendering/RenderTable.h b/Source/WebCore/rendering/RenderTable.h index 7d3049b7a..c3eb0729b 100644 --- a/Source/WebCore/rendering/RenderTable.h +++ b/Source/WebCore/rendering/RenderTable.h @@ -143,10 +143,13 @@ public: // This function returns 0 if the table has no section. RenderTableSection* topSection() const; + RenderTableSection* bottomSection() const; // This function returns 0 if the table has no non-empty sections. RenderTableSection* topNonEmptySection() const; + unsigned lastColumnIndex() const { return numEffCols() - 1; } + void splitColumn(unsigned position, unsigned firstSpan); void appendColumn(unsigned span); unsigned numEffCols() const { return m_columns.size(); } @@ -219,6 +222,9 @@ public: return createAnonymousWithParentRenderer(parent); } + const BorderValue& tableStartBorderAdjoiningCell(const RenderTableCell*) const; + const BorderValue& tableEndBorderAdjoiningCell(const RenderTableCell*) const; + protected: virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); diff --git a/Source/WebCore/rendering/RenderTableCell.cpp b/Source/WebCore/rendering/RenderTableCell.cpp index 950acb4b1..159b54b3b 100644 --- a/Source/WebCore/rendering/RenderTableCell.cpp +++ b/Source/WebCore/rendering/RenderTableCell.cpp @@ -193,7 +193,7 @@ void RenderTableCell::layout() LayoutUnit RenderTableCell::paddingTop() const { - LayoutUnit result = computedCSSPaddingTop(); + int result = computedCSSPaddingTop(); if (!isHorizontalWritingMode()) return result; return result + (style()->writingMode() == TopToBottomWritingMode ? intrinsicPaddingBefore() : intrinsicPaddingAfter()); @@ -201,7 +201,7 @@ LayoutUnit RenderTableCell::paddingTop() const LayoutUnit RenderTableCell::paddingBottom() const { - LayoutUnit result = computedCSSPaddingBottom(); + int result = computedCSSPaddingBottom(); if (!isHorizontalWritingMode()) return result; return result + (style()->writingMode() == TopToBottomWritingMode ? intrinsicPaddingAfter() : intrinsicPaddingBefore()); @@ -209,16 +209,15 @@ LayoutUnit RenderTableCell::paddingBottom() const LayoutUnit RenderTableCell::paddingLeft() const { - LayoutUnit result = computedCSSPaddingLeft(); + int result = computedCSSPaddingLeft(); if (isHorizontalWritingMode()) return result; return result + (style()->writingMode() == LeftToRightWritingMode ? intrinsicPaddingBefore() : intrinsicPaddingAfter()); - } LayoutUnit RenderTableCell::paddingRight() const { - LayoutUnit result = computedCSSPaddingRight(); + int result = computedCSSPaddingRight(); if (isHorizontalWritingMode()) return result; return result + (style()->writingMode() == LeftToRightWritingMode ? intrinsicPaddingAfter() : intrinsicPaddingBefore()); @@ -226,18 +225,18 @@ LayoutUnit RenderTableCell::paddingRight() const LayoutUnit RenderTableCell::paddingBefore() const { - return computedCSSPaddingBefore() + intrinsicPaddingBefore(); + return static_cast<int>(computedCSSPaddingBefore()) + intrinsicPaddingBefore(); } LayoutUnit RenderTableCell::paddingAfter() const { - return computedCSSPaddingAfter() + intrinsicPaddingAfter(); + return static_cast<int>(computedCSSPaddingAfter()) + intrinsicPaddingAfter(); } -void RenderTableCell::setOverrideHeightFromRowHeight(LayoutUnit rowHeight) +void RenderTableCell::setOverrideLogicalContentHeightFromRowHeight(LayoutUnit rowHeight) { clearIntrinsicPadding(); - RenderBlock::setOverrideHeight(max<LayoutUnit>(0, rowHeight - borderBefore() - paddingBefore() - borderAfter() - paddingAfter())); + setOverrideLogicalContentHeight(max<LayoutUnit>(0, rowHeight - borderAndPaddingLogicalHeight())); } LayoutSize RenderTableCell::offsetFromContainer(RenderObject* o, const LayoutPoint& point, bool* offsetDependsOnPoint) const @@ -468,7 +467,7 @@ CollapsedBorderValue RenderTableCell::computeCollapsedStartBorder(IncludeBorderC } } else { // (7) The table's start border. - result = chooseBorder(result, CollapsedBorderValue(table->style()->borderStart(), includeColor ? table->style()->visitedDependentColor(startColorProperty) : Color(), BTABLE)); + result = chooseBorder(result, CollapsedBorderValue(table->tableStartBorderAdjoiningCell(this), includeColor ? table->style()->visitedDependentColor(startColorProperty) : Color(), BTABLE)); if (!result.exists()) return result; } @@ -542,7 +541,7 @@ CollapsedBorderValue RenderTableCell::computeCollapsedEndBorder(IncludeBorderCol } } else { // (7) The table's end border. - result = chooseBorder(result, CollapsedBorderValue(table->style()->borderEnd(), includeColor ? table->style()->visitedDependentColor(endColorProperty) : Color(), BTABLE)); + result = chooseBorder(result, CollapsedBorderValue(table->tableEndBorderAdjoiningCell(this), includeColor ? table->style()->visitedDependentColor(endColorProperty) : Color(), BTABLE)); if (!result.exists()) return result; } diff --git a/Source/WebCore/rendering/RenderTableCell.h b/Source/WebCore/rendering/RenderTableCell.h index d1b0a28a3..4381555cd 100644 --- a/Source/WebCore/rendering/RenderTableCell.h +++ b/Source/WebCore/rendering/RenderTableCell.h @@ -122,7 +122,7 @@ public: virtual LayoutUnit paddingBefore() const OVERRIDE; virtual LayoutUnit paddingAfter() const OVERRIDE; - void setOverrideHeightFromRowHeight(LayoutUnit); + void setOverrideLogicalContentHeightFromRowHeight(LayoutUnit); virtual void scrollbarsChanged(bool horizontalScrollbarChanged, bool verticalScrollbarChanged); @@ -142,9 +142,33 @@ public: // on all table parts and writing-mode on cells. const RenderStyle* styleForCellFlow() const { - return table()->style(); + return section()->style(); } + const BorderValue& borderAdjoiningTableStart() const + { + ASSERT(isFirstOrLastCellInRow()); + if (section()->hasSameDirectionAsTable()) + return style()->borderStart(); + + return style()->borderEnd(); + } + + const BorderValue& borderAdjoiningTableEnd() const + { + ASSERT(isFirstOrLastCellInRow()); + if (section()->hasSameDirectionAsTable()) + return style()->borderEnd(); + + return style()->borderStart(); + } + +#ifndef NDEBUG + bool isFirstOrLastCellInRow() const + { + return !table()->cellAfter(this) || !table()->cellBefore(this); + } +#endif protected: virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); diff --git a/Source/WebCore/rendering/RenderTableRow.h b/Source/WebCore/rendering/RenderTableRow.h index 04696607d..c01cd45ed 100644 --- a/Source/WebCore/rendering/RenderTableRow.h +++ b/Source/WebCore/rendering/RenderTableRow.h @@ -66,6 +66,22 @@ public: return m_rowIndex; } + const BorderValue& borderAdjoiningTableStart() const + { + if (section()->hasSameDirectionAsTable()) + return style()->borderStart(); + + return style()->borderEnd(); + } + + const BorderValue& borderAdjoiningTableEnd() const + { + if (section()->hasSameDirectionAsTable()) + return style()->borderEnd(); + + return style()->borderStart(); + } + private: virtual RenderObjectChildList* virtualChildren() { return children(); } virtual const RenderObjectChildList* virtualChildren() const { return children(); } diff --git a/Source/WebCore/rendering/RenderTableSection.cpp b/Source/WebCore/rendering/RenderTableSection.cpp index 173085c25..d78a3d6f4 100644 --- a/Source/WebCore/rendering/RenderTableSection.cpp +++ b/Source/WebCore/rendering/RenderTableSection.cpp @@ -333,7 +333,7 @@ int RenderTableSection::calcRowLogicalHeight() LayoutUnit baselineDescent = 0; // Our base size is the biggest logical height from our cells' styles (excluding row spanning cells). - m_rowPos[r + 1] = max(m_rowPos[r] + minimumIntValueForLength(m_grid[r].logicalHeight, 0, viewRenderer), 0); + m_rowPos[r + 1] = max(m_rowPos[r] + minimumValueForLength(m_grid[r].logicalHeight, 0, viewRenderer).round(), 0); Row& row = m_grid[r].row; unsigned totalCols = row.size(); @@ -373,7 +373,7 @@ int RenderTableSection::calcRowLogicalHeight() if (va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP || va == SUPER || va == SUB || va == LENGTH) { LayoutUnit baselinePosition = cell->cellBaselinePosition(); if (baselinePosition > cell->borderBefore() + cell->paddingBefore()) { - m_grid[r].baseline = max(m_grid[r].baseline, baselinePosition - cell->intrinsicPaddingBefore()); + m_grid[cellStartRow].baseline = max(m_grid[cellStartRow].baseline, baselinePosition - cell->intrinsicPaddingBefore()); baselineDescent = max(baselineDescent, m_rowPos[cellStartRow] + cellLogicalHeight - (baselinePosition - cell->intrinsicPaddingBefore())); } } @@ -406,6 +406,10 @@ void RenderTableSection::layout() ASSERT(!needsCellRecalc()); ASSERT(!table()->needsSectionRecalc()); + // addChild may over-grow m_grid but we don't want to throw away the memory too early as addChild + // can be called in a loop (e.g during parsing). Doing it now ensures we have a stable-enough structure. + m_grid.shrinkToFit(); + LayoutStateMaintainer statePusher(view(), this, locationOffset(), style()->isFlippedBlocksWritingMode()); for (RenderObject* child = children()->firstChild(); child; child = child->nextSibling()) { if (child->isTableRow()) { @@ -529,7 +533,6 @@ void RenderTableSection::layoutRows() m_overflowingCells.clear(); m_forceSlowPaintPathWithOverflowingCell = false; - int hspacing = table()->hBorderSpacing(); int vspacing = table()->vBorderSpacing(); unsigned nEffCols = table()->numEffCols(); @@ -606,7 +609,7 @@ void RenderTableSection::layoutRows() // Alignment within a cell is based off the calculated // height, which becomes irrelevant once the cell has // been resized based off its percentage. - cell->setOverrideHeightFromRowHeight(rHeight); + cell->setOverrideLogicalContentHeightFromRowHeight(rHeight); cell->layoutIfNeeded(); // If the baseline moved, we may have to update the data for our row. Find out the new baseline. @@ -630,9 +633,9 @@ void RenderTableSection::layoutRows() case TEXT_BOTTOM: case LENGTH: case BASELINE: { - LayoutUnit b = cell->cellBaselinePosition(); - if (b > cell->borderBefore() + cell->paddingBefore()) - intrinsicPaddingBefore = getBaseline(r) - (b - oldIntrinsicPaddingBefore); + LayoutUnit baseline = cell->cellBaselinePosition(); + if (baseline > cell->borderBefore() + cell->paddingBefore()) + intrinsicPaddingBefore = getBaseline(cell->rowIndex()) - (baseline - oldIntrinsicPaddingBefore); break; } case TOP: @@ -653,14 +656,7 @@ void RenderTableSection::layoutRows() LayoutRect oldCellRect(cell->x(), cell->y() , cell->width(), cell->height()); - LayoutPoint cellLocation(0, m_rowPos[rindx]); - // FIXME: Switch to cell's styleForCellFlow() for consistency with RenderTableCell, once it supports row group. - if (!style()->isLeftToRightDirection()) - cellLocation.setX(table()->columnPositions()[nEffCols] - table()->columnPositions()[table()->colToEffCol(cell->col() + cell->colSpan())] + hspacing); - else - cellLocation.setX(table()->columnPositions()[c] + hspacing); - cell->setLogicalLocation(cellLocation); - view()->addLayoutDelta(oldCellRect.location() - cell->location()); + setLogicalPositionForCell(cell, c); if (intrinsicPaddingBefore != oldIntrinsicPaddingBefore || intrinsicPaddingAfter != oldIntrinsicPaddingAfter) cell->setNeedsLayout(true, MarkOnlyThis); @@ -1034,77 +1030,120 @@ void RenderTableSection::paintCell(RenderTableCell* cell, PaintInfo& paintInfo, cell->paint(paintInfo, cellPoint); } +LayoutRect RenderTableSection::logicalRectForWritingModeAndDirection(const LayoutRect& rect) const +{ + LayoutRect tableAlignedRect(rect); + + flipForWritingMode(tableAlignedRect); + + if (!style()->isHorizontalWritingMode()) + tableAlignedRect = tableAlignedRect.transposedRect(); + + const Vector<int>& columnPos = table()->columnPositions(); + if (!style()->isLeftToRightDirection()) + tableAlignedRect.setX(columnPos[columnPos.size() - 1] - tableAlignedRect.maxX()); + + return tableAlignedRect; +} + CellSpan RenderTableSection::dirtiedRows(const LayoutRect& damageRect) const { if (m_forceSlowPaintPathWithOverflowingCell) return fullTableRowSpan(); - LayoutUnit before = style()->isHorizontalWritingMode() ? damageRect.y() : damageRect.x(); + CellSpan coveredRows = spannedRows(damageRect); - // binary search to find a row - unsigned startRow = std::lower_bound(m_rowPos.begin(), m_rowPos.end(), before) - m_rowPos.begin(); + // To repaint the border we might need to repaint first or last row even if they are not spanned themselves. + if (coveredRows.start() >= m_rowPos.size() - 1 && m_rowPos[m_rowPos.size() - 1] + table()->outerBorderAfter() >= damageRect.y()) + --coveredRows.start(); - // The binary search above gives us the first row with - // a y position >= the top of the paint rect. Thus, the previous - // may need to be repainted as well. - if (startRow == m_rowPos.size() || (startRow > 0 && (m_rowPos[startRow] > before))) - --startRow; + if (!coveredRows.end() && m_rowPos[0] - table()->outerBorderBefore() <= damageRect.maxY()) + ++coveredRows.end(); - LayoutUnit after = (style()->isHorizontalWritingMode() ? damageRect.maxY() : damageRect.maxX()); - unsigned endRow = std::lower_bound(m_rowPos.begin(), m_rowPos.end(), after) - m_rowPos.begin(); - if (endRow == m_rowPos.size()) - --endRow; - - if (!endRow && m_rowPos[0] - table()->outerBorderBefore() <= after) - ++endRow; - - return CellSpan(startRow, endRow); + return coveredRows; } - CellSpan RenderTableSection::dirtiedColumns(const LayoutRect& damageRect) const { if (m_forceSlowPaintPathWithOverflowingCell) return fullTableColumnSpan(); - // FIXME: Implement RTL. - if (!style()->isLeftToRightDirection()) - return fullTableColumnSpan(); + CellSpan coveredColumns = spannedColumns(damageRect); - LayoutUnit start = style()->isHorizontalWritingMode() ? damageRect.x() : damageRect.y(); Vector<int>& columnPos = table()->columnPositions(); - unsigned startCol = std::lower_bound(columnPos.begin(), columnPos.end(), start) - columnPos.begin(); - if ((startCol == columnPos.size()) || (startCol > 0 && (columnPos[startCol] > start))) - --startCol; + // To repaint the border we might need to repaint first or last column even if they are not spanned themselves. + if (coveredColumns.start() >= columnPos.size() - 1 && columnPos[columnPos.size() - 1] + table()->outerBorderEnd() >= damageRect.x()) + --coveredColumns.start(); + + if (!coveredColumns.end() && columnPos[0] - table()->outerBorderStart() <= damageRect.maxX()) + ++coveredColumns.end(); + + return coveredColumns; +} - LayoutUnit end = (style()->isHorizontalWritingMode() ? damageRect.maxX() : damageRect.maxY()); - unsigned endCol = std::lower_bound(columnPos.begin(), columnPos.end(), end) - columnPos.begin(); - if (endCol == columnPos.size()) - --endCol; +CellSpan RenderTableSection::spannedRows(const LayoutRect& flippedRect) const +{ + // Find the first row that starts after rect top. + // FIXME: Upper_bound might not be the correct algorithm here since it might skip empty rows, but it is + // consistent with behavior in the former point based hit-testing (but inconsistent with spannedColumns). + unsigned nextRow = std::upper_bound(m_rowPos.begin(), m_rowPos.end(), flippedRect.y()) - m_rowPos.begin(); + + if (nextRow == m_rowPos.size()) + return CellSpan(m_rowPos.size() - 1, m_rowPos.size() - 1); // After all rows. + + unsigned startRow = nextRow > 0 ? nextRow - 1 : 0; + + // Find the first row that starts after rect bottom. + unsigned endRow; + if (m_rowPos[nextRow] >= flippedRect.maxY()) + endRow = nextRow; + else { + endRow = std::upper_bound(m_rowPos.begin() + nextRow, m_rowPos.end(), flippedRect.maxY()) - m_rowPos.begin(); + if (endRow == m_rowPos.size()) + endRow = m_rowPos.size() - 1; + } - if (!endCol && columnPos[0] - table()->outerBorderStart() <= end) - ++endCol; + return CellSpan(startRow, endRow); +} + +CellSpan RenderTableSection::spannedColumns(const LayoutRect& flippedRect) const +{ + const Vector<int>& columnPos = table()->columnPositions(); + + // Find the first columnt that starts after rect left. + unsigned nextColumn = std::lower_bound(columnPos.begin(), columnPos.end(), flippedRect.x()) - columnPos.begin(); + + if (nextColumn == columnPos.size()) + return CellSpan(columnPos.size() - 1, columnPos.size() - 1); // After all columns. + + unsigned startColumn = nextColumn > 0 ? nextColumn - 1 : 0; + + // Find the first row that starts after rect right. + unsigned endColumn; + if (columnPos[nextColumn] >= flippedRect.maxX()) + endColumn = nextColumn; + else { + endColumn = std::lower_bound(columnPos.begin() + nextColumn, columnPos.end(), flippedRect.maxX()) - columnPos.begin(); + if (endColumn == columnPos.size()) + endColumn = columnPos.size() - 1; + } - return CellSpan(startCol, endCol); + return CellSpan(startColumn, endColumn); } + void RenderTableSection::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { PaintPhase paintPhase = paintInfo.phase; LayoutRect localRepaintRect = paintInfo.rect; localRepaintRect.moveBy(-paintOffset); - if (style()->isFlippedBlocksWritingMode()) { - if (style()->isHorizontalWritingMode()) - localRepaintRect.setY(height() - localRepaintRect.maxY()); - else - localRepaintRect.setX(width() - localRepaintRect.maxX()); - } - localRepaintRect.inflate(maximalOutlineSize(paintPhase)); - CellSpan dirtiedRows = this->dirtiedRows(localRepaintRect); - CellSpan dirtiedColumns = this->dirtiedColumns(localRepaintRect); + LayoutRect tableAlignedRect = logicalRectForWritingModeAndDirection(localRepaintRect); + + CellSpan dirtiedRows = this->dirtiedRows(tableAlignedRect); + CellSpan dirtiedColumns = this->dirtiedColumns(tableAlignedRect); if (dirtiedColumns.start() < dirtiedColumns.end()) { if (!m_hasMultipleCellLevels && !m_overflowingCells.size()) { @@ -1276,6 +1315,18 @@ unsigned RenderTableSection::numColumns() const return result + 1; } +const RenderTableCell* RenderTableSection::firstRowCellAdjoiningTableStart() const +{ + unsigned adjoiningStartCellColumnIndex = hasSameDirectionAsTable() ? 0 : table()->lastColumnIndex(); + return cellAt(0, adjoiningStartCellColumnIndex).primaryCell(); +} + +const RenderTableCell* RenderTableSection::firstRowCellAdjoiningTableEnd() const +{ + unsigned adjoiningEndCellColumnIndex = hasSameDirectionAsTable() ? table()->lastColumnIndex() : 0; + return cellAt(0, adjoiningEndCellColumnIndex).primaryCell(); +} + void RenderTableSection::appendColumn(unsigned pos) { ASSERT(!m_needsCellRecalc); @@ -1340,52 +1391,41 @@ bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResul return false; } - LayoutPoint location = pointInContainer - toLayoutSize(adjustedLocation); - if (style()->isFlippedBlocksWritingMode()) { - if (style()->isHorizontalWritingMode()) - location.setY(height() - location.y()); - else - location.setX(width() - location.x()); - } - - LayoutUnit offsetInColumnDirection = style()->isHorizontalWritingMode() ? location.y() : location.x(); - recalcCellsIfNeeded(); - // Find the first row that starts after offsetInColumnDirection. - unsigned nextRow = std::upper_bound(m_rowPos.begin(), m_rowPos.end(), offsetInColumnDirection) - m_rowPos.begin(); - if (nextRow == m_rowPos.size()) - return false; - // Now set hitRow to the index of the hit row, or 0. - unsigned hitRow = nextRow > 0 ? nextRow - 1 : 0; - - Vector<int>& columnPos = table()->columnPositions(); - LayoutUnit offsetInRowDirection = style()->isHorizontalWritingMode() ? location.x() : location.y(); - if (!style()->isLeftToRightDirection()) - offsetInRowDirection = columnPos[columnPos.size() - 1] - offsetInRowDirection; + LayoutRect hitTestRect = result.rectForPoint(pointInContainer); + hitTestRect.moveBy(-adjustedLocation); - unsigned nextColumn = std::lower_bound(columnPos.begin(), columnPos.end(), offsetInRowDirection) - columnPos.begin(); - if (nextColumn == columnPos.size()) - return false; - unsigned hitColumn = nextColumn > 0 ? nextColumn - 1 : 0; + LayoutRect tableAlignedRect = logicalRectForWritingModeAndDirection(hitTestRect); + CellSpan rowSpan = spannedRows(tableAlignedRect); + CellSpan columnSpan = spannedColumns(tableAlignedRect); - CellStruct& current = cellAt(hitRow, hitColumn); + // Now iterate over the spanned rows and columns. + for (unsigned hitRow = rowSpan.start(); hitRow < rowSpan.end(); ++hitRow) { + for (unsigned hitColumn = columnSpan.start(); hitColumn < columnSpan.end(); ++hitColumn) { + CellStruct& current = cellAt(hitRow, hitColumn); - // If the cell is empty, there's nothing to do - if (!current.hasCells()) - return false; + // If the cell is empty, there's nothing to do + if (!current.hasCells()) + continue; - for (unsigned i = current.cells.size() ; i; ) { - --i; - RenderTableCell* cell = current.cells[i]; - LayoutPoint cellPoint = flipForWritingModeForChild(cell, adjustedLocation); - if (static_cast<RenderObject*>(cell)->nodeAtPoint(request, result, pointInContainer, cellPoint, action)) { - updateHitTestResult(result, toLayoutPoint(pointInContainer - cellPoint)); - return true; + for (unsigned i = current.cells.size() ; i; ) { + --i; + RenderTableCell* cell = current.cells[i]; + LayoutPoint cellPoint = flipForWritingModeForChild(cell, adjustedLocation); + if (static_cast<RenderObject*>(cell)->nodeAtPoint(request, result, pointInContainer, cellPoint, action)) { + updateHitTestResult(result, toLayoutPoint(pointInContainer - cellPoint)); + return true; + } + } + if (!result.isRectBasedTest()) + break; } + if (!result.isRectBasedTest()) + break; } - return false; + return false; } void RenderTableSection::removeCachedCollapsedBorders(const RenderTableCell* cell) @@ -1419,4 +1459,20 @@ RenderTableSection* RenderTableSection::createAnonymousWithParentRenderer(const return newSection; } +void RenderTableSection::setLogicalPositionForCell(RenderTableCell* cell, unsigned effectiveColumn) const +{ + LayoutPoint oldCellLocation(cell->x(), cell->y()); + + LayoutPoint cellLocation(0, m_rowPos[cell->rowIndex()]); + int horizontalBorderSpacing = table()->hBorderSpacing(); + + if (!cell->styleForCellFlow()->isLeftToRightDirection()) + cellLocation.setX(table()->columnPositions()[table()->numEffCols()] - table()->columnPositions()[table()->colToEffCol(cell->col() + cell->colSpan())] + horizontalBorderSpacing); + else + cellLocation.setX(table()->columnPositions()[effectiveColumn] + horizontalBorderSpacing); + + cell->setLogicalLocation(cellLocation); + view()->addLayoutDelta(oldCellLocation - cell->location()); +} + } // namespace WebCore diff --git a/Source/WebCore/rendering/RenderTableSection.h b/Source/WebCore/rendering/RenderTableSection.h index dcdc13490..289415306 100644 --- a/Source/WebCore/rendering/RenderTableSection.h +++ b/Source/WebCore/rendering/RenderTableSection.h @@ -49,6 +49,9 @@ public: unsigned start() const { return m_start; } unsigned end() const { return m_end; } + unsigned& start() { return m_start; } + unsigned& end() { return m_end; } + private: unsigned m_start; unsigned m_end; @@ -114,6 +117,30 @@ public: Length logicalHeight; }; + bool hasSameDirectionAsTable() const + { + return table()->style()->direction() == style()->direction(); + } + + const BorderValue& borderAdjoiningTableStart() const + { + if (hasSameDirectionAsTable()) + return style()->borderStart(); + + return style()->borderEnd(); + } + + const BorderValue& borderAdjoiningTableEnd() const + { + if (hasSameDirectionAsTable()) + return style()->borderEnd(); + + return style()->borderStart(); + } + + const RenderTableCell* firstRowCellAdjoiningTableStart() const; + const RenderTableCell* firstRowCellAdjoiningTableEnd() const; + CellStruct& cellAt(unsigned row, unsigned col) { return m_grid[row].row[col]; } const CellStruct& cellAt(unsigned row, unsigned col) const { return m_grid[row].row[col]; } RenderTableCell* primaryCellAt(unsigned row, unsigned col) @@ -165,6 +192,8 @@ public: { return createAnonymousWithParentRenderer(parent); } + + virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE; protected: virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); @@ -183,7 +212,6 @@ private: virtual void removeChild(RenderObject* oldChild); - virtual void paint(PaintInfo&, const LayoutPoint&); virtual void paintCell(RenderTableCell*, PaintInfo&, const LayoutPoint&); virtual void paintObject(PaintInfo&, const LayoutPoint&); @@ -202,9 +230,19 @@ private: CellSpan fullTableRowSpan() const { return CellSpan(0, m_grid.size()); } CellSpan fullTableColumnSpan() const { return CellSpan(0, table()->columns().size()); } + // Flip the rect so it aligns with the coordinates used by the rowPos and columnPos vectors. + LayoutRect logicalRectForWritingModeAndDirection(const LayoutRect&) const; + CellSpan dirtiedRows(const LayoutRect& repaintRect) const; CellSpan dirtiedColumns(const LayoutRect& repaintRect) const; + // These two functions take a rectangle as input that has been flipped by logicalRectForWritingModeAndDirection. + // The returned span of rows or columns is end-exclusive, and empty if start==end. + CellSpan spannedRows(const LayoutRect& flippedRect) const; + CellSpan spannedColumns(const LayoutRect& flippedRect) const; + + void setLogicalPositionForCell(RenderTableCell*, unsigned effectiveColumn) const; + RenderObjectChildList m_children; Vector<RowStruct> m_grid; diff --git a/Source/WebCore/rendering/RenderText.cpp b/Source/WebCore/rendering/RenderText.cpp index 16c1ea172..7ea7d7b43 100644 --- a/Source/WebCore/rendering/RenderText.cpp +++ b/Source/WebCore/rendering/RenderText.cpp @@ -53,7 +53,7 @@ using namespace Unicode; namespace WebCore { -class SameSizeAsRenderText : public RenderObject { +struct SameSizeAsRenderText : public RenderObject { uint32_t bitfields : 16; float widths[4]; String text; @@ -687,10 +687,6 @@ LayoutRect RenderText::localCaretRect(InlineBox* inlineBox, int caretOffset, Lay bool rightAligned = false; switch (cbStyle->textAlign()) { - case TAAUTO: - case JUSTIFY: - rightAligned = !cbStyle->isLeftToRightDirection(); - break; case RIGHT: case WEBKIT_RIGHT: rightAligned = true; @@ -700,6 +696,7 @@ LayoutRect RenderText::localCaretRect(InlineBox* inlineBox, int caretOffset, Lay case CENTER: case WEBKIT_CENTER: break; + case JUSTIFY: case TASTART: rightAligned = !cbStyle->isLeftToRightDirection(); break; diff --git a/Source/WebCore/rendering/RenderTextControlSingleLine.cpp b/Source/WebCore/rendering/RenderTextControlSingleLine.cpp index 848fc2119..31f1f2837 100644 --- a/Source/WebCore/rendering/RenderTextControlSingleLine.cpp +++ b/Source/WebCore/rendering/RenderTextControlSingleLine.cpp @@ -30,7 +30,6 @@ #include "Frame.h" #include "FrameSelection.h" #include "FrameView.h" -#include "HTMLInputElement.h" #include "HTMLNames.h" #include "HitTestResult.h" #include "LocalizedStrings.h" @@ -39,7 +38,6 @@ #include "RenderLayer.h" #include "RenderScrollbar.h" #include "RenderTheme.h" -#include "SearchPopupMenu.h" #include "Settings.h" #include "SimpleFontData.h" #include "StyleResolver.h" @@ -70,10 +68,8 @@ VisiblePosition RenderTextControlInnerBlock::positionForPoint(const LayoutPoint& RenderTextControlSingleLine::RenderTextControlSingleLine(Node* node) : RenderTextControl(node) - , m_searchPopupIsVisible(false) , m_shouldDrawCapsLockIndicator(false) , m_desiredInnerTextHeight(-1) - , m_searchPopup(0) { ASSERT(node->isHTMLElement()); ASSERT(node->toInputElement()); @@ -81,20 +77,6 @@ RenderTextControlSingleLine::RenderTextControlSingleLine(Node* node) RenderTextControlSingleLine::~RenderTextControlSingleLine() { - if (m_searchPopup) { - m_searchPopup->popupMenu()->disconnectClient(); - m_searchPopup = 0; - } -} - -inline HTMLElement* RenderTextControlSingleLine::containerElement() const -{ - return inputElement()->containerElement(); -} - -inline HTMLElement* RenderTextControlSingleLine::innerBlockElement() const -{ - return inputElement()->innerBlockElement(); } inline HTMLElement* RenderTextControlSingleLine::innerSpinButtonElement() const @@ -102,88 +84,12 @@ inline HTMLElement* RenderTextControlSingleLine::innerSpinButtonElement() const return inputElement()->innerSpinButtonElement(); } -inline HTMLElement* RenderTextControlSingleLine::resultsButtonElement() const -{ - return inputElement()->resultsButtonElement(); -} - -inline HTMLElement* RenderTextControlSingleLine::cancelButtonElement() const -{ - return inputElement()->cancelButtonElement(); -} - RenderStyle* RenderTextControlSingleLine::textBaseStyle() const { HTMLElement* innerBlock = innerBlockElement(); return innerBlock ? innerBlock->renderer()->style() : style(); } -void RenderTextControlSingleLine::addSearchResult() -{ - HTMLInputElement* input = inputElement(); - if (input->maxResults() <= 0) - return; - - String value = input->value(); - if (value.isEmpty()) - return; - - Settings* settings = document()->settings(); - if (!settings || settings->privateBrowsingEnabled()) - return; - - int size = static_cast<int>(m_recentSearches.size()); - for (int i = size - 1; i >= 0; --i) { - if (m_recentSearches[i] == value) - m_recentSearches.remove(i); - } - - m_recentSearches.insert(0, value); - while (static_cast<int>(m_recentSearches.size()) > input->maxResults()) - m_recentSearches.removeLast(); - - const AtomicString& name = autosaveName(); - if (!m_searchPopup) - m_searchPopup = document()->page()->chrome()->createSearchPopupMenu(this); - - m_searchPopup->saveRecentSearches(name, m_recentSearches); -} - -void RenderTextControlSingleLine::showPopup() -{ - if (m_searchPopupIsVisible) - return; - - if (!m_searchPopup) - m_searchPopup = document()->page()->chrome()->createSearchPopupMenu(this); - - if (!m_searchPopup->enabled()) - return; - - m_searchPopupIsVisible = true; - - const AtomicString& name = autosaveName(); - m_searchPopup->loadRecentSearches(name, m_recentSearches); - - // Trim the recent searches list if the maximum size has changed since we last saved. - HTMLInputElement* input = inputElement(); - if (static_cast<int>(m_recentSearches.size()) > input->maxResults()) { - do { - m_recentSearches.removeLast(); - } while (static_cast<int>(m_recentSearches.size()) > input->maxResults()); - - m_searchPopup->saveRecentSearches(name, m_recentSearches); - } - - m_searchPopup->popupMenu()->show(pixelSnappedIntRect(absoluteBoundingBoxRect()), document()->view(), -1); -} - -void RenderTextControlSingleLine::hidePopup() -{ - if (m_searchPopup) - m_searchPopup->popupMenu()->hide(); -} - void RenderTextControlSingleLine::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { RenderTextControl::paint(paintInfo, paintOffset); @@ -200,6 +106,11 @@ void RenderTextControlSingleLine::paint(PaintInfo& paintInfo, const LayoutPoint& } } +LayoutUnit RenderTextControlSingleLine::computeHeightLimit() const +{ + return containerElement() ? contentHeight() : height(); +} + void RenderTextControlSingleLine::layout() { // FIXME: We should remove the height-related hacks in layout() and @@ -225,7 +136,7 @@ void RenderTextControlSingleLine::layout() LayoutUnit desiredHeight = textBlockHeight(); LayoutUnit currentHeight = innerTextRenderer->height(); - LayoutUnit heightLimit = (inputElement()->isSearchField() || !container) ? height() : contentHeight(); + LayoutUnit heightLimit = computeHeightLimit(); if (currentHeight > heightLimit) { if (desiredHeight != currentHeight) setNeedsLayout(true, MarkOnlyThis); @@ -258,12 +169,8 @@ void RenderTextControlSingleLine::layout() if (!container && currentHeight != contentHeight()) { LayoutUnit heightDiff = currentHeight - contentHeight(); innerTextRenderer->setY(innerTextRenderer->y() - (heightDiff / 2 + layoutMod(heightDiff, 2))); - } else if (inputElement()->isSearchField() && containerRenderer && containerRenderer->height() > contentHeight()) { - // A quirk for find-in-page box on Safari Windows. - // http://webkit.org/b/63157 - LayoutUnit heightDiff = containerRenderer->height() - contentHeight(); - containerRenderer->setY(containerRenderer->y() - (heightDiff / 2 + layoutMod(heightDiff, 2))); - } + } else + centerContainerIfNeeded(containerRenderer); // Ignores the paddings for the inner spin button. if (RenderBox* innerSpinBox = innerSpinButtonElement() ? innerSpinButtonElement()->renderBox() : 0) { @@ -431,31 +338,12 @@ LayoutUnit RenderTextControlSingleLine::preferredContentWidth(float charWidth) c LayoutUnit RenderTextControlSingleLine::computeControlHeight(LayoutUnit lineHeight, LayoutUnit nonContentHeight) const { - HTMLElement* resultsButton = resultsButtonElement(); - if (RenderBox* resultsRenderer = resultsButton ? resultsButton->renderBox() : 0) { - resultsRenderer->computeLogicalHeight(); - nonContentHeight = max(nonContentHeight, resultsRenderer->borderAndPaddingHeight() + resultsRenderer->marginHeight()); - lineHeight = max(lineHeight, resultsRenderer->height()); - } - HTMLElement* cancelButton = cancelButtonElement(); - if (RenderBox* cancelRenderer = cancelButton ? cancelButton->renderBox() : 0) { - cancelRenderer->computeLogicalHeight(); - nonContentHeight = max(nonContentHeight, cancelRenderer->borderAndPaddingHeight() + cancelRenderer->marginHeight()); - lineHeight = max(lineHeight, cancelRenderer->height()); - } - return lineHeight + nonContentHeight; } void RenderTextControlSingleLine::updateFromElement() { RenderTextControl::updateFromElement(); - - if (cancelButtonElement()) - updateCancelButtonVisibility(); - - if (m_searchPopupIsVisible) - m_searchPopup->popupMenu()->updateFromElement(); } PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerTextStyle(const RenderStyle* startStyle) const @@ -496,188 +384,12 @@ PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerBlockStyle(const return innerBlockStyle.release(); } -void RenderTextControlSingleLine::updateCancelButtonVisibility() const -{ - RenderObject* cancelButtonRenderer = cancelButtonElement()->renderer(); - if (!cancelButtonRenderer) - return; - - const RenderStyle* curStyle = cancelButtonRenderer->style(); - EVisibility buttonVisibility = visibilityForCancelButton(); - if (curStyle->visibility() == buttonVisibility) - return; - - RefPtr<RenderStyle> cancelButtonStyle = RenderStyle::clone(curStyle); - cancelButtonStyle->setVisibility(buttonVisibility); - cancelButtonRenderer->setStyle(cancelButtonStyle); -} - -EVisibility RenderTextControlSingleLine::visibilityForCancelButton() const -{ - return (style()->visibility() == HIDDEN || inputElement()->value().isEmpty()) ? HIDDEN : VISIBLE; -} - bool RenderTextControlSingleLine::textShouldBeTruncated() const { return document()->focusedNode() != node() && style()->textOverflow() == TextOverflowEllipsis; } -const AtomicString& RenderTextControlSingleLine::autosaveName() const -{ - return static_cast<Element*>(node())->getAttribute(autosaveAttr); -} - -// PopupMenuClient methods -void RenderTextControlSingleLine::valueChanged(unsigned listIndex, bool fireEvents) -{ - ASSERT(static_cast<int>(listIndex) < listSize()); - HTMLInputElement* input = inputElement(); - if (static_cast<int>(listIndex) == (listSize() - 1)) { - if (fireEvents) { - m_recentSearches.clear(); - const AtomicString& name = autosaveName(); - if (!name.isEmpty()) { - if (!m_searchPopup) - m_searchPopup = document()->page()->chrome()->createSearchPopupMenu(this); - m_searchPopup->saveRecentSearches(name, m_recentSearches); - } - } - } else { - input->setValue(itemText(listIndex)); - if (fireEvents) - input->onSearch(); - input->select(); - } -} - -String RenderTextControlSingleLine::itemText(unsigned listIndex) const -{ - int size = listSize(); - if (size == 1) { - ASSERT(!listIndex); - return searchMenuNoRecentSearchesText(); - } - if (!listIndex) - return searchMenuRecentSearchesText(); - if (itemIsSeparator(listIndex)) - return String(); - if (static_cast<int>(listIndex) == (size - 1)) - return searchMenuClearRecentSearchesText(); - return m_recentSearches[listIndex - 1]; -} - -String RenderTextControlSingleLine::itemLabel(unsigned) const -{ - return String(); -} - -String RenderTextControlSingleLine::itemIcon(unsigned) const -{ - return String(); -} - -bool RenderTextControlSingleLine::itemIsEnabled(unsigned listIndex) const -{ - if (!listIndex || itemIsSeparator(listIndex)) - return false; - return true; -} - -PopupMenuStyle RenderTextControlSingleLine::itemStyle(unsigned) const -{ - return menuStyle(); -} - -PopupMenuStyle RenderTextControlSingleLine::menuStyle() const -{ - return PopupMenuStyle(style()->visitedDependentColor(CSSPropertyColor), style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->font(), style()->visibility() == VISIBLE, - style()->display() == NONE, style()->textIndent(), style()->direction(), isOverride(style()->unicodeBidi())); -} - -int RenderTextControlSingleLine::clientInsetLeft() const -{ - // Inset the menu by the radius of the cap on the left so that - // it only runs along the straight part of the bezel. - return height() / 2; -} - -int RenderTextControlSingleLine::clientInsetRight() const -{ - // Inset the menu by the radius of the cap on the right so that - // it only runs along the straight part of the bezel (unless it needs - // to be wider). - return height() / 2; -} - -LayoutUnit RenderTextControlSingleLine::clientPaddingLeft() const -{ - LayoutUnit padding = paddingLeft(); - if (RenderBox* box = innerBlockElement() ? innerBlockElement()->renderBox() : 0) - padding += box->x(); - return padding; -} - -LayoutUnit RenderTextControlSingleLine::clientPaddingRight() const -{ - LayoutUnit padding = paddingRight(); - if (RenderBox* containerBox = containerElement() ? containerElement()->renderBox() : 0) { - if (RenderBox* innerBlockBox = innerBlockElement() ? innerBlockElement()->renderBox() : 0) - padding += containerBox->width() - (innerBlockBox->x() + innerBlockBox->width()); - } - return padding; -} - -int RenderTextControlSingleLine::listSize() const -{ - // If there are no recent searches, then our menu will have 1 "No recent searches" item. - if (!m_recentSearches.size()) - return 1; - // Otherwise, leave room in the menu for a header, a separator, and the "Clear recent searches" item. - return m_recentSearches.size() + 3; -} - -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. - return static_cast<int>(listIndex) == (listSize() - 2); -} - -bool RenderTextControlSingleLine::itemIsLabel(unsigned listIndex) const -{ - return listIndex == 0; -} - -bool RenderTextControlSingleLine::itemIsSelected(unsigned) const -{ - return false; -} - -void RenderTextControlSingleLine::setTextFromItem(unsigned listIndex) -{ - inputElement()->setValue(itemText(listIndex)); -} - -FontSelector* RenderTextControlSingleLine::fontSelector() const -{ - return document()->styleResolver()->fontSelector(); -} - -HostWindow* RenderTextControlSingleLine::hostWindow() const -{ - return document()->view()->hostWindow(); -} - void RenderTextControlSingleLine::autoscroll() { RenderLayer* layer = innerTextElement()->renderBox()->layer(); @@ -741,17 +453,6 @@ bool RenderTextControlSingleLine::logicalScroll(ScrollLogicalDirection direction return RenderBlock::logicalScroll(direction, granularity, multiplier, stopNode); } -PassRefPtr<Scrollbar> RenderTextControlSingleLine::createScrollbar(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, ScrollbarControlSize controlSize) -{ - RefPtr<Scrollbar> widget; - bool hasCustomScrollbarStyle = style()->hasPseudoStyle(SCROLLBAR); - if (hasCustomScrollbarStyle) - widget = RenderScrollbar::createCustomScrollbar(scrollableArea, orientation, this->node()); - else - widget = Scrollbar::createNativeScrollbar(scrollableArea, orientation, controlSize); - return widget.release(); -} - HTMLInputElement* RenderTextControlSingleLine::inputElement() const { return node()->toInputElement(); diff --git a/Source/WebCore/rendering/RenderTextControlSingleLine.h b/Source/WebCore/rendering/RenderTextControlSingleLine.h index 6e21c856c..ffc50a33d 100644 --- a/Source/WebCore/rendering/RenderTextControlSingleLine.h +++ b/Source/WebCore/rendering/RenderTextControlSingleLine.h @@ -23,32 +23,31 @@ #ifndef RenderTextControlSingleLine_h #define RenderTextControlSingleLine_h -#include "PopupMenuClient.h" +#include "HTMLInputElement.h" #include "RenderTextControl.h" namespace WebCore { class HTMLInputElement; -class SearchPopupMenu; -class RenderTextControlSingleLine : public RenderTextControl, private PopupMenuClient { +class RenderTextControlSingleLine : public RenderTextControl { public: RenderTextControlSingleLine(Node*); virtual ~RenderTextControlSingleLine(); // FIXME: Move create*Style() to their classes. virtual PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const; PassRefPtr<RenderStyle> createInnerBlockStyle(const RenderStyle* startStyle) const; - void updateCancelButtonVisibility() const; - - void addSearchResult(); - void stopSearchEventTimer(); - - bool popupIsVisible() const { return m_searchPopupIsVisible; } - void showPopup(); - void hidePopup(); void capsLockStateMayHaveChanged(); +protected: + virtual void centerContainerIfNeeded(RenderBox*) const { } + virtual LayoutUnit computeHeightLimit() const; + HTMLElement* containerElement() const; + HTMLElement* innerBlockElement() const; + HTMLInputElement* inputElement() const; + virtual void updateFromElement() OVERRIDE; + private: virtual bool hasControlClip() const; virtual LayoutRect controlClipRect(const LayoutPoint&) const; @@ -76,59 +75,28 @@ private: virtual LayoutUnit preferredContentWidth(float charWidth) const; virtual LayoutUnit computeControlHeight(LayoutUnit lineHeight, LayoutUnit nonContentHeight) const OVERRIDE; - virtual void updateFromElement(); virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); virtual RenderStyle* textBaseStyle() const; - EVisibility visibilityForCancelButton() const; bool textShouldBeTruncated() const; - const AtomicString& autosaveName() const; - - // PopupMenuClient methods - virtual void valueChanged(unsigned listIndex, bool fireEvents = true) OVERRIDE; - virtual void selectionChanged(unsigned, bool) OVERRIDE { } - virtual void selectionCleared() OVERRIDE { } - virtual String itemText(unsigned listIndex) const OVERRIDE; - virtual String itemLabel(unsigned listIndex) const OVERRIDE; - virtual String itemIcon(unsigned listIndex) const OVERRIDE; - virtual String itemToolTip(unsigned) const OVERRIDE { return String(); } - virtual String itemAccessibilityText(unsigned) const OVERRIDE { return String(); } - virtual bool itemIsEnabled(unsigned listIndex) const OVERRIDE; - virtual PopupMenuStyle itemStyle(unsigned listIndex) const OVERRIDE; - virtual PopupMenuStyle menuStyle() const OVERRIDE; - virtual int clientInsetLeft() const OVERRIDE; - virtual int clientInsetRight() const OVERRIDE; - virtual LayoutUnit clientPaddingLeft() const OVERRIDE; - virtual LayoutUnit clientPaddingRight() const OVERRIDE; - virtual int listSize() const OVERRIDE; - virtual int selectedIndex() const OVERRIDE; - virtual void popupDidHide() OVERRIDE; - virtual bool itemIsSeparator(unsigned listIndex) const OVERRIDE; - virtual bool itemIsLabel(unsigned listIndex) const OVERRIDE; - virtual bool itemIsSelected(unsigned listIndex) const OVERRIDE; - virtual bool shouldPopOver() const OVERRIDE { return false; } - virtual bool valueShouldChangeOnHotTrack() const OVERRIDE { return false; } - virtual void setTextFromItem(unsigned listIndex) OVERRIDE; - virtual FontSelector* fontSelector() const OVERRIDE; - virtual HostWindow* hostWindow() const OVERRIDE; - virtual PassRefPtr<Scrollbar> createScrollbar(ScrollableArea*, ScrollbarOrientation, ScrollbarControlSize) OVERRIDE; - - HTMLInputElement* inputElement() const; - HTMLElement* containerElement() const; - HTMLElement* innerBlockElement() const; HTMLElement* innerSpinButtonElement() const; - HTMLElement* resultsButtonElement() const; - HTMLElement* cancelButtonElement() const; - bool m_searchPopupIsVisible; bool m_shouldDrawCapsLockIndicator; LayoutUnit m_desiredInnerTextHeight; - RefPtr<SearchPopupMenu> m_searchPopup; - Vector<String> m_recentSearches; }; +inline HTMLElement* RenderTextControlSingleLine::containerElement() const +{ + return inputElement()->containerElement(); +} + +inline HTMLElement* RenderTextControlSingleLine::innerBlockElement() const +{ + return inputElement()->innerBlockElement(); +} + inline RenderTextControlSingleLine* toRenderTextControlSingleLine(RenderObject* object) { ASSERT(!object || object->isTextField()); diff --git a/Source/WebCore/rendering/RenderTheme.cpp b/Source/WebCore/rendering/RenderTheme.cpp index 585385f1b..e68b893eb 100644 --- a/Source/WebCore/rendering/RenderTheme.cpp +++ b/Source/WebCore/rendering/RenderTheme.cpp @@ -202,6 +202,14 @@ void RenderTheme::adjustStyle(StyleResolver* styleResolver, RenderStyle* style, return adjustMenuListStyle(styleResolver, style, e); case MenulistButtonPart: return adjustMenuListButtonStyle(styleResolver, style, e); + case MediaPlayButtonPart: + case MediaCurrentTimePart: + case MediaTimeRemainingPart: + case MediaEnterFullscreenButtonPart: + case MediaExitFullscreenButtonPart: + case MediaMuteButtonPart: + case MediaVolumeSliderContainerPart: + return adjustMediaControlStyle(styleResolver, style, e); case MediaSliderPart: case MediaVolumeSliderPart: case MediaFullScreenVolumeSliderPart: @@ -969,16 +977,20 @@ void RenderTheme::adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Elemen { } +void RenderTheme::adjustMediaControlStyle(StyleResolver*, RenderStyle*, Element*) const +{ +} + void RenderTheme::adjustSliderTrackStyle(StyleResolver*, RenderStyle*, Element*) const { } -void RenderTheme::adjustSliderThumbStyle(StyleResolver*, RenderStyle* style, Element*) const +void RenderTheme::adjustSliderThumbStyle(StyleResolver*, RenderStyle* style, Element* element) const { - adjustSliderThumbSize(style); + adjustSliderThumbSize(style, element); } -void RenderTheme::adjustSliderThumbSize(RenderStyle*) const +void RenderTheme::adjustSliderThumbSize(RenderStyle*, Element*) const { } diff --git a/Source/WebCore/rendering/RenderTheme.h b/Source/WebCore/rendering/RenderTheme.h index e3e71475f..5e56b6df5 100644 --- a/Source/WebCore/rendering/RenderTheme.h +++ b/Source/WebCore/rendering/RenderTheme.h @@ -172,7 +172,7 @@ public: virtual int minimumMenuListSize(RenderStyle*) const { return 0; } - virtual void adjustSliderThumbSize(RenderStyle*) const; + virtual void adjustSliderThumbSize(RenderStyle*, Element*) const; virtual int popupInternalPaddingLeft(RenderStyle*) const { return 0; } virtual int popupInternalPaddingRight(RenderStyle*) const { return 0; } @@ -198,6 +198,7 @@ public: virtual bool hasOwnDisabledStateHandlingFor(ControlPart) const { return false; } virtual bool usesMediaControlStatusDisplay() { return false; } virtual bool usesMediaControlVolumeSlider() const { return true; } + virtual bool usesVerticalVolumeSlider() const { return true; } virtual double mediaControlsFadeInDuration() { return 0.1; } virtual double mediaControlsFadeOutDuration() { return 0.3; } virtual String formatMediaControlsTime(float time) const; @@ -305,6 +306,7 @@ protected: virtual void adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle*, Element*) const; virtual bool paintSearchFieldResultsButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; } + virtual void adjustMediaControlStyle(StyleResolver*, RenderStyle*, Element*) const; virtual bool paintMediaFullscreenButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; } virtual bool paintMediaPlayButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; } virtual bool paintMediaMuteButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; } diff --git a/Source/WebCore/rendering/RenderThemeChromiumAndroid.cpp b/Source/WebCore/rendering/RenderThemeChromiumAndroid.cpp index 8b7123088..97f587455 100644 --- a/Source/WebCore/rendering/RenderThemeChromiumAndroid.cpp +++ b/Source/WebCore/rendering/RenderThemeChromiumAndroid.cpp @@ -99,4 +99,12 @@ bool RenderThemeChromiumAndroid::paintMediaFullscreenButton(RenderObject* object #endif } +int RenderThemeChromiumAndroid::menuListArrowPadding() const +{ + // We cannot use the scrollbar thickness here, as it's width is 0 on Android. + // Instead, use the width of the scrollbar down arrow. + IntSize scrollbarSize = PlatformSupport::getThemePartSize(PlatformSupport::PartScrollbarDownArrow); + return scrollbarSize.width(); +} + } // namespace WebCore diff --git a/Source/WebCore/rendering/RenderThemeChromiumAndroid.h b/Source/WebCore/rendering/RenderThemeChromiumAndroid.h index 3dcd6df93..f7aafaa18 100644 --- a/Source/WebCore/rendering/RenderThemeChromiumAndroid.h +++ b/Source/WebCore/rendering/RenderThemeChromiumAndroid.h @@ -41,7 +41,7 @@ public: virtual bool delegatesMenuListRendering() const OVERRIDE { return true; } - virtual bool paintMediaFullscreenButton(RenderObject*, const PaintInfo&, const IntRect&); + virtual bool paintMediaFullscreenButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE; #if ENABLE(VIDEO) virtual String extraMediaControlsStyleSheet() OVERRIDE; @@ -54,10 +54,19 @@ public: } #endif + virtual Color platformActiveSelectionBackgroundColor() const OVERRIDE + { + return RenderThemeChromiumAndroid::defaultActiveSelectionBackgroundColor; + } + +protected: + virtual int menuListArrowPadding() const OVERRIDE; + private: virtual ~RenderThemeChromiumAndroid(); static const RGBA32 defaultTapHighlightColor = 0x6633b5e5; + static const RGBA32 defaultActiveSelectionBackgroundColor = 0x6633b5e5; }; } // namespace WebCore diff --git a/Source/WebCore/rendering/RenderThemeChromiumLinux.cpp b/Source/WebCore/rendering/RenderThemeChromiumLinux.cpp index 019694f0d..6b7f158ee 100644 --- a/Source/WebCore/rendering/RenderThemeChromiumLinux.cpp +++ b/Source/WebCore/rendering/RenderThemeChromiumLinux.cpp @@ -146,7 +146,7 @@ Color RenderThemeChromiumLinux::platformInactiveSelectionForegroundColor() const return m_inactiveSelectionForegroundColor; } -void RenderThemeChromiumLinux::adjustSliderThumbSize(RenderStyle* style) const +void RenderThemeChromiumLinux::adjustSliderThumbSize(RenderStyle* style, Element* element) const { IntSize size = PlatformSupport::getThemePartSize(PlatformSupport::PartSliderThumb); @@ -157,7 +157,7 @@ void RenderThemeChromiumLinux::adjustSliderThumbSize(RenderStyle* style) const style->setWidth(Length(size.height(), Fixed)); style->setHeight(Length(size.width(), Fixed)); } else - RenderThemeChromiumSkia::adjustSliderThumbSize(style); + RenderThemeChromiumSkia::adjustSliderThumbSize(style, element); } bool RenderThemeChromiumLinux::supportsControlTints() const diff --git a/Source/WebCore/rendering/RenderThemeChromiumLinux.h b/Source/WebCore/rendering/RenderThemeChromiumLinux.h index 7e308083f..d75408251 100644 --- a/Source/WebCore/rendering/RenderThemeChromiumLinux.h +++ b/Source/WebCore/rendering/RenderThemeChromiumLinux.h @@ -54,7 +54,7 @@ namespace WebCore { virtual Color platformActiveSelectionForegroundColor() const; virtual Color platformInactiveSelectionForegroundColor() const; - virtual void adjustSliderThumbSize(RenderStyle*) const; + virtual void adjustSliderThumbSize(RenderStyle*, Element*) const; static void setCaretBlinkInterval(double interval); virtual double caretBlinkIntervalInternal() const; diff --git a/Source/WebCore/rendering/RenderThemeChromiumMac.h b/Source/WebCore/rendering/RenderThemeChromiumMac.h index 2b4c8c635..973299a31 100644 --- a/Source/WebCore/rendering/RenderThemeChromiumMac.h +++ b/Source/WebCore/rendering/RenderThemeChromiumMac.h @@ -42,7 +42,6 @@ protected: virtual bool paintMediaPlayButton(RenderObject*, const PaintInfo&, const IntRect&); virtual bool paintMediaMuteButton(RenderObject*, const PaintInfo&, const IntRect&); virtual bool paintMediaSliderTrack(RenderObject*, const PaintInfo&, const IntRect&); - virtual bool paintMediaControlsBackground(RenderObject*, const PaintInfo&, const IntRect&); virtual String extraMediaControlsStyleSheet(); #if ENABLE(FULLSCREEN_API) virtual String extraFullScreenStyleSheet(); @@ -55,6 +54,11 @@ protected: virtual IntPoint volumeSliderOffsetFromMuteButton(RenderBox*, const IntSize&) const OVERRIDE; virtual bool usesMediaControlStatusDisplay() { return false; } virtual bool hasOwnDisabledStateHandlingFor(ControlPart) const { return true; } + virtual bool usesVerticalVolumeSlider() const { return false; } + virtual String formatMediaControlsTime(float time) const; + virtual String formatMediaControlsCurrentTime(float currentTime, float duration) const; + virtual String formatMediaControlsRemainingTime(float currentTime, float duration) const; + virtual bool paintMediaFullscreenButton(RenderObject*, const PaintInfo&, const IntRect&); #endif virtual bool usesTestModeFocusRingColor() const; diff --git a/Source/WebCore/rendering/RenderThemeChromiumMac.mm b/Source/WebCore/rendering/RenderThemeChromiumMac.mm index a778228c5..1791b09ab 100644 --- a/Source/WebCore/rendering/RenderThemeChromiumMac.mm +++ b/Source/WebCore/rendering/RenderThemeChromiumMac.mm @@ -173,11 +173,6 @@ bool RenderThemeChromiumMac::paintMediaSliderTrack(RenderObject* object, const P return RenderMediaControlsChromium::paintMediaControlsPart(MediaSlider, object, paintInfo, rect); } -bool RenderThemeChromiumMac::paintMediaControlsBackground(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) -{ - return RenderMediaControlsChromium::paintMediaControlsPart(MediaTimelineContainer, object, paintInfo, rect); -} - String RenderThemeChromiumMac::extraMediaControlsStyleSheet() { return String(mediaControlsChromiumUserAgentStyleSheet, sizeof(mediaControlsChromiumUserAgentStyleSheet)); @@ -228,6 +223,26 @@ IntPoint RenderThemeChromiumMac::volumeSliderOffsetFromMuteButton(RenderBox* mut { return RenderTheme::volumeSliderOffsetFromMuteButton(muteButtonBox, size); } + +String RenderThemeChromiumMac::formatMediaControlsTime(float time) const +{ + return RenderMediaControlsChromium::formatMediaControlsTime(time); +} + +String RenderThemeChromiumMac::formatMediaControlsCurrentTime(float currentTime, float duration) const +{ + return RenderMediaControlsChromium::formatMediaControlsCurrentTime(currentTime, duration); +} + +String RenderThemeChromiumMac::formatMediaControlsRemainingTime(float currentTime, float duration) const +{ + return RenderThemeChromiumMac::formatMediaControlsRemainingTime(currentTime, duration); +} + +bool RenderThemeChromiumMac::paintMediaFullscreenButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) +{ + return RenderMediaControlsChromium::paintMediaControlsPart(MediaEnterFullscreenButton, object, paintInfo, rect); +} #endif } // namespace WebCore diff --git a/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp b/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp index 902dad013..c88066616 100644 --- a/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp +++ b/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp @@ -378,18 +378,6 @@ bool RenderThemeChromiumSkia::paintSearchFieldResultsButton(RenderObject* magnif return false; } -bool RenderThemeChromiumSkia::paintMediaControlsBackground(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) -{ -#if ENABLE(VIDEO) - return RenderMediaControlsChromium::paintMediaControlsPart(MediaTimelineContainer, object, paintInfo, rect); -#else - UNUSED_PARAM(object); - UNUSED_PARAM(paintInfo); - UNUSED_PARAM(rect); - return false; -#endif -} - bool RenderThemeChromiumSkia::paintMediaSliderTrack(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) { #if ENABLE(VIDEO) @@ -414,7 +402,7 @@ bool RenderThemeChromiumSkia::paintMediaVolumeSliderTrack(RenderObject* object, #endif } -void RenderThemeChromiumSkia::adjustSliderThumbSize(RenderStyle* style) const +void RenderThemeChromiumSkia::adjustSliderThumbSize(RenderStyle* style, Element*) const { #if ENABLE(VIDEO) RenderMediaControlsChromium::adjustMediaSliderThumbSize(style); @@ -471,6 +459,50 @@ bool RenderThemeChromiumSkia::paintMediaMuteButton(RenderObject* object, const P #endif } +String RenderThemeChromiumSkia::formatMediaControlsTime(float time) const +{ +#if ENABLE(VIDEO) + return RenderMediaControlsChromium::formatMediaControlsTime(time); +#else + UNUSED_PARAM(time); + return 0; +#endif +} + +String RenderThemeChromiumSkia::formatMediaControlsCurrentTime(float currentTime, float duration) const +{ +#if ENABLE(VIDEO) + return RenderMediaControlsChromium::formatMediaControlsCurrentTime(currentTime, duration); +#else + UNUSED_PARAM(currentTime); + UNUSED_PARAM(duration); + return 0; +#endif +} + +String RenderThemeChromiumSkia::formatMediaControlsRemainingTime(float currentTime, float duration) const +{ +#if ENABLE(VIDEO) + return RenderMediaControlsChromium::formatMediaControlsRemainingTime(currentTime, duration); +#else + UNUSED_PARAM(currentTime); + UNUSED_PARAM(duration); + return 0; +#endif +} + +bool RenderThemeChromiumSkia::paintMediaFullscreenButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) +{ +#if ENABLE(VIDEO) + return RenderMediaControlsChromium::paintMediaControlsPart(MediaEnterFullscreenButton, object, paintInfo, rect); +#else + UNUSED_PARAM(object); + UNUSED_PARAM(paintInfo); + UNUSED_PARAM(rect); + return false; +#endif +} + void RenderThemeChromiumSkia::adjustMenuListStyle(StyleResolver*, RenderStyle* style, WebCore::Element*) const { // Height is locked to auto on all browsers. @@ -519,6 +551,11 @@ double RenderThemeChromiumSkia::caretBlinkIntervalInternal() const return RenderTheme::caretBlinkInterval(); } +int RenderThemeChromiumSkia::menuListArrowPadding() const +{ + return ScrollbarTheme::theme()->scrollbarThickness(); +} + // static void RenderThemeChromiumSkia::setSizeIfAuto(RenderStyle* style, const IntSize& size) { @@ -541,7 +578,7 @@ int RenderThemeChromiumSkia::menuListInternalPadding(RenderStyle* style, int pad // we don't draw a button, so don't reserve space for it. const int barType = style->direction() == LTR ? RightPadding : LeftPadding; if (paddingType == barType && style->appearance() != NoControlPart) - padding += ScrollbarTheme::theme()->scrollbarThickness(); + padding += menuListArrowPadding(); return padding; } diff --git a/Source/WebCore/rendering/RenderThemeChromiumSkia.h b/Source/WebCore/rendering/RenderThemeChromiumSkia.h index c5306c12f..745873052 100644 --- a/Source/WebCore/rendering/RenderThemeChromiumSkia.h +++ b/Source/WebCore/rendering/RenderThemeChromiumSkia.h @@ -91,14 +91,17 @@ class RenderThemeChromiumSkia : public RenderTheme { virtual void adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle*, Element*) const; virtual bool paintSearchFieldResultsButton(RenderObject*, const PaintInfo&, const IntRect&); - virtual bool paintMediaControlsBackground(RenderObject*, const PaintInfo&, const IntRect&); virtual bool paintMediaSliderTrack(RenderObject*, const PaintInfo&, const IntRect&); virtual bool paintMediaVolumeSliderTrack(RenderObject*, const PaintInfo&, const IntRect&); - virtual void adjustSliderThumbSize(RenderStyle*) const; + virtual void adjustSliderThumbSize(RenderStyle*, Element*) const; virtual bool paintMediaSliderThumb(RenderObject*, const PaintInfo&, const IntRect&); virtual bool paintMediaVolumeSliderThumb(RenderObject*, const PaintInfo&, const IntRect&); virtual bool paintMediaPlayButton(RenderObject*, const PaintInfo&, const IntRect&); virtual bool paintMediaMuteButton(RenderObject*, const PaintInfo&, const IntRect&); + virtual String formatMediaControlsTime(float time) const; + virtual String formatMediaControlsCurrentTime(float currentTime, float duration) const; + virtual String formatMediaControlsRemainingTime(float currentTime, float duration) const; + virtual bool paintMediaFullscreenButton(RenderObject*, const PaintInfo&, const IntRect&); // MenuList refers to an unstyled menulist (meaning a menulist without // background-color or border set) and MenuListButton refers to a styled @@ -127,6 +130,7 @@ class RenderThemeChromiumSkia : public RenderTheme { #if ENABLE(VIDEO) // Media controls virtual bool hasOwnDisabledStateHandlingFor(ControlPart) const { return true; } + virtual bool usesVerticalVolumeSlider() const { return false; } #endif // Provide a way to pass the default font size from the Settings object @@ -146,6 +150,8 @@ class RenderThemeChromiumSkia : public RenderTheme { virtual double caretBlinkIntervalInternal() const; + virtual int menuListArrowPadding() const; + static void setSizeIfAuto(RenderStyle*, const IntSize&); #if ENABLE(PROGRESS_TAG) diff --git a/Source/WebCore/rendering/RenderThemeChromiumWin.cpp b/Source/WebCore/rendering/RenderThemeChromiumWin.cpp index 444212fd0..e2c41d9dd 100644 --- a/Source/WebCore/rendering/RenderThemeChromiumWin.cpp +++ b/Source/WebCore/rendering/RenderThemeChromiumWin.cpp @@ -391,7 +391,7 @@ Color RenderThemeChromiumWin::systemColor(int cssValueId) const return Color(GetRValue(color), GetGValue(color), GetBValue(color)); } -void RenderThemeChromiumWin::adjustSliderThumbSize(RenderStyle* style) const +void RenderThemeChromiumWin::adjustSliderThumbSize(RenderStyle* style, Element* element) const { // These sizes match what WinXP draws for various menus. const int sliderThumbAlongAxis = 11; @@ -403,7 +403,7 @@ void RenderThemeChromiumWin::adjustSliderThumbSize(RenderStyle* style) const style->setWidth(Length(sliderThumbAcrossAxis, Fixed)); style->setHeight(Length(sliderThumbAlongAxis, Fixed)); } else - RenderThemeChromiumSkia::adjustSliderThumbSize(style); + RenderThemeChromiumSkia::adjustSliderThumbSize(style, element); } bool RenderThemeChromiumWin::paintCheckbox(RenderObject* o, const PaintInfo& i, const IntRect& r) diff --git a/Source/WebCore/rendering/RenderThemeChromiumWin.h b/Source/WebCore/rendering/RenderThemeChromiumWin.h index 7856d039f..ad9eace89 100644 --- a/Source/WebCore/rendering/RenderThemeChromiumWin.h +++ b/Source/WebCore/rendering/RenderThemeChromiumWin.h @@ -61,7 +61,7 @@ namespace WebCore { virtual void systemFont(int propId, FontDescription&) const; virtual Color systemColor(int cssValueId) const; - virtual void adjustSliderThumbSize(RenderStyle*) const; + virtual void adjustSliderThumbSize(RenderStyle*, Element*) const; // Various paint functions. virtual bool paintCheckbox(RenderObject*, const PaintInfo&, const IntRect&); diff --git a/Source/WebCore/rendering/RenderThemeMac.h b/Source/WebCore/rendering/RenderThemeMac.h index ebbb2352c..2f5f80e8c 100644 --- a/Source/WebCore/rendering/RenderThemeMac.h +++ b/Source/WebCore/rendering/RenderThemeMac.h @@ -67,7 +67,7 @@ public: virtual int minimumMenuListSize(RenderStyle*) const; - virtual void adjustSliderThumbSize(RenderStyle*) const; + virtual void adjustSliderThumbSize(RenderStyle*, Element*) const; virtual int popupInternalPaddingLeft(RenderStyle*) const; virtual int popupInternalPaddingRight(RenderStyle*) const; diff --git a/Source/WebCore/rendering/RenderThemeMac.mm b/Source/WebCore/rendering/RenderThemeMac.mm index f6f57b905..e09437db2 100644 --- a/Source/WebCore/rendering/RenderThemeMac.mm +++ b/Source/WebCore/rendering/RenderThemeMac.mm @@ -1747,7 +1747,7 @@ const int sliderThumbHeight = 15; const int mediaSliderThumbWidth = 13; const int mediaSliderThumbHeight = 14; -void RenderThemeMac::adjustSliderThumbSize(RenderStyle* style) const +void RenderThemeMac::adjustSliderThumbSize(RenderStyle* style, Element*) const { float zoomLevel = style->effectiveZoom(); if (style->appearance() == SliderThumbHorizontalPart || style->appearance() == SliderThumbVerticalPart) { @@ -1833,9 +1833,9 @@ bool RenderThemeMac::paintMediaFullscreenButton(RenderObject* o, const PaintInfo if (!node) return false; - if (MediaControlFullscreenButtonElement* btn = static_cast<MediaControlFullscreenButtonElement*>(o->node())) { + if (node->isMediaControlElement()) { LocalCurrentGraphicsContext localContext(paintInfo.context); - wkDrawMediaUIPart(btn->displayType(), mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node)); + wkDrawMediaUIPart(mediaControlElementType(node), mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node)); } return false; } diff --git a/Source/WebCore/rendering/RenderThemeSafari.cpp b/Source/WebCore/rendering/RenderThemeSafari.cpp index 00a5d7e66..23fd8b193 100644 --- a/Source/WebCore/rendering/RenderThemeSafari.cpp +++ b/Source/WebCore/rendering/RenderThemeSafari.cpp @@ -1006,7 +1006,7 @@ bool RenderThemeSafari::paintSliderThumb(RenderObject* o, const PaintInfo& paint const int sliderThumbWidth = 15; const int sliderThumbHeight = 15; -void RenderThemeSafari::adjustSliderThumbSize(RenderStyle* style) const +void RenderThemeSafari::adjustSliderThumbSize(RenderStyle* style, Element*) const { if (style->appearance() == SliderThumbHorizontalPart || style->appearance() == SliderThumbVerticalPart) { style->setWidth(Length(sliderThumbWidth, Fixed)); diff --git a/Source/WebCore/rendering/RenderThemeSafari.h b/Source/WebCore/rendering/RenderThemeSafari.h index 05b1fb5ea..cb861e668 100644 --- a/Source/WebCore/rendering/RenderThemeSafari.h +++ b/Source/WebCore/rendering/RenderThemeSafari.h @@ -76,7 +76,7 @@ public: virtual int minimumMenuListSize(RenderStyle*) const; - virtual void adjustSliderThumbSize(RenderStyle*) const; + virtual void adjustSliderThumbSize(RenderStyle*, Element*) const; virtual void adjustSliderThumbStyle(StyleResolver*, RenderStyle*, Element*) const; virtual int popupInternalPaddingLeft(RenderStyle*) const; diff --git a/Source/WebCore/rendering/RenderThemeWin.cpp b/Source/WebCore/rendering/RenderThemeWin.cpp index e58bad9e1..403dd98b1 100644 --- a/Source/WebCore/rendering/RenderThemeWin.cpp +++ b/Source/WebCore/rendering/RenderThemeWin.cpp @@ -841,7 +841,7 @@ bool RenderThemeWin::paintSliderThumb(RenderObject* o, const PaintInfo& i, const const int sliderThumbWidth = 7; const int sliderThumbHeight = 15; -void RenderThemeWin::adjustSliderThumbSize(RenderStyle* style) const +void RenderThemeWin::adjustSliderThumbSize(RenderStyle* style, Element*) const { ControlPart part = style->appearance(); if (part == SliderThumbVerticalPart) { diff --git a/Source/WebCore/rendering/RenderThemeWin.h b/Source/WebCore/rendering/RenderThemeWin.h index d2337c361..b97f30004 100644 --- a/Source/WebCore/rendering/RenderThemeWin.h +++ b/Source/WebCore/rendering/RenderThemeWin.h @@ -93,7 +93,7 @@ public: virtual bool paintSliderTrack(RenderObject* o, const PaintInfo& i, const IntRect& r); virtual bool paintSliderThumb(RenderObject* o, const PaintInfo& i, const IntRect& r); - virtual void adjustSliderThumbSize(RenderStyle*) const; + virtual void adjustSliderThumbSize(RenderStyle*, Element*) const; virtual bool popupOptionSupportsTextIndent() const { return true; } diff --git a/Source/WebCore/rendering/RenderThemeWinCE.cpp b/Source/WebCore/rendering/RenderThemeWinCE.cpp index d89257d04..40349de10 100644 --- a/Source/WebCore/rendering/RenderThemeWinCE.cpp +++ b/Source/WebCore/rendering/RenderThemeWinCE.cpp @@ -331,7 +331,7 @@ Color RenderThemeWinCE::systemColor(int cssValueId) const const int sliderThumbWidth = 7; const int sliderThumbHeight = 15; -void RenderThemeWinCE::adjustSliderThumbSize(RenderStyle* style) const +void RenderThemeWinCE::adjustSliderThumbSize(RenderStyle* style, Element*) const { if (style->appearance() == SliderThumbVerticalPart) { style->setWidth(Length(sliderThumbHeight, Fixed)); diff --git a/Source/WebCore/rendering/RenderThemeWinCE.h b/Source/WebCore/rendering/RenderThemeWinCE.h index dee237eaf..bde872c6c 100644 --- a/Source/WebCore/rendering/RenderThemeWinCE.h +++ b/Source/WebCore/rendering/RenderThemeWinCE.h @@ -89,7 +89,7 @@ namespace WebCore { virtual bool paintSliderTrack(RenderObject* o, const PaintInfo& i, const IntRect& r); virtual bool paintSliderThumb(RenderObject* o, const PaintInfo& i, const IntRect& r); - virtual void adjustSliderThumbSize(RenderStyle*) const; + virtual void adjustSliderThumbSize(RenderStyle*, Element*) const; virtual bool popupOptionSupportsTextIndent() const { return true; } diff --git a/Source/WebCore/rendering/RenderTreeAsText.cpp b/Source/WebCore/rendering/RenderTreeAsText.cpp index 39319ca1f..59ceebd68 100644 --- a/Source/WebCore/rendering/RenderTreeAsText.cpp +++ b/Source/WebCore/rendering/RenderTreeAsText.cpp @@ -374,6 +374,23 @@ void RenderTreeAsText::writeRenderObject(TextStream& ts, const RenderObject& o, ts << "]"; } + +#if ENABLE(MATHML) + // We want to show any layout padding, both CSS padding and intrinsic padding, so we can't just check o.style()->hasPadding(). + if (o.isRenderMathMLBlock() && (box.paddingTop() || box.paddingRight() || box.paddingBottom() || box.paddingLeft())) { + ts << " ["; + LayoutUnit cssTop = box.computedCSSPaddingTop(); + LayoutUnit cssRight = box.computedCSSPaddingRight(); + LayoutUnit cssBottom = box.computedCSSPaddingBottom(); + LayoutUnit cssLeft = box.computedCSSPaddingLeft(); + if (box.paddingTop() != cssTop || box.paddingRight() != cssRight || box.paddingBottom() != cssBottom || box.paddingLeft() != cssLeft) { + ts << "intrinsic "; + if (cssTop || cssRight || cssBottom || cssLeft) + ts << "+ CSS "; + } + ts << "padding: " << roundToInt(box.paddingTop()) << " " << roundToInt(box.paddingRight()) << " " << roundToInt(box.paddingBottom()) << " " << roundToInt(box.paddingLeft()) << "]"; + } +#endif } if (o.isTableCell()) { diff --git a/Source/WebCore/rendering/RenderView.cpp b/Source/WebCore/rendering/RenderView.cpp index aadb9b9b5..d497a33ab 100644 --- a/Source/WebCore/rendering/RenderView.cpp +++ b/Source/WebCore/rendering/RenderView.cpp @@ -44,6 +44,10 @@ #include "RenderLayerCompositor.h" #endif +#if ENABLE(CSS_SHADERS) && ENABLE(WEBGL) +#include "CustomFilterGlobalContext.h" +#endif + namespace WebCore { RenderView::RenderView(Node* node, FrameView* view) @@ -390,7 +394,7 @@ void RenderView::computeRectForRepaint(RenderBoxModelObject* repaintContainer, L } if (fixed && m_frameView) - rect.move(m_frameView->scrollXForFixedPosition(), m_frameView->scrollYForFixedPosition()); + rect.move(m_frameView->scrollOffsetForFixedPosition()); // Apply our transform if we have one (because of full page zooming). if (!repaintContainer && m_layer && m_layer->transform()) @@ -656,8 +660,7 @@ bool RenderView::shouldUsePrintingLayout() const if (!printing() || !m_frameView) return false; Frame* frame = m_frameView->frame(); - // Only root frame should have special handling for printing. - return frame && !frame->tree()->parent(); + return frame && frame->shouldUsePrintingLayout(); } size_t RenderView::getRetainedWidgets(Vector<RenderWidget*>& renderWidgets) @@ -899,6 +902,15 @@ void RenderView::willMoveOffscreen() #endif } +#if ENABLE(CSS_SHADERS) && ENABLE(WEBGL) +CustomFilterGlobalContext* RenderView::customFilterGlobalContext() +{ + if (!m_customFilterGlobalContext) + m_customFilterGlobalContext = adoptPtr(new CustomFilterGlobalContext()); + return m_customFilterGlobalContext.get(); +} +#endif + void RenderView::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { RenderBlock::styleDidChange(diff, oldStyle); @@ -946,20 +958,4 @@ void RenderView::setFixedPositionedObjectsNeedLayout() } } -void RenderView::insertFixedPositionedObject(RenderBox* object) -{ - if (!m_positionedObjects) - m_positionedObjects = adoptPtr(new PositionedObjectsListHashSet); - - m_positionedObjects->add(object); -} - -void RenderView::removeFixedPositionedObject(RenderBox* object) -{ - if (!m_positionedObjects) - return; - - m_positionedObjects->remove(object); -} - } // namespace WebCore diff --git a/Source/WebCore/rendering/RenderView.h b/Source/WebCore/rendering/RenderView.h index e6a5722d8..8e5bc3c5a 100644 --- a/Source/WebCore/rendering/RenderView.h +++ b/Source/WebCore/rendering/RenderView.h @@ -37,6 +37,10 @@ class RenderWidget; class RenderLayerCompositor; #endif +#if ENABLE(CSS_SHADERS) && ENABLE(WEBGL) +class CustomFilterGlobalContext; +#endif + class RenderView : public RenderBlock { public: RenderView(Node*, FrameView*); @@ -168,6 +172,10 @@ public: bool usesCompositing() const; #endif +#if ENABLE(CSS_SHADERS) && ENABLE(WEBGL) + CustomFilterGlobalContext* customFilterGlobalContext(); +#endif + IntRect unscaledDocumentRect() const; LayoutRect backgroundRect(RenderBox* backgroundRenderer) const; @@ -183,8 +191,6 @@ public: IntSize viewportSize() const { return document()->viewportSize(); } void setFixedPositionedObjectsNeedLayout(); - void insertFixedPositionedObject(RenderBox*); - void removeFixedPositionedObject(RenderBox*); protected: virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const; @@ -276,6 +282,9 @@ private: #if USE(ACCELERATED_COMPOSITING) OwnPtr<RenderLayerCompositor> m_compositor; #endif +#if ENABLE(CSS_SHADERS) && ENABLE(WEBGL) + OwnPtr<CustomFilterGlobalContext> m_customFilterGlobalContext; +#endif OwnPtr<FlowThreadController> m_flowThreadController; RefPtr<IntervalArena> m_intervalArena; }; diff --git a/Source/WebCore/rendering/RenderingAllInOne.cpp b/Source/WebCore/rendering/RenderingAllInOne.cpp index d17bd313a..1f0a4a38e 100644 --- a/Source/WebCore/rendering/RenderingAllInOne.cpp +++ b/Source/WebCore/rendering/RenderingAllInOne.cpp @@ -91,6 +91,7 @@ #include "RenderScrollbar.cpp" #include "RenderScrollbarPart.cpp" #include "RenderScrollbarTheme.cpp" +#include "RenderSearchField.cpp" #include "RenderSlider.cpp" #include "RenderTable.cpp" #include "RenderTableCaption.cpp" diff --git a/Source/WebCore/rendering/TableLayout.h b/Source/WebCore/rendering/TableLayout.h index a72bfeff3..750768347 100644 --- a/Source/WebCore/rendering/TableLayout.h +++ b/Source/WebCore/rendering/TableLayout.h @@ -42,6 +42,8 @@ public: virtual void layout() = 0; protected: + const static int tableMaxWidth = 15000; + RenderTable* m_table; }; diff --git a/Source/WebCore/rendering/break_lines.cpp b/Source/WebCore/rendering/break_lines.cpp index 7522ccb3e..4bba3ce7e 100644 --- a/Source/WebCore/rendering/break_lines.cpp +++ b/Source/WebCore/rendering/break_lines.cpp @@ -121,32 +121,21 @@ COMPILE_ASSERT(WTF_ARRAY_LENGTH(asciiLineBreakTable) == asciiLineBreakTableLastC static inline bool shouldBreakAfter(UChar lastCh, UChar ch, UChar nextCh) { - switch (ch) { - case ideographicComma: - case ideographicFullStop: - // FIXME: cases for ideographicComma and ideographicFullStop are a workaround for an issue in Unicode 5.0 - // which is likely to be resolved in Unicode 5.1 <http://bugs.webkit.org/show_bug.cgi?id=17411>. - // We may want to remove or conditionalize this workaround at some point. - return true; - case '-': - if (isASCIIDigit(nextCh)) { - // Don't allow line breaking between '-' and a digit if the '-' may mean a minus sign in the context, - // while allow breaking in 'ABCD-1234' and '1234-5678' which may be in long URLs. - return isASCIIAlphanumeric(lastCh); - } - // Fall through - default: - // If both ch and nextCh are ASCII characters, use a lookup table for enhanced speed and for compatibility - // with other browsers (see comments for asciiLineBreakTable for details). - if (ch >= asciiLineBreakTableFirstChar && ch <= asciiLineBreakTableLastChar - && nextCh >= asciiLineBreakTableFirstChar && nextCh <= asciiLineBreakTableLastChar) { - const unsigned char* tableRow = asciiLineBreakTable[ch - asciiLineBreakTableFirstChar]; - int nextChIndex = nextCh - asciiLineBreakTableFirstChar; - return tableRow[nextChIndex / 8] & (1 << (nextChIndex % 8)); - } - // Otherwise defer to the Unicode algorithm by returning false. - return false; + // Don't allow line breaking between '-' and a digit if the '-' may mean a minus sign in the context, + // while allow breaking in 'ABCD-1234' and '1234-5678' which may be in long URLs. + if (ch == '-' && isASCIIDigit(nextCh)) + return isASCIIAlphanumeric(lastCh); + + // If both ch and nextCh are ASCII characters, use a lookup table for enhanced speed and for compatibility + // with other browsers (see comments for asciiLineBreakTable for details). + if (ch >= asciiLineBreakTableFirstChar && ch <= asciiLineBreakTableLastChar + && nextCh >= asciiLineBreakTableFirstChar && nextCh <= asciiLineBreakTableLastChar) { + const unsigned char* tableRow = asciiLineBreakTable[ch - asciiLineBreakTableFirstChar]; + int nextChIndex = nextCh - asciiLineBreakTableFirstChar; + return tableRow[nextChIndex / 8] & (1 << (nextChIndex % 8)); } + // Otherwise defer to the Unicode algorithm by returning false. + return false; } static inline bool needsLineBreakIterator(UChar ch) diff --git a/Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp b/Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp index d944eda2f..a4f927407 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. + * Copyright (C) 2012 David Barton (dbarton@mathscribe.com). All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -146,10 +147,10 @@ void RenderMathMLBlock::computePreferredLogicalWidths() RenderBlock::computePreferredLogicalWidths(); } -RenderMathMLBlock* RenderMathMLBlock::createAlmostAnonymousBlock(EDisplay display) +RenderMathMLBlock* RenderMathMLBlock::createAnonymousMathMLBlock(EDisplay display) { RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), display); - RenderMathMLBlock* newBlock = new (renderArena()) RenderMathMLBlock(node() /* "almost" anonymous block */); + RenderMathMLBlock* newBlock = new (renderArena()) RenderMathMLBlock(document() /* is anonymous */); newBlock->setStyle(newStyle.release()); return newBlock; } @@ -196,6 +197,18 @@ LayoutUnit RenderMathMLBlock::preferredLogicalHeightAfterSizing(RenderObject* ch return child->style()->fontSize(); } +const char* RenderMathMLBlock::renderName() const +{ + EDisplay display = style()->display(); + if (display == BLOCK) + return isAnonymous() ? "RenderMathMLBlock (anonymous, block)" : "RenderMathMLBlock (block)"; + if (display == INLINE_BLOCK) + return isAnonymous() ? "RenderMathMLBlock (anonymous, inline-block)" : "RenderMathMLBlock (inline-block)"; + // |display| should be one of the above. + ASSERT_NOT_REACHED(); + return isAnonymous() ? "RenderMathMLBlock (anonymous)" : "RenderMathMLBlock"; +} + #if ENABLE(DEBUG_MATH_LAYOUT) void RenderMathMLBlock::paint(PaintInfo& info, const LayoutPoint& paintOffset) { diff --git a/Source/WebCore/rendering/mathml/RenderMathMLBlock.h b/Source/WebCore/rendering/mathml/RenderMathMLBlock.h index 634d0a6dc..45f729643 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLBlock.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLBlock.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Alex Milowski (alex@milowski.com). All rights reserved. + * Copyright (C) 2012 David Barton (dbarton@mathscribe.com). All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -79,9 +80,8 @@ public: virtual void paint(PaintInfo&, const LayoutPoint&); #endif - // Create a new RenderBlock, with a new style inheriting from this->style(). - // FIXME: Create a true anonymous block, like RenderBlock::createAnonymousBlock(). - RenderMathMLBlock* createAlmostAnonymousBlock(EDisplay = BLOCK); + // Create a new RenderMathMLBlock, with a new style inheriting from this->style(). + RenderMathMLBlock* createAnonymousMathMLBlock(EDisplay = BLOCK); protected: static LayoutUnit getBoxModelObjectHeight(const RenderObject* object) @@ -104,7 +104,7 @@ protected: } private: - virtual const char* renderName() const { return isAnonymous() ? "RenderMathMLBlock (anonymous)" : "RenderMathMLBlock"; } + virtual const char* renderName() const OVERRIDE; protected: // Set our logical width to a large value, and compute our children's preferred logical heights. diff --git a/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp b/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp index 351f99e84..68c2b0533 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp @@ -81,22 +81,19 @@ void RenderMathMLFenced::updateFromElement() makeFences(); } -PassRefPtr<RenderStyle> RenderMathMLFenced::createOperatorStyle() +RenderMathMLOperator* RenderMathMLFenced::createMathMLOperator(UChar uChar) { - RefPtr<RenderStyle> newStyle = RenderStyle::create(); - newStyle->inheritFrom(style()); - newStyle->setDisplay(INLINE_BLOCK); + RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), INLINE_BLOCK); newStyle->setPaddingRight(Length(static_cast<int>(gOperatorPadding * style()->fontSize()), Fixed)); - return newStyle.release(); + RenderMathMLOperator* newOperator = new (renderArena()) RenderMathMLOperator(node() /* "almost anonymous" */, uChar); + newOperator->setStyle(newStyle.release()); + return newOperator; } void RenderMathMLFenced::makeFences() { - RenderObject* openFence = new (renderArena()) RenderMathMLOperator(node(), m_open); - openFence->setStyle(createOperatorStyle()); - RenderBlock::addChild(openFence, firstChild()); - m_closeFenceRenderer = new (renderArena()) RenderMathMLOperator(node(), m_close); - m_closeFenceRenderer->setStyle(createOperatorStyle()); + RenderBlock::addChild(createMathMLOperator(m_open), firstChild()); + m_closeFenceRenderer = createMathMLOperator(m_close); RenderBlock::addChild(m_closeFenceRenderer); } @@ -131,15 +128,14 @@ void RenderMathMLFenced::addChild(RenderObject* child, RenderObject* beforeChild else separator = (*m_separators.get())[count - 1]; - separatorRenderer = new (renderArena()) RenderMathMLOperator(node(), separator); - separatorRenderer->setStyle(createOperatorStyle()); + separatorRenderer = createMathMLOperator(separator); } } // If we have a block, we'll wrap it in an inline-block. if (child->isBlockFlow() && child->style()->display() != INLINE_BLOCK) { // Block objects wrapper. - RenderBlock* block = createAlmostAnonymousBlock(INLINE_BLOCK); + RenderMathMLBlock* block = createAnonymousMathMLBlock(INLINE_BLOCK); block->addChild(child); child = block; @@ -158,6 +154,20 @@ void RenderMathMLFenced::addChild(RenderObject* child, RenderObject* beforeChild } } +// FIXME: Change createMathMLOperator() above to create an isAnonymous() operator, and remove this styleDidChange() function. +void RenderMathMLFenced::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) +{ + RenderMathMLBlock::styleDidChange(diff, oldStyle); + + for (RenderObject* child = firstChild(); child; child = child->nextSibling()) { + if (child->node() == node()) { + ASSERT(child->style()->refCount() == 1); + child->style()->inheritFrom(style()); + child->style()->setPaddingRight(Length(static_cast<int>(gOperatorPadding * style()->fontSize()), Fixed)); + } + } +} + } #endif diff --git a/Source/WebCore/rendering/mathml/RenderMathMLFenced.h b/Source/WebCore/rendering/mathml/RenderMathMLFenced.h index 75324dcdc..987bb1343 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLFenced.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLFenced.h @@ -41,9 +41,11 @@ public: private: virtual const char* renderName() const { return "RenderMathMLFenced"; } - PassRefPtr<RenderStyle> createOperatorStyle(); + RenderMathMLOperator* createMathMLOperator(UChar); void makeFences(); + virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE; + UChar m_open; UChar m_close; RefPtr<StringImpl> m_separators; diff --git a/Source/WebCore/rendering/mathml/RenderMathMLFraction.cpp b/Source/WebCore/rendering/mathml/RenderMathMLFraction.cpp index 296548a2e..ffc4f1bc8 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLFraction.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLFraction.cpp @@ -50,9 +50,19 @@ RenderMathMLFraction::RenderMathMLFraction(Element* element) : RenderMathMLBlock(element) , m_lineThickness(gLineMedium) { - setChildrenInline(false); } +void RenderMathMLFraction::fixChildStyle(RenderObject* child) +{ + ASSERT(child->isAnonymous() && child->style()->refCount() == 1); + child->style()->setTextAlign(CENTER); + Length pad(static_cast<int>(style()->fontSize() * gHorizontalPad), Fixed); + child->style()->setPaddingLeft(pad); + child->style()->setPaddingRight(pad); +} + +// FIXME: It's cleaner to only call updateFromElement when an attribute has changed. Move parts +// of this to fixChildStyle or other methods, and call them when needed. void RenderMathMLFraction::updateFromElement() { // FIXME: mfrac where bevelled=true will need to reorganize the descendants @@ -100,20 +110,21 @@ void RenderMathMLFraction::updateFromElement() void RenderMathMLFraction::addChild(RenderObject* child, RenderObject* beforeChild) { - RenderBlock* row = createAlmostAnonymousBlock(); - - row->style()->setTextAlign(CENTER); - Length pad(static_cast<int>(style()->fontSize() * gHorizontalPad), Fixed); - row->style()->setPaddingLeft(pad); - row->style()->setPaddingRight(pad); - - // Only add padding for rows as denominators - bool isNumerator = isEmpty(); - if (!isNumerator) - row->style()->setPaddingTop(Length(2, Fixed)); + RenderMathMLBlock* row = createAnonymousMathMLBlock(); RenderBlock::addChild(row, beforeChild); row->addChild(child); + + fixChildStyle(row); + updateFromElement(); +} + +void RenderMathMLFraction::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) +{ + RenderMathMLBlock::styleDidChange(diff, oldStyle); + + for (RenderObject* child = firstChild(); child; child = child->nextSibling()) + fixChildStyle(child); updateFromElement(); } diff --git a/Source/WebCore/rendering/mathml/RenderMathMLFraction.h b/Source/WebCore/rendering/mathml/RenderMathMLFraction.h index 4756583b6..eedc7f356 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLFraction.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLFraction.h @@ -47,6 +47,9 @@ protected: virtual void layout(); private: + void fixChildStyle(RenderObject* child); + virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE; + virtual const char* renderName() const { return "RenderMathMLFraction"; } float m_lineThickness; diff --git a/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp b/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp index 50f02be59..1160aa1cf 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp @@ -70,6 +70,14 @@ void RenderMathMLOperator::stretchToHeight(int height) updateFromElement(); } +void RenderMathMLOperator::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) +{ + RenderMathMLBlock::styleDidChange(diff, oldStyle); + + if (firstChild()) + updateFromElement(); +} + void RenderMathMLOperator::computePreferredLogicalWidths() { ASSERT(preferredLogicalWidthsDirty()); @@ -150,6 +158,10 @@ int RenderMathMLOperator::lineHeightForCharacter(UChar character) return gGlyphLineHeight; } +// FIXME: It's cleaner to only call updateFromElement when an attribute has changed. The body of +// this method should probably be moved to a private stretchHeightChanged or checkStretchHeight +// method. Probably at the same time, addChild/removeChild methods should be made to work for +// dynamic DOM changes. void RenderMathMLOperator::updateFromElement() { RenderObject* savedRenderer = node()->renderer(); diff --git a/Source/WebCore/rendering/mathml/RenderMathMLOperator.h b/Source/WebCore/rendering/mathml/RenderMathMLOperator.h index 5adab8fd1..42ed2bee6 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLOperator.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLOperator.h @@ -58,6 +58,8 @@ private: int glyphHeightForCharacter(UChar); int lineHeightForCharacter(UChar); + virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE; + int m_stretchHeight; bool m_isStacked; UChar m_operator; diff --git a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h index b0270efbb..cbb2c5706 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h @@ -41,8 +41,6 @@ public: private: virtual const char* renderName() const { return "RenderMathMLSquareRoot"; } - - virtual bool createsAnonymousWrapper() const OVERRIDE { return true; } }; } diff --git a/Source/WebCore/rendering/mathml/RenderMathMLSubSup.cpp b/Source/WebCore/rendering/mathml/RenderMathMLSubSup.cpp index 5342cbd84..da406003a 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLSubSup.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLSubSup.cpp @@ -63,6 +63,17 @@ RenderBoxModelObject* RenderMathMLSubSup::base() const return toRenderBoxModelObject(base); } +void RenderMathMLSubSup::fixScriptsStyle() +{ + ASSERT(m_scripts && m_scripts->style()->refCount() == 1); + RenderStyle* scriptsStyle = m_scripts->style(); + scriptsStyle->setVerticalAlign(TOP); + scriptsStyle->setMarginLeft(Length(gSubsupScriptMargin, Fixed)); + scriptsStyle->setTextAlign(LEFT); + // Set this wrapper's font-size for its line-height & baseline position, for its children. + scriptsStyle->setBlendedFontSize(static_cast<int>(0.75 * style()->fontSize())); +} + void RenderMathMLSubSup::addChild(RenderObject* child, RenderObject* beforeChild) { // Note: The RenderMathMLBlock only allows element children to be added. @@ -70,20 +81,14 @@ void RenderMathMLSubSup::addChild(RenderObject* child, RenderObject* beforeChild if (childElement && !childElement->previousElementSibling()) { // Position 1 is always the base of the msub/msup/msubsup. - RenderBlock* baseWrapper = createAlmostAnonymousBlock(INLINE_BLOCK); + RenderMathMLBlock* baseWrapper = createAnonymousMathMLBlock(INLINE_BLOCK); RenderMathMLBlock::addChild(baseWrapper, firstChild()); baseWrapper->addChild(child); // Make sure we have a script block for rendering. if (m_kind == SubSup && !m_scripts) { - RefPtr<RenderStyle> scriptsStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), INLINE_BLOCK); - scriptsStyle->setVerticalAlign(TOP); - scriptsStyle->setMarginLeft(Length(gSubsupScriptMargin, Fixed)); - scriptsStyle->setTextAlign(LEFT); - // Set this wrapper's font-size for its line-height & baseline position. - scriptsStyle->setBlendedFontSize(static_cast<int>(0.75 * style()->fontSize())); - m_scripts = new (renderArena()) RenderMathMLBlock(node()); - m_scripts->setStyle(scriptsStyle); + m_scripts = createAnonymousMathMLBlock(INLINE_BLOCK); + fixScriptsStyle(); RenderMathMLBlock::addChild(m_scripts, beforeChild); } } else { @@ -92,7 +97,7 @@ void RenderMathMLSubSup::addChild(RenderObject* child, RenderObject* beforeChild if (!childElement) return; - RenderBlock* script = m_scripts->createAlmostAnonymousBlock(); + RenderMathMLBlock* script = m_scripts->createAnonymousMathMLBlock(); // The order is always backwards so the first script is the subscript and the superscript // is last. That means the superscript is the first to render vertically. @@ -108,6 +113,19 @@ void RenderMathMLSubSup::addChild(RenderObject* child, RenderObject* beforeChild } } +void RenderMathMLSubSup::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) +{ + RenderMathMLBlock::styleDidChange(diff, oldStyle); + + if (m_scripts) { + fixScriptsStyle(); + for (RenderObject* script = m_scripts->firstChild(); script; script = script->nextSibling()) { + ASSERT(script->isAnonymous() && script->style()->refCount() == 1); + script->style()->inheritFrom(m_scripts->style()); + } + } +} + RenderMathMLOperator* RenderMathMLSubSup::unembellishedOperator() { RenderBoxModelObject* base = this->base(); diff --git a/Source/WebCore/rendering/mathml/RenderMathMLSubSup.h b/Source/WebCore/rendering/mathml/RenderMathMLSubSup.h index c88fe663b..f906d48ca 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLSubSup.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLSubSup.h @@ -44,6 +44,9 @@ protected: virtual void layout(); private: + void fixScriptsStyle(); + virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE; + virtual const char* renderName() const { return "RenderMathMLSubSup"; } // Omit our subscript and/or superscript. This may return 0 for a non-MathML base (which diff --git a/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.cpp b/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.cpp index 03c9c31ef..272032db6 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.cpp @@ -66,7 +66,7 @@ RenderBoxModelObject* RenderMathMLUnderOver::base() const void RenderMathMLUnderOver::addChild(RenderObject* child, RenderObject* beforeChild) { - RenderBlock* row = createAnonymousBlock(); + RenderMathMLBlock* row = createAnonymousMathMLBlock(); // look through the children for rendered elements counting the blocks so we know what child // we are adding @@ -84,7 +84,6 @@ void RenderMathMLUnderOver::addChild(RenderObject* child, RenderObject* beforeCh break; case 1: // the under or over - // FIXME: text-align: center does not work row->style()->setTextAlign(CENTER); if (m_kind == Over) { // add the over as first @@ -96,7 +95,6 @@ void RenderMathMLUnderOver::addChild(RenderObject* child, RenderObject* beforeCh break; case 2: // the under or over - // FIXME: text-align: center does not work row->style()->setTextAlign(CENTER); if (m_kind == UnderOver) { // add the over as first @@ -115,6 +113,18 @@ void RenderMathMLUnderOver::addChild(RenderObject* child, RenderObject* beforeCh row->addChild(child); } +void RenderMathMLUnderOver::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) +{ + RenderMathMLBlock::styleDidChange(diff, oldStyle); + + RenderObject* base = this->base(); + for (RenderObject* child = firstChild(); child; child = child->nextSibling()) { + ASSERT(child->isAnonymous() && child->style()->refCount() == 1); + if (child->firstChild() != base) + child->style()->setTextAlign(CENTER); + } +} + RenderMathMLOperator* RenderMathMLUnderOver::unembellishedOperator() { RenderBoxModelObject* base = this->base(); diff --git a/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h b/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h index 3a4f70d76..b450689c9 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h @@ -38,10 +38,13 @@ public: virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); virtual RenderMathMLOperator* unembellishedOperator(); + virtual void layout(); virtual LayoutUnit baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; private: + virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE; + virtual const char* renderName() const { return "RenderMathMLUnderOver"; } // Omit our underscript and/or overscript. This may return 0 for a non-MathML base (which diff --git a/Source/WebCore/rendering/style/KeyframeList.h b/Source/WebCore/rendering/style/KeyframeList.h index fb352f9fd..5101b0689 100644 --- a/Source/WebCore/rendering/style/KeyframeList.h +++ b/Source/WebCore/rendering/style/KeyframeList.h @@ -62,9 +62,8 @@ private: class KeyframeList { public: - KeyframeList(RenderObject* renderer, const AtomicString& animationName) + KeyframeList(RenderObject*, const AtomicString& animationName) : m_animationName(animationName) - , m_renderer(renderer) { insert(KeyframeValue(0, 0)); insert(KeyframeValue(1, 0)); @@ -92,7 +91,6 @@ private: AtomicString m_animationName; Vector<KeyframeValue> m_keyframes; // Kept sorted by key. HashSet<CSSPropertyID> m_properties; // The properties being animated. - RenderObject* m_renderer; }; } // namespace WebCore diff --git a/Source/WebCore/rendering/style/RenderStyle.cpp b/Source/WebCore/rendering/style/RenderStyle.cpp index af6736704..36c5ed40e 100644 --- a/Source/WebCore/rendering/style/RenderStyle.cpp +++ b/Source/WebCore/rendering/style/RenderStyle.cpp @@ -139,7 +139,6 @@ ALWAYS_INLINE RenderStyle::RenderStyle(bool) rareNonInheritedData.access()->m_gridItem.init(); rareInheritedData.init(); inherited.init(); - #if ENABLE(SVG) m_svgStyle.init(); #endif @@ -162,9 +161,15 @@ ALWAYS_INLINE RenderStyle::RenderStyle(const RenderStyle& o) { } -void RenderStyle::inheritFrom(const RenderStyle* inheritParent) +void RenderStyle::inheritFrom(const RenderStyle* inheritParent, IsAtShadowBoundary isAtShadowBoundary) { - rareInheritedData = inheritParent->rareInheritedData; + if (isAtShadowBoundary == AtShadowBoundary) { + // Even if surrounding content is user-editable, shadow DOM should act as a single unit, and not necessarily be editable + EUserModify currentUserModify = userModify(); + rareInheritedData = inheritParent->rareInheritedData; + setUserModify(currentUserModify); + } else + rareInheritedData = inheritParent->rareInheritedData; inherited = inheritParent->inherited; inherited_flags = inheritParent->inherited_flags; #if ENABLE(SVG) @@ -396,6 +401,12 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon if (rareNonInheritedData->m_flexibleBox.get() != other->rareNonInheritedData->m_flexibleBox.get() && *rareNonInheritedData->m_flexibleBox.get() != *other->rareNonInheritedData->m_flexibleBox.get()) return StyleDifferenceLayout; + if (rareNonInheritedData->m_order != other->rareNonInheritedData->m_order + || rareNonInheritedData->m_alignContent != other->rareNonInheritedData->m_alignContent + || rareNonInheritedData->m_alignItems != other->rareNonInheritedData->m_alignItems + || rareNonInheritedData->m_alignSelf != other->rareNonInheritedData->m_alignSelf + || rareNonInheritedData->m_justifyContent != other->rareNonInheritedData->m_justifyContent) + return StyleDifferenceLayout; // FIXME: We should add an optimized form of layout that just recomputes visual overflow. if (!rareNonInheritedData->shadowDataEquivalent(*other->rareNonInheritedData.get())) @@ -461,6 +472,10 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon || rareInheritedData->m_tabSize != other->rareInheritedData->m_tabSize || rareInheritedData->m_lineBoxContain != other->rareInheritedData->m_lineBoxContain || rareInheritedData->m_lineGrid != other->rareInheritedData->m_lineGrid +#if ENABLE(CSS_IMAGE_RESOLUTION) + || rareInheritedData->m_imageResolutionSource != other->rareInheritedData->m_imageResolutionSource + || rareInheritedData->m_imageResolution != other->rareInheritedData->m_imageResolution +#endif || rareInheritedData->m_lineSnap != other->rareInheritedData->m_lineSnap || rareInheritedData->m_lineAlign != other->rareInheritedData->m_lineAlign) return StyleDifferenceLayout; diff --git a/Source/WebCore/rendering/style/RenderStyle.h b/Source/WebCore/rendering/style/RenderStyle.h index 7b1127677..947c6075f 100644 --- a/Source/WebCore/rendering/style/RenderStyle.h +++ b/Source/WebCore/rendering/style/RenderStyle.h @@ -390,7 +390,12 @@ public: static PassRefPtr<RenderStyle> createAnonymousStyleWithDisplay(const RenderStyle* parentStyle, EDisplay); static PassRefPtr<RenderStyle> clone(const RenderStyle*); - void inheritFrom(const RenderStyle* inheritParent); + enum IsAtShadowBoundary { + AtShadowBoundary, + NotAtShadowBoundary, + }; + + void inheritFrom(const RenderStyle* inheritParent, IsAtShadowBoundary = NotAtShadowBoundary); void copyNonInheritedFrom(const RenderStyle*); PseudoId styleType() const { return static_cast<PseudoId>(noninherited_flags._styleType); } @@ -402,6 +407,11 @@ public: const PseudoStyleCache* cachedPseudoStyles() const { return m_cachedPseudoStyles.get(); } +#if ENABLE(CSS_VARIABLES) + void setVariable(const AtomicString& name, const String& value) { rareInheritedData.access()->m_variables.access()->setVariable(name, value); } + const HashMap<AtomicString, String>* variables() { return &(rareInheritedData->m_variables->m_data); } +#endif + bool affectedByHoverRules() const { return noninherited_flags.affectedByHover(); } bool affectedByActiveRules() const { return noninherited_flags.affectedByActive(); } bool affectedByDragRules() const { return noninherited_flags.affectedByDrag(); } @@ -804,18 +814,18 @@ public: EBoxOrient boxOrient() const { return static_cast<EBoxOrient>(rareNonInheritedData->m_deprecatedFlexibleBox->orient); } EBoxPack boxPack() const { return static_cast<EBoxPack>(rareNonInheritedData->m_deprecatedFlexibleBox->pack); } - int order() const { return rareNonInheritedData->m_order; } - float positiveFlex() const { return rareNonInheritedData->m_flexibleBox->m_positiveFlex; } - float negativeFlex() const { return rareNonInheritedData->m_flexibleBox->m_negativeFlex; } - Length flexPreferredSize() const { return rareNonInheritedData->m_flexibleBox->m_preferredSize; } - EFlexPack flexPack() const { return static_cast<EFlexPack>(rareNonInheritedData->m_flexibleBox->m_flexPack); } + float order() const { return rareNonInheritedData->m_order; } + float flexGrow() const { return rareNonInheritedData->m_flexibleBox->m_flexGrow; } + float flexShrink() const { return rareNonInheritedData->m_flexibleBox->m_flexShrink; } + Length flexBasis() const { return rareNonInheritedData->m_flexibleBox->m_flexBasis; } + EAlignContent alignContent() const { return static_cast<EAlignContent>(rareNonInheritedData->m_alignContent); } EAlignItems alignItems() const { return static_cast<EAlignItems>(rareNonInheritedData->m_alignItems); } EAlignItems alignSelf() const { return static_cast<EAlignItems>(rareNonInheritedData->m_alignSelf); } EFlexDirection flexDirection() const { return static_cast<EFlexDirection>(rareNonInheritedData->m_flexibleBox->m_flexDirection); } bool isColumnFlexDirection() const { return flexDirection() == FlowColumn || flexDirection() == FlowColumnReverse; } bool isReverseFlexDirection() const { return flexDirection() == FlowRowReverse || flexDirection() == FlowColumnReverse; } EFlexWrap flexWrap() const { return static_cast<EFlexWrap>(rareNonInheritedData->m_flexibleBox->m_flexWrap); } - EFlexLinePack flexLinePack() const { return static_cast<EFlexLinePack>(rareNonInheritedData->m_flexibleBox->m_flexLinePack); } + EJustifyContent justifyContent() const { return static_cast<EJustifyContent>(rareNonInheritedData->m_justifyContent); } const Vector<Length>& gridColumns() const { return rareNonInheritedData->m_grid->m_gridColumns; } const Vector<Length>& gridRows() const { return rareNonInheritedData->m_grid->m_gridRows; } @@ -830,7 +840,9 @@ public: void getBoxShadowInlineDirectionExtent(LayoutUnit& logicalLeft, LayoutUnit& logicalRight) { getShadowInlineDirectionExtent(boxShadow(), logicalLeft, logicalRight); } void getBoxShadowBlockDirectionExtent(LayoutUnit& logicalTop, LayoutUnit& logicalBottom) { getShadowBlockDirectionExtent(boxShadow(), logicalTop, logicalBottom); } +#if ENABLE(CSS_BOX_DECORATION_BREAK) EBoxDecorationBreak boxDecorationBreak() const { return m_box->boxDecorationBreak(); } +#endif StyleReflection* boxReflect() const { return rareNonInheritedData->m_boxReflect.get(); } EBoxSizing boxSizing() const { return m_box->boxSizing(); } Length marqueeIncrement() const { return rareNonInheritedData->m_marquee->increment; } @@ -848,7 +860,6 @@ public: EWordWrap wordWrap() const { return static_cast<EWordWrap>(rareInheritedData->wordWrap); } ENBSPMode nbspMode() const { return static_cast<ENBSPMode>(rareInheritedData->nbspMode); } EKHTMLLineBreak khtmlLineBreak() const { return static_cast<EKHTMLLineBreak>(rareInheritedData->khtmlLineBreak); } - EMatchNearestMailBlockquoteColor matchNearestMailBlockquoteColor() const { return static_cast<EMatchNearestMailBlockquoteColor>(rareNonInheritedData->matchNearestMailBlockquoteColor); } const AtomicString& highlight() const { return rareInheritedData->highlight; } Hyphens hyphens() const { return static_cast<Hyphens>(rareInheritedData->hyphens); } short hyphenationLimitBefore() const { return rareInheritedData->hyphenationLimitBefore; } @@ -863,6 +874,7 @@ public: ColumnAxis axis = columnAxis(); return axis == AutoColumnAxis || isHorizontalWritingMode() == (axis == HorizontalColumnAxis); } + ColumnProgression columnProgression() const { return static_cast<ColumnProgression>(rareNonInheritedData->m_multiCol->m_progression); } float columnWidth() const { return rareNonInheritedData->m_multiCol->m_width; } bool hasAutoColumnWidth() const { return rareNonInheritedData->m_multiCol->m_autoWidth; } unsigned short columnCount() const { return rareNonInheritedData->m_multiCol->m_count; } @@ -968,6 +980,11 @@ public: bool isFlippedBlocksWritingMode() const { return writingMode() == RightToLeftWritingMode || writingMode() == BottomToTopWritingMode; } EImageRendering imageRendering() const { return static_cast<EImageRendering>(rareInheritedData->m_imageRendering); } + +#if ENABLE(CSS_IMAGE_RESOLUTION) + ImageResolutionSource imageResolutionSource() const { return static_cast<ImageResolutionSource>(rareInheritedData->m_imageResolutionSource); } + float imageResolution() const { return rareInheritedData->m_imageResolution; } +#endif ESpeak speak() const { return static_cast<ESpeak>(rareInheritedData->speak); } @@ -1135,6 +1152,11 @@ public: bool setEffectiveZoom(float); void setImageRendering(EImageRendering v) { SET_VAR(rareInheritedData, m_imageRendering, v) } +#if ENABLE(CSS_IMAGE_RESOLUTION) + void setImageResolutionSource(ImageResolutionSource v) { SET_VAR(rareInheritedData, m_imageResolutionSource, v) } + void setImageResolution(float f) { SET_VAR(rareInheritedData, m_imageResolution, f) } +#endif + void setWhiteSpace(EWhiteSpace v) { inherited_flags._white_space = v; } void setWordSpacing(int v) { inherited.access()->font.setWordSpacing(v); } @@ -1235,7 +1257,9 @@ public: void setAppearance(ControlPart a) { SET_VAR(rareNonInheritedData, m_appearance, a); } // For valid values of box-align see http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/#alignment void setBoxAlign(EBoxAlignment a) { SET_VAR(rareNonInheritedData.access()->m_deprecatedFlexibleBox, align, a); } +#if ENABLE(CSS_BOX_DECORATION_BREAK) void setBoxDecorationBreak(EBoxDecorationBreak b) { SET_VAR(m_box, m_boxDecorationBreak, b); } +#endif void setBoxDirection(EBoxDirection d) { inherited_flags._box_direction = d; } void setBoxFlex(float f) { SET_VAR(rareNonInheritedData.access()->m_deprecatedFlexibleBox, flex, f); } void setBoxFlexGroup(unsigned int fg) { SET_VAR(rareNonInheritedData.access()->m_deprecatedFlexibleBox, flex_group, fg); } @@ -1246,16 +1270,16 @@ public: void setBoxShadow(PassOwnPtr<ShadowData>, bool add = false); void setBoxReflect(PassRefPtr<StyleReflection> reflect) { if (rareNonInheritedData->m_boxReflect != reflect) rareNonInheritedData.access()->m_boxReflect = reflect; } void setBoxSizing(EBoxSizing s) { SET_VAR(m_box, m_boxSizing, s); } - void setPositiveFlex(float f) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_positiveFlex, f); } - void setNegativeFlex(float f) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_negativeFlex, f); } - void setFlexPreferredSize(Length l) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_preferredSize, l); } - void setOrder(int o) { SET_VAR(rareNonInheritedData, m_order, o); } - void setFlexPack(EFlexPack p) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexPack, p); } + void setFlexGrow(float f) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexGrow, f); } + void setFlexShrink(float f) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexShrink, f); } + void setFlexBasis(Length length) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexBasis, length); } + void setOrder(float o) { SET_VAR(rareNonInheritedData, m_order, o); } + void setAlignContent(EAlignContent p) { SET_VAR(rareNonInheritedData, m_alignContent, p); } void setAlignItems(EAlignItems a) { SET_VAR(rareNonInheritedData, m_alignItems, a); } void setAlignSelf(EAlignItems a) { SET_VAR(rareNonInheritedData, m_alignSelf, a); } void setFlexDirection(EFlexDirection direction) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexDirection, direction); } void setFlexWrap(EFlexWrap w) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexWrap, w); } - void setFlexLinePack(EFlexLinePack p) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexLinePack, p); } + void setJustifyContent(EJustifyContent p) { SET_VAR(rareNonInheritedData, m_justifyContent, p); } void setGridColumns(const Vector<Length>& lengths) { SET_VAR(rareNonInheritedData.access()->m_grid, m_gridColumns, lengths); } void setGridRows(const Vector<Length>& lengths) { SET_VAR(rareNonInheritedData.access()->m_grid, m_gridRows, lengths); } void setGridItemColumn(const Length& columnPosition) { SET_VAR(rareNonInheritedData.access()->m_gridItem, m_gridColumn, columnPosition); } @@ -1276,7 +1300,6 @@ public: void setWordWrap(EWordWrap b) { SET_VAR(rareInheritedData, wordWrap, b); } void setNBSPMode(ENBSPMode b) { SET_VAR(rareInheritedData, nbspMode, b); } void setKHTMLLineBreak(EKHTMLLineBreak b) { SET_VAR(rareInheritedData, khtmlLineBreak, b); } - void setMatchNearestMailBlockquoteColor(EMatchNearestMailBlockquoteColor c) { SET_VAR(rareNonInheritedData, matchNearestMailBlockquoteColor, c); } void setHighlight(const AtomicString& h) { SET_VAR(rareInheritedData, highlight, h); } void setHyphens(Hyphens h) { SET_VAR(rareInheritedData, hyphens, h); } void setHyphenationLimitBefore(short limit) { SET_VAR(rareInheritedData, hyphenationLimitBefore, limit); } @@ -1287,6 +1310,7 @@ public: void setBorderFit(EBorderFit b) { SET_VAR(rareNonInheritedData, m_borderFit, b); } void setResize(EResize r) { SET_VAR(rareInheritedData, resize, r); } void setColumnAxis(ColumnAxis axis) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_axis, axis); } + void setColumnProgression(ColumnProgression progression) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_progression, progression); } void setColumnWidth(float f) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_autoWidth, false); SET_VAR(rareNonInheritedData.access()->m_multiCol, m_width, f); } void setHasAutoColumnWidth() { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_autoWidth, true); SET_VAR(rareNonInheritedData.access()->m_multiCol, m_width, 0); } void setColumnCount(unsigned short c) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_autoCount, false); SET_VAR(rareNonInheritedData.access()->m_multiCol, m_count, c); } @@ -1526,6 +1550,7 @@ public: static EClear initialClear() { return CNONE; } static ColorSpace initialColorSpace() { return ColorSpaceDeviceRGB; } static ColumnAxis initialColumnAxis() { return AutoColumnAxis; } + static ColumnProgression initialColumnProgression() { return NormalColumnProgression; } static TextDirection initialDirection() { return LTR; } static WritingMode initialWritingMode() { return TopToBottomWritingMode; } static TextCombine initialTextCombine() { return TextCombineNone; } @@ -1564,7 +1589,7 @@ public: static short initialWidows() { return 2; } static short initialOrphans() { return 2; } static Length initialLineHeight() { return Length(-100.0, Percent); } - static ETextAlign initialTextAlign() { return TAAUTO; } + static ETextAlign initialTextAlign() { return TASTART; } static ETextDecoration initialTextDecoration() { return TDNONE; } static float initialZoom() { return 1.0f; } static int initialOutlineOffset() { return 0; } @@ -1580,16 +1605,16 @@ public: static unsigned int initialBoxOrdinalGroup() { return 1; } static EBoxSizing initialBoxSizing() { return CONTENT_BOX; } static StyleReflection* initialBoxReflect() { return 0; } - static float initialPositiveFlex() { return 1; } - static float initialNegativeFlex() { return 1; } - static Length initialFlexPreferredSize() { return Length(Auto); } - static int initialOrder() { return 0; } - static EFlexPack initialFlexPack() { return PackStart; } + static float initialFlexGrow() { return 0; } + static float initialFlexShrink() { return 1; } + static Length initialFlexBasis() { return Length(Auto); } + static float initialOrder() { return 0; } + static EAlignContent initialAlignContent() { return AlignContentStretch; } static EAlignItems initialAlignItems() { return AlignStretch; } static EAlignItems initialAlignSelf() { return AlignAuto; } static EFlexDirection initialFlexDirection() { return FlowRow; } static EFlexWrap initialFlexWrap() { return FlexWrapNone; } - static EFlexLinePack initialFlexLinePack() { return LinePackStretch; } + static EJustifyContent initialJustifyContent() { return JustifyFlexStart; } static int initialMarqueeLoopCount() { return -1; } static int initialMarqueeSpeed() { return 85; } static Length initialMarqueeIncrement() { return Length(6, Fixed); } @@ -1605,7 +1630,6 @@ public: static EWordWrap initialWordWrap() { return NormalWordWrap; } static ENBSPMode initialNBSPMode() { return NBNORMAL; } static EKHTMLLineBreak initialKHTMLLineBreak() { return LBNORMAL; } - static EMatchNearestMailBlockquoteColor initialMatchNearestMailBlockquoteColor() { return BCNORMAL; } static const AtomicString& initialHighlight() { return nullAtom; } static ESpeak initialSpeak() { return SpeakNormal; } static Hyphens initialHyphens() { return HyphensManual; } @@ -1642,6 +1666,8 @@ public: static TextEmphasisPosition initialTextEmphasisPosition() { return TextEmphasisPositionOver; } static LineBoxContain initialLineBoxContain() { return LineBoxContainBlock | LineBoxContainInline | LineBoxContainReplaced; } static EImageRendering initialImageRendering() { return ImageRenderingAuto; } + static ImageResolutionSource initialImageResolutionSource() { return ImageResolutionSpecified; } + static float initialImageResolution() { return 1; } static StyleImage* initialBorderImageSource() { return 0; } static StyleImage* initialMaskBoxImageSource() { return 0; } static PrintColorAdjust initialPrintColorAdjust() { return PrintColorAdjustEconomy; } diff --git a/Source/WebCore/rendering/style/RenderStyleConstants.h b/Source/WebCore/rendering/style/RenderStyleConstants.h index 73e819489..1a5a57c70 100644 --- a/Source/WebCore/rendering/style/RenderStyleConstants.h +++ b/Source/WebCore/rendering/style/RenderStyleConstants.h @@ -173,11 +173,11 @@ enum EBoxDirection { BNORMAL, BREVERSE }; // CSS3 Flexbox Properties -enum EAlignItems { AlignAuto, AlignStart, AlignEnd, AlignCenter, AlignStretch, AlignBaseline }; -enum EFlexPack { PackStart, PackEnd, PackCenter, PackSpaceBetween, PackSpaceAround }; +enum EAlignContent { AlignContentFlexStart, AlignContentFlexEnd, AlignContentCenter, AlignContentSpaceBetween, AlignContentSpaceAround, AlignContentStretch }; +enum EAlignItems { AlignAuto, AlignFlexStart, AlignFlexEnd, AlignCenter, AlignStretch, AlignBaseline }; enum EFlexDirection { FlowRow, FlowRowReverse, FlowColumn, FlowColumnReverse }; -enum EFlexLinePack { LinePackStart, LinePackEnd, LinePackCenter, LinePackSpaceBetween, LinePackSpaceAround, LinePackStretch }; enum EFlexWrap { FlexWrapNone, FlexWrap, FlexWrapReverse }; +enum EJustifyContent { JustifyFlexStart, JustifyFlexEnd, JustifyCenter, JustifySpaceBetween, JustifySpaceAround }; enum ETextSecurity { TSNONE, TSDISC, TSCIRCLE, TSSQUARE @@ -219,10 +219,6 @@ enum EKHTMLLineBreak { LBNORMAL, AFTER_WHITE_SPACE }; -enum EMatchNearestMailBlockquoteColor { - BCNORMAL, MATCH -}; - enum EResize { RESIZE_NONE, RESIZE_BOTH, RESIZE_HORIZONTAL, RESIZE_VERTICAL }; @@ -335,7 +331,7 @@ enum EWhiteSpace { // The order of this enum must match the order of the text align values in CSSValueKeywords.in. enum ETextAlign { - TAAUTO, LEFT, RIGHT, CENTER, JUSTIFY, WEBKIT_LEFT, WEBKIT_RIGHT, WEBKIT_CENTER, TASTART, TAEND, + LEFT, RIGHT, CENTER, JUSTIFY, WEBKIT_LEFT, WEBKIT_RIGHT, WEBKIT_CENTER, TASTART, TAEND, }; enum ETextTransform { @@ -454,12 +450,16 @@ enum TextOverflow { TextOverflowClip = 0, TextOverflowEllipsis }; enum EImageRendering { ImageRenderingAuto, ImageRenderingOptimizeSpeed, ImageRenderingOptimizeQuality, ImageRenderingOptimizeContrast }; +enum ImageResolutionSource { ImageResolutionSpecified = 0, ImageResolutionFromImage }; + enum Order { LogicalOrder = 0, VisualOrder }; enum RegionOverflow { AutoRegionOverflow, BreakRegionOverflow }; enum ColumnAxis { HorizontalColumnAxis, VerticalColumnAxis, AutoColumnAxis }; +enum ColumnProgression { NormalColumnProgression, ReverseColumnProgression }; + enum LineSnap { LineSnapNone, LineSnapBaseline, LineSnapContain }; enum LineAlign { LineAlignNone, LineAlignEdges }; diff --git a/Source/WebCore/rendering/style/StyleBoxData.cpp b/Source/WebCore/rendering/style/StyleBoxData.cpp index fb9655c21..3fc00c8dc 100644 --- a/Source/WebCore/rendering/style/StyleBoxData.cpp +++ b/Source/WebCore/rendering/style/StyleBoxData.cpp @@ -27,6 +27,14 @@ namespace WebCore { +struct SameSizeAsStyleBoxData : public RefCounted<SameSizeAsStyleBoxData> { + Length length[7]; + int m_zIndex; + uint32_t bitfields; +}; + +COMPILE_ASSERT(sizeof(StyleBoxData) == sizeof(SameSizeAsStyleBoxData), StyleBoxData_should_not_grow); + StyleBoxData::StyleBoxData() : m_minWidth(RenderStyle::initialMinSize()) , m_maxWidth(RenderStyle::initialMaxSize()) @@ -35,7 +43,9 @@ StyleBoxData::StyleBoxData() , m_zIndex(0) , m_hasAutoZIndex(true) , m_boxSizing(CONTENT_BOX) +#if ENABLE(CSS_BOX_DECORATION_BREAK) , m_boxDecorationBreak(DSLICE) +#endif { } @@ -51,7 +61,9 @@ StyleBoxData::StyleBoxData(const StyleBoxData& o) , m_zIndex(o.m_zIndex) , m_hasAutoZIndex(o.m_hasAutoZIndex) , m_boxSizing(o.m_boxSizing) +#if ENABLE(CSS_BOX_DECORATION_BREAK) , m_boxDecorationBreak(o.m_boxDecorationBreak) +#endif { } @@ -67,7 +79,10 @@ bool StyleBoxData::operator==(const StyleBoxData& o) const && m_zIndex == o.m_zIndex && m_hasAutoZIndex == o.m_hasAutoZIndex && m_boxSizing == o.m_boxSizing - && m_boxDecorationBreak == o.m_boxDecorationBreak; +#if ENABLE(CSS_BOX_DECORATION_BREAK) + && m_boxDecorationBreak == o.m_boxDecorationBreak +#endif + ; } } // namespace WebCore diff --git a/Source/WebCore/rendering/style/StyleBoxData.h b/Source/WebCore/rendering/style/StyleBoxData.h index 2984d176b..86fd6e922 100644 --- a/Source/WebCore/rendering/style/StyleBoxData.h +++ b/Source/WebCore/rendering/style/StyleBoxData.h @@ -58,7 +58,9 @@ public: bool hasAutoZIndex() const { return m_hasAutoZIndex; } EBoxSizing boxSizing() const { return static_cast<EBoxSizing>(m_boxSizing); } +#if ENABLE(CSS_BOX_DECORATION_BREAK) EBoxDecorationBreak boxDecorationBreak() const { return static_cast<EBoxDecorationBreak>(m_boxDecorationBreak); } +#endif private: friend class RenderStyle; @@ -78,9 +80,11 @@ private: Length m_verticalAlign; int m_zIndex; - bool m_hasAutoZIndex : 1; + unsigned m_hasAutoZIndex : 1; unsigned m_boxSizing : 1; // EBoxSizing +#if ENABLE(CSS_BOX_DECORATION_BREAK) unsigned m_boxDecorationBreak : 1; // EBoxDecorationBreak +#endif }; } // namespace WebCore diff --git a/Source/WebCore/rendering/style/StyleCachedImage.cpp b/Source/WebCore/rendering/style/StyleCachedImage.cpp index a7a1996fa..2e3abb943 100644 --- a/Source/WebCore/rendering/style/StyleCachedImage.cpp +++ b/Source/WebCore/rendering/style/StyleCachedImage.cpp @@ -97,7 +97,7 @@ void StyleCachedImage::addClient(RenderObject* renderer) void StyleCachedImage::removeClient(RenderObject* renderer) { - m_image->removeClientForRenderer(renderer); + m_image->removeClient(renderer); } PassRefPtr<Image> StyleCachedImage::image(RenderObject* renderer, const IntSize&) const diff --git a/Source/WebCore/rendering/style/StyleCachedImageSet.cpp b/Source/WebCore/rendering/style/StyleCachedImageSet.cpp index f5071d169..c0a9f5e2f 100644 --- a/Source/WebCore/rendering/style/StyleCachedImageSet.cpp +++ b/Source/WebCore/rendering/style/StyleCachedImageSet.cpp @@ -108,7 +108,7 @@ void StyleCachedImageSet::addClient(RenderObject* renderer) void StyleCachedImageSet::removeClient(RenderObject* renderer) { - m_bestFitImage->removeClientForRenderer(renderer); + m_bestFitImage->removeClient(renderer); } PassRefPtr<Image> StyleCachedImageSet::image(RenderObject* renderer, const IntSize&) const diff --git a/Source/WebCore/rendering/style/StyleFlexibleBoxData.cpp b/Source/WebCore/rendering/style/StyleFlexibleBoxData.cpp index 53d7270cb..a7cfac1ed 100644 --- a/Source/WebCore/rendering/style/StyleFlexibleBoxData.cpp +++ b/Source/WebCore/rendering/style/StyleFlexibleBoxData.cpp @@ -31,33 +31,28 @@ namespace WebCore { StyleFlexibleBoxData::StyleFlexibleBoxData() - : m_positiveFlex(RenderStyle::initialPositiveFlex()) - , m_negativeFlex(RenderStyle::initialNegativeFlex()) - , m_preferredSize(RenderStyle::initialFlexPreferredSize()) - , m_flexPack(RenderStyle::initialFlexPack()) + : m_flexGrow(RenderStyle::initialFlexGrow()) + , m_flexShrink(RenderStyle::initialFlexShrink()) + , m_flexBasis(RenderStyle::initialFlexBasis()) , m_flexDirection(RenderStyle::initialFlexDirection()) , m_flexWrap(RenderStyle::initialFlexWrap()) - , m_flexLinePack(RenderStyle::initialFlexLinePack()) { } StyleFlexibleBoxData::StyleFlexibleBoxData(const StyleFlexibleBoxData& o) : RefCounted<StyleFlexibleBoxData>() - , m_positiveFlex(o.m_positiveFlex) - , m_negativeFlex(o.m_negativeFlex) - , m_preferredSize(o.m_preferredSize) - , m_flexPack(o.m_flexPack) + , m_flexGrow(o.m_flexGrow) + , m_flexShrink(o.m_flexShrink) + , m_flexBasis(o.m_flexBasis) , m_flexDirection(o.m_flexDirection) , m_flexWrap(o.m_flexWrap) - , m_flexLinePack(o.m_flexLinePack) { } bool StyleFlexibleBoxData::operator==(const StyleFlexibleBoxData& o) const { - return m_positiveFlex == o.m_positiveFlex && m_negativeFlex == o.m_negativeFlex && m_preferredSize == o.m_preferredSize - && m_flexPack == o.m_flexPack && m_flexDirection == o.m_flexDirection - && m_flexWrap == o.m_flexWrap && m_flexLinePack == o.m_flexLinePack; + return m_flexGrow == o.m_flexGrow && m_flexShrink == o.m_flexShrink && m_flexBasis == o.m_flexBasis + && m_flexDirection == o.m_flexDirection && m_flexWrap == o.m_flexWrap; } } diff --git a/Source/WebCore/rendering/style/StyleFlexibleBoxData.h b/Source/WebCore/rendering/style/StyleFlexibleBoxData.h index 5eab784dc..6c070d551 100644 --- a/Source/WebCore/rendering/style/StyleFlexibleBoxData.h +++ b/Source/WebCore/rendering/style/StyleFlexibleBoxData.h @@ -44,14 +44,12 @@ public: return !(*this == o); } - float m_positiveFlex; - float m_negativeFlex; - Length m_preferredSize; + float m_flexGrow; + float m_flexShrink; + Length m_flexBasis; - unsigned m_flexPack : 3; // EFlexPack unsigned m_flexDirection : 2; // EFlexDirection unsigned m_flexWrap : 2; // EFlexWrap - unsigned m_flexLinePack : 3; // EFlexLinePack private: StyleFlexibleBoxData(); diff --git a/Source/WebCore/rendering/style/StyleMultiColData.cpp b/Source/WebCore/rendering/style/StyleMultiColData.cpp index 96327ff8c..610277c20 100644 --- a/Source/WebCore/rendering/style/StyleMultiColData.cpp +++ b/Source/WebCore/rendering/style/StyleMultiColData.cpp @@ -38,6 +38,7 @@ StyleMultiColData::StyleMultiColData() , m_breakAfter(RenderStyle::initialPageBreak()) , m_breakInside(RenderStyle::initialPageBreak()) , m_axis(RenderStyle::initialColumnAxis()) + , m_progression(RenderStyle::initialColumnProgression()) { } @@ -56,6 +57,7 @@ StyleMultiColData::StyleMultiColData(const StyleMultiColData& o) , m_breakAfter(o.m_breakAfter) , m_breakInside(o.m_breakInside) , m_axis(o.m_axis) + , m_progression(o.m_progression) { } @@ -64,7 +66,8 @@ bool StyleMultiColData::operator==(const StyleMultiColData& o) const return m_width == o.m_width && m_count == o.m_count && m_gap == o.m_gap && m_rule == o.m_rule && m_visitedLinkColumnRuleColor == o.m_visitedLinkColumnRuleColor && m_breakBefore == o.m_breakBefore && m_autoWidth == o.m_autoWidth && m_autoCount == o.m_autoCount && m_normalGap == o.m_normalGap - && m_columnSpan == o.m_columnSpan && m_breakAfter == o.m_breakAfter && m_breakInside == o.m_breakInside && m_axis == o.m_axis; + && m_columnSpan == o.m_columnSpan && m_breakAfter == o.m_breakAfter && m_breakInside == o.m_breakInside && m_axis == o.m_axis + && m_progression == o.m_progression; } } // namespace WebCore diff --git a/Source/WebCore/rendering/style/StyleMultiColData.h b/Source/WebCore/rendering/style/StyleMultiColData.h index 99300834c..888ae6d56 100644 --- a/Source/WebCore/rendering/style/StyleMultiColData.h +++ b/Source/WebCore/rendering/style/StyleMultiColData.h @@ -67,6 +67,7 @@ public: unsigned m_breakAfter : 2; // EPageBreak unsigned m_breakInside : 2; // EPageBreak unsigned m_axis : 2; // ColumnAxis + unsigned m_progression : 2; // ColumnProgression private: StyleMultiColData(); diff --git a/Source/WebCore/rendering/style/StyleRareInheritedData.cpp b/Source/WebCore/rendering/style/StyleRareInheritedData.cpp index 9918e0ede..7fe609c21 100644 --- a/Source/WebCore/rendering/style/StyleRareInheritedData.cpp +++ b/Source/WebCore/rendering/style/StyleRareInheritedData.cpp @@ -30,6 +30,35 @@ namespace WebCore { +struct SameSizeAsStyleRareInheritedData : public RefCounted<SameSizeAsStyleRareInheritedData> { + Color firstColor; + float firstFloat; + Color colors[5]; + void* ownPtrs[1]; + AtomicString atomicStrings[5]; + void* refPtrs[2]; + Length lengths[1]; + float secondFloat; + unsigned m_bitfields[2]; + short pagedMediaShorts[2]; + unsigned unsigneds[1]; + short hyphenationShorts[3]; + +#if ENABLE(CSS_IMAGE_RESOLUTION) + float imageResolutionFloats; +#endif + +#if ENABLE(TOUCH_EVENTS) + Color touchColors; +#endif + +#if ENABLE(CSS_VARIABLES) + void* variableDataRefs[1]; +#endif +}; + +COMPILE_ASSERT(sizeof(StyleRareInheritedData) == sizeof(SameSizeAsStyleRareInheritedData), StyleRareInheritedData_should_bit_pack); + StyleRareInheritedData::StyleRareInheritedData() : textStrokeWidth(RenderStyle::initialTextStrokeWidth()) , indent(RenderStyle::initialTextIndent()) @@ -58,15 +87,24 @@ StyleRareInheritedData::StyleRareInheritedData() #if ENABLE(OVERFLOW_SCROLLING) , useTouchOverflowScrolling(RenderStyle::initialUseTouchOverflowScrolling()) #endif +#if ENABLE(CSS_IMAGE_RESOLUTION) + , m_imageResolutionSource(RenderStyle::initialImageResolutionSource()) +#endif , hyphenationLimitBefore(-1) , hyphenationLimitAfter(-1) , hyphenationLimitLines(-1) , m_lineGrid(RenderStyle::initialLineGrid()) , m_tabSize(RenderStyle::initialTabSize()) +#if ENABLE(CSS_IMAGE_RESOLUTION) + , m_imageResolution(RenderStyle::initialImageResolution()) +#endif #if ENABLE(TOUCH_EVENTS) , tapHighlightColor(RenderStyle::initialTapHighlightColor()) #endif { +#if ENABLE(CSS_VARIABLES) + m_variables.init(); +#endif } StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedData& o) @@ -107,6 +145,9 @@ StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedData& o) #if ENABLE(OVERFLOW_SCROLLING) , useTouchOverflowScrolling(o.useTouchOverflowScrolling) #endif +#if ENABLE(CSS_IMAGE_RESOLUTION) + , m_imageResolutionSource(o.m_imageResolutionSource) +#endif , hyphenationString(o.hyphenationString) , hyphenationLimitBefore(o.hyphenationLimitBefore) , hyphenationLimitAfter(o.hyphenationLimitAfter) @@ -115,9 +156,15 @@ StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedData& o) , textEmphasisCustomMark(o.textEmphasisCustomMark) , m_lineGrid(o.m_lineGrid) , m_tabSize(o.m_tabSize) +#if ENABLE(CSS_IMAGE_RESOLUTION) + , m_imageResolution(o.m_imageResolution) +#endif #if ENABLE(TOUCH_EVENTS) , tapHighlightColor(o.tapHighlightColor) #endif +#if ENABLE(CSS_VARIABLES) + , m_variables(o.m_variables) +#endif { } @@ -182,7 +229,14 @@ bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const && m_tabSize == o.m_tabSize && m_lineGrid == o.m_lineGrid && m_imageRendering == o.m_imageRendering +#if ENABLE(CSS_IMAGE_RESOLUTION) + && m_imageResolutionSource == o.m_imageResolutionSource + && m_imageResolution == o.m_imageResolution +#endif && m_lineSnap == o.m_lineSnap +#if ENABLE(CSS_VARIABLES) + && m_variables == o.m_variables +#endif && m_lineAlign == o.m_lineAlign; } diff --git a/Source/WebCore/rendering/style/StyleRareInheritedData.h b/Source/WebCore/rendering/style/StyleRareInheritedData.h index df8879a11..5891af98f 100644 --- a/Source/WebCore/rendering/style/StyleRareInheritedData.h +++ b/Source/WebCore/rendering/style/StyleRareInheritedData.h @@ -31,6 +31,11 @@ #include <wtf/PassRefPtr.h> #include <wtf/text/AtomicString.h> +#if ENABLE(CSS_VARIABLES) +#include "DataRef.h" +#include "StyleVariableData.h" +#endif + namespace WebCore { class CursorList; @@ -79,7 +84,7 @@ public: unsigned wordWrap : 1; // EWordWrap unsigned nbspMode : 1; // ENBSPMode unsigned khtmlLineBreak : 1; // EKHTMLLineBreak - bool textSizeAdjust : 1; // An Apple extension. + unsigned textSizeAdjust : 1; // An Apple extension. unsigned resize : 2; // EResize unsigned userSelect : 1; // EUserSelect unsigned colorSpace : 1; // ColorSpace @@ -96,6 +101,9 @@ public: #if ENABLE(OVERFLOW_SCROLLING) unsigned useTouchOverflowScrolling: 1; #endif +#if ENABLE(CSS_IMAGE_RESOLUTION) + unsigned m_imageResolutionSource : 1; // ImageResolutionSource +#endif AtomicString hyphenationString; short hyphenationLimitBefore; @@ -110,10 +118,18 @@ public: AtomicString m_lineGrid; unsigned m_tabSize; +#if ENABLE(CSS_IMAGE_RESOLUTION) + float m_imageResolution; +#endif + #if ENABLE(TOUCH_EVENTS) Color tapHighlightColor; #endif +#if ENABLE(CSS_VARIABLES) + DataRef<StyleVariableData> m_variables; +#endif + private: StyleRareInheritedData(); StyleRareInheritedData(const StyleRareInheritedData&); diff --git a/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp b/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp index b4c045619..22b3272e8 100644 --- a/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp +++ b/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp @@ -60,13 +60,14 @@ StyleRareNonInheritedData::StyleRareNonInheritedData() , m_pageSizeType(PAGE_SIZE_AUTO) , m_transformStyle3D(RenderStyle::initialTransformStyle3D()) , m_backfaceVisibility(RenderStyle::initialBackfaceVisibility()) + , m_alignContent(RenderStyle::initialAlignContent()) , m_alignItems(RenderStyle::initialAlignItems()) , m_alignSelf(RenderStyle::initialAlignSelf()) + , m_justifyContent(RenderStyle::initialJustifyContent()) , userDrag(RenderStyle::initialUserDrag()) , textOverflow(RenderStyle::initialTextOverflow()) , marginBeforeCollapse(MCOLLAPSE) , marginAfterCollapse(MCOLLAPSE) - , matchNearestMailBlockquoteColor(RenderStyle::initialMatchNearestMailBlockquoteColor()) , m_appearance(RenderStyle::initialAppearance()) , m_borderFit(RenderStyle::initialBorderFit()) , m_textCombine(RenderStyle::initialTextCombine()) @@ -130,13 +131,14 @@ StyleRareNonInheritedData::StyleRareNonInheritedData(const StyleRareNonInherited , m_pageSizeType(o.m_pageSizeType) , m_transformStyle3D(o.m_transformStyle3D) , m_backfaceVisibility(o.m_backfaceVisibility) + , m_alignContent(o.m_alignContent) , m_alignItems(o.m_alignItems) , m_alignSelf(o.m_alignSelf) + , m_justifyContent(o.m_justifyContent) , userDrag(o.userDrag) , textOverflow(o.textOverflow) , marginBeforeCollapse(o.marginBeforeCollapse) , marginAfterCollapse(o.marginAfterCollapse) - , matchNearestMailBlockquoteColor(o.matchNearestMailBlockquoteColor) , m_appearance(o.m_appearance) , m_borderFit(o.m_borderFit) , m_textCombine(o.m_textCombine) @@ -206,13 +208,14 @@ bool StyleRareNonInheritedData::operator==(const StyleRareNonInheritedData& o) c && m_pageSizeType == o.m_pageSizeType && m_transformStyle3D == o.m_transformStyle3D && m_backfaceVisibility == o.m_backfaceVisibility + && m_alignContent == o.m_alignContent && m_alignItems == o.m_alignItems && m_alignSelf == o.m_alignSelf + && m_justifyContent == o.m_justifyContent && userDrag == o.userDrag && textOverflow == o.textOverflow && marginBeforeCollapse == o.marginBeforeCollapse && marginAfterCollapse == o.marginAfterCollapse - && matchNearestMailBlockquoteColor == o.matchNearestMailBlockquoteColor && m_appearance == o.m_appearance && m_borderFit == o.m_borderFit && m_textCombine == o.m_textCombine diff --git a/Source/WebCore/rendering/style/StyleRareNonInheritedData.h b/Source/WebCore/rendering/style/StyleRareNonInheritedData.h index 494bb8d20..94c4c8dfb 100644 --- a/Source/WebCore/rendering/style/StyleRareNonInheritedData.h +++ b/Source/WebCore/rendering/style/StyleRareNonInheritedData.h @@ -146,7 +146,7 @@ public: Color m_visitedLinkBorderTopColor; Color m_visitedLinkBorderBottomColor; - int m_order; + float m_order; AtomicString m_flowThread; AtomicString m_regionThread; @@ -160,14 +160,15 @@ public: unsigned m_transformStyle3D : 1; // ETransformStyle3D unsigned m_backfaceVisibility : 1; // EBackfaceVisibility + unsigned m_alignContent : 3; // EAlignContent unsigned m_alignItems : 3; // EAlignItems unsigned m_alignSelf : 3; // EAlignItems + unsigned m_justifyContent : 3; // EJustifyContent unsigned userDrag : 2; // EUserDrag unsigned textOverflow : 1; // Whether or not lines that spill out should be truncated with "..." unsigned marginBeforeCollapse : 2; // EMarginCollapse unsigned marginAfterCollapse : 2; // EMarginCollapse - unsigned matchNearestMailBlockquoteColor : 1; // EMatchNearestMailBlockquoteColor, FIXME: This property needs to be eliminated. It should never have been added. unsigned m_appearance : 6; // EAppearance unsigned m_borderFit : 1; // EBorderFit unsigned m_textCombine : 1; // CSS3 text-combine properties diff --git a/Source/WebCore/rendering/style/StyleVariableData.h b/Source/WebCore/rendering/style/StyleVariableData.h new file mode 100644 index 000000000..bb45989f1 --- /dev/null +++ b/Source/WebCore/rendering/style/StyleVariableData.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2012 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT + * OWNER 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 StyleVariableData_h +#define StyleVariableData_h +#if ENABLE(CSS_VARIABLES) + +#include <wtf/Forward.h> +#include <wtf/HashMap.h> +#include <wtf/RefCounted.h> +#include <wtf/text/AtomicStringHash.h> + +namespace WebCore { + +class CursorList; +class QuotesData; +class ShadowData; + +class StyleVariableData : public RefCounted<StyleVariableData> { +public: + static PassRefPtr<StyleVariableData> create() { return adoptRef(new StyleVariableData()); } + PassRefPtr<StyleVariableData> copy() const { return adoptRef(new StyleVariableData(*this)); } + + bool operator==(const StyleVariableData& other) const { return other.m_data == m_data; } + bool operator!=(const StyleVariableData& other) const { return !(*this == other); } + + void setVariable(const AtomicString& name, const String& value) { m_data.set(name, value); } + + HashMap<AtomicString, String> m_data; +private: + explicit StyleVariableData() : RefCounted<StyleVariableData>() { } + StyleVariableData(const StyleVariableData& other) : RefCounted<StyleVariableData>(), m_data(HashMap<AtomicString, String>(other.m_data)) { } +}; + +} // namespace WebCore + +#endif /* ENABLE(CSS_VARIABLES) */ +#endif /* StyleVariableData_h */ diff --git a/Source/WebCore/rendering/svg/RenderSVGContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGContainer.cpp index 7b2866113..380275396 100644 --- a/Source/WebCore/rendering/svg/RenderSVGContainer.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGContainer.cpp @@ -163,11 +163,6 @@ void RenderSVGContainer::addFocusRingRects(Vector<IntRect>& rects, const LayoutP void RenderSVGContainer::updateCachedBoundaries() { - m_objectBoundingBox = FloatRect(); - m_objectBoundingBoxValid = false; - m_strokeBoundingBox = FloatRect(); - m_repaintBoundingBox = FloatRect(); - SVGRenderSupport::computeContainerBoundingBoxes(this, m_objectBoundingBox, m_objectBoundingBoxValid, m_strokeBoundingBox, m_repaintBoundingBox); SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingBox); } diff --git a/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp b/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp index eff707724..454f7aa6d 100644 --- a/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp @@ -232,9 +232,7 @@ void RenderSVGInlineText::computeNewScaledFontForStyle(RenderObject* renderer, c ASSERT(styleResolver); // Alter font-size to the right on-screen value to avoid scaling the glyphs themselves, except when GeometricPrecision is specified - AffineTransform ctm; - SVGRenderingContext::calculateTransformationToOutermostSVGCoordinateSystem(renderer, ctm); - scalingFactor = narrowPrecisionToFloat(sqrt((pow(ctm.xScale(), 2) + pow(ctm.yScale(), 2)) / 2)); + scalingFactor = SVGRenderingContext::calculateScreenFontSizeScalingFactor(renderer); if (scalingFactor == 1 || !scalingFactor || style->fontDescription().textRenderingMode() == GeometricPrecision) { scalingFactor = 1; scaledFont = style->font(); diff --git a/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp b/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp index c1c27b09a..cf3079c06 100644 --- a/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp @@ -171,8 +171,10 @@ bool RenderSVGModelObject::checkIntersection(RenderObject* renderer, const Float if (!isGraphicsElement(renderer)) return false; AffineTransform ctm; - getElementCTM(static_cast<SVGElement*>(renderer->node()), ctm); - return intersectsAllowingEmpty(rect, ctm.mapRect(renderer->repaintRectInLocalCoordinates())); + SVGElement* svgElement = static_cast<SVGElement*>(renderer->node()); + getElementCTM(svgElement, ctm); + ASSERT(svgElement->renderer()); + return intersectsAllowingEmpty(rect, ctm.mapRect(svgElement->renderer()->repaintRectInLocalCoordinates())); } bool RenderSVGModelObject::checkEnclosure(RenderObject* renderer, const FloatRect& rect) @@ -182,8 +184,10 @@ bool RenderSVGModelObject::checkEnclosure(RenderObject* renderer, const FloatRec if (!isGraphicsElement(renderer)) return false; AffineTransform ctm; - getElementCTM(static_cast<SVGElement*>(renderer->node()), ctm); - return rect.contains(ctm.mapRect(renderer->repaintRectInLocalCoordinates())); + SVGElement* svgElement = static_cast<SVGElement*>(renderer->node()); + getElementCTM(svgElement, ctm); + ASSERT(svgElement->renderer()); + return rect.contains(ctm.mapRect(svgElement->renderer()->repaintRectInLocalCoordinates())); } } // namespace WebCore diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp index 80760fd48..3e223ed3b 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp @@ -24,6 +24,7 @@ #include "RenderSVGRoot.h" #include "RenderView.h" +#include "SVGRenderingContext.h" #include "SVGResourcesCache.h" #include "SVGStyledTransformableElement.h" @@ -170,6 +171,27 @@ void RenderSVGResourceContainer::registerResource() } } +bool RenderSVGResourceContainer::shouldTransformOnTextPainting(RenderObject* object, AffineTransform& resourceTransform) +{ + ASSERT_UNUSED(object, object); +#if USE(CG) + UNUSED_PARAM(resourceTransform); + return false; +#else + // This method should only be called for RenderObjects that deal with text rendering. Cmp. RenderObject.h's is*() methods. + ASSERT(object->isSVGText() || object->isSVGTextPath() || object->isSVGInline()); + + // In text drawing, the scaling part of the graphics context CTM is removed, compare SVGInlineTextBox::paintTextWithShadows. + // So, we use that scaling factor here, too, and then push it down to pattern or gradient space + // in order to keep the pattern or gradient correctly scaled. + float scalingFactor = SVGRenderingContext::calculateScreenFontSizeScalingFactor(object); + if (scalingFactor == 1) + return false; + resourceTransform.scale(scalingFactor); + return true; +#endif +} + // FIXME: This does not belong here. AffineTransform RenderSVGResourceContainer::transformOnNonScalingStroke(RenderObject* object, const AffineTransform& resourceTransform) { diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceContainer.h b/Source/WebCore/rendering/svg/RenderSVGResourceContainer.h index b7473d927..1e8e62de8 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceContainer.h +++ b/Source/WebCore/rendering/svg/RenderSVGResourceContainer.h @@ -38,6 +38,7 @@ public: virtual bool isSVGResourceContainer() const { return true; } virtual RenderSVGResourceContainer* toRenderSVGResourceContainer() { return this; } + static bool shouldTransformOnTextPainting(RenderObject*, AffineTransform&); static AffineTransform transformOnNonScalingStroke(RenderObject*, const AffineTransform& resourceTransform); void idChanged(); diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp index f8f493db8..58e0079b2 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp @@ -166,6 +166,13 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle* calculateGradientTransform(gradientTransform); gradientData->userspaceTransform *= gradientTransform; + if (isPaintingText) { + // Depending on font scaling factor, we may need to rescale the gradient here since + // text painting removes the scale factor from the context. + AffineTransform additionalTextTransform; + if (shouldTransformOnTextPainting(object, additionalTextTransform)) + gradientData->userspaceTransform *= additionalTextTransform; + } gradientData->gradient->setGradientSpaceTransform(gradientData->userspaceTransform); } diff --git a/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp b/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp index 15d647689..b4af99918 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp @@ -133,6 +133,12 @@ bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle* if (!patternTransform.isIdentity()) patternData->transform = patternTransform * patternData->transform; + // Account for text drawing resetting the context to non-scaled, see SVGInlineTextBox::paintTextWithShadows. + if (resourceMode & ApplyToTextMode) { + AffineTransform additionalTextTransformation; + if (shouldTransformOnTextPainting(object, additionalTextTransformation)) + patternData->transform *= additionalTextTransformation; + } patternData->pattern->setPatternSpaceTransform(patternData->transform); } diff --git a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp b/Source/WebCore/rendering/svg/RenderSVGRoot.cpp index 663245333..58a715309 100644 --- a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGRoot.cpp @@ -404,11 +404,6 @@ const RenderObject* RenderSVGRoot::pushMappingToContainer(const RenderBoxModelOb void RenderSVGRoot::updateCachedBoundaries() { - m_objectBoundingBox = FloatRect(); - m_objectBoundingBoxValid = false; - m_strokeBoundingBox = FloatRect(); - m_repaintBoundingBox = FloatRect(); - SVGRenderSupport::computeContainerBoundingBoxes(this, m_objectBoundingBox, m_objectBoundingBoxValid, m_strokeBoundingBox, m_repaintBoundingBox); SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingBox); m_repaintBoundingBox.inflate(borderAndPaddingWidth()); diff --git a/Source/WebCore/rendering/svg/RenderSVGTextPath.cpp b/Source/WebCore/rendering/svg/RenderSVGTextPath.cpp index c30fad59b..3ed63ddd6 100644 --- a/Source/WebCore/rendering/svg/RenderSVGTextPath.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGTextPath.cpp @@ -36,7 +36,6 @@ namespace WebCore { RenderSVGTextPath::RenderSVGTextPath(Node* n) : RenderSVGInline(n) - , m_startOffset(0) , m_exactAlignment(true) , m_stretchMethod(false) { diff --git a/Source/WebCore/rendering/svg/RenderSVGTextPath.h b/Source/WebCore/rendering/svg/RenderSVGTextPath.h index f1871b0f6..be156ba48 100644 --- a/Source/WebCore/rendering/svg/RenderSVGTextPath.h +++ b/Source/WebCore/rendering/svg/RenderSVGTextPath.h @@ -40,8 +40,6 @@ public: private: virtual const char* renderName() const { return "RenderSVGTextPath"; } - float m_startOffset; - bool m_exactAlignment : 1; bool m_stretchMethod : 1; diff --git a/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp b/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp index 24e9a82f7..9302aef80 100644 --- a/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp +++ b/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp @@ -44,7 +44,7 @@ using namespace std; namespace WebCore { -class ExpectedSVGInlineTextBoxSize : public InlineTextBox { +struct ExpectedSVGInlineTextBoxSize : public InlineTextBox { float float1; uint32_t bitfields : 5; void* pointer; diff --git a/Source/WebCore/rendering/svg/SVGRenderSupport.cpp b/Source/WebCore/rendering/svg/SVGRenderSupport.cpp index 177ce9c44..0bfb0a527 100644 --- a/Source/WebCore/rendering/svg/SVGRenderSupport.cpp +++ b/Source/WebCore/rendering/svg/SVGRenderSupport.cpp @@ -121,6 +121,13 @@ static inline void updateObjectBoundingBox(FloatRect& objectBoundingBox, bool& o void SVGRenderSupport::computeContainerBoundingBoxes(const RenderObject* container, FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, FloatRect& strokeBoundingBox, FloatRect& repaintBoundingBox) { + objectBoundingBox = FloatRect(); + objectBoundingBoxValid = false; + strokeBoundingBox = FloatRect(); + + // When computing the strokeBoundingBox, we use the repaintRects of the container's children so that the container's stroke includes + // the resources applied to the children (such as clips and filters). This allows filters applied to containers to correctly bound + // the children, and also improves inlining of SVG content, as the stroke bound is used in that situation also. for (RenderObject* current = container->firstChild(); current; current = current->nextSibling()) { if (current->isSVGHiddenContainer()) continue; @@ -128,14 +135,14 @@ void SVGRenderSupport::computeContainerBoundingBoxes(const RenderObject* contain const AffineTransform& transform = current->localToParentTransform(); if (transform.isIdentity()) { updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, current, current->objectBoundingBox()); - strokeBoundingBox.unite(current->strokeBoundingBox()); - repaintBoundingBox.unite(current->repaintRectInLocalCoordinates()); + strokeBoundingBox.unite(current->repaintRectInLocalCoordinates()); } else { updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, current, transform.mapRect(current->objectBoundingBox())); - strokeBoundingBox.unite(transform.mapRect(current->strokeBoundingBox())); - repaintBoundingBox.unite(transform.mapRect(current->repaintRectInLocalCoordinates())); + strokeBoundingBox.unite(transform.mapRect(current->repaintRectInLocalCoordinates())); } } + + repaintBoundingBox = strokeBoundingBox; } bool SVGRenderSupport::paintInfoIntersectsRepaintRect(const FloatRect& localRepaintRect, const AffineTransform& localTransform, const PaintInfo& paintInfo) diff --git a/Source/WebCore/rendering/svg/SVGRenderingContext.cpp b/Source/WebCore/rendering/svg/SVGRenderingContext.cpp index 80f53ef17..e2adb3063 100644 --- a/Source/WebCore/rendering/svg/SVGRenderingContext.cpp +++ b/Source/WebCore/rendering/svg/SVGRenderingContext.cpp @@ -167,6 +167,15 @@ static AffineTransform& currentContentTransformation() return s_currentContentTransformation; } +float SVGRenderingContext::calculateScreenFontSizeScalingFactor(const RenderObject* renderer) +{ + ASSERT(renderer); + + AffineTransform ctm; + calculateTransformationToOutermostSVGCoordinateSystem(renderer, ctm); + return narrowPrecisionToFloat(sqrt((pow(ctm.xScale(), 2) + pow(ctm.yScale(), 2)) / 2)); +} + void SVGRenderingContext::calculateTransformationToOutermostSVGCoordinateSystem(const RenderObject* renderer, AffineTransform& absoluteTransform) { const RenderObject* current = renderer; diff --git a/Source/WebCore/rendering/svg/SVGRenderingContext.h b/Source/WebCore/rendering/svg/SVGRenderingContext.h index 4649d9ab7..5d38ce495 100644 --- a/Source/WebCore/rendering/svg/SVGRenderingContext.h +++ b/Source/WebCore/rendering/svg/SVGRenderingContext.h @@ -83,6 +83,7 @@ public: static void renderSubtreeToImageBuffer(ImageBuffer*, RenderObject*, const AffineTransform&); static void clipToImageBuffer(GraphicsContext*, const AffineTransform& absoluteTransform, const FloatRect& targetRect, OwnPtr<ImageBuffer>&, bool safeToClear); + static float calculateScreenFontSizeScalingFactor(const RenderObject*); static void calculateTransformationToOutermostSVGCoordinateSystem(const RenderObject*, AffineTransform& absoluteTransform); static IntSize clampedAbsoluteSize(const IntSize&); static FloatRect clampedAbsoluteTargetRect(const FloatRect& absoluteTargetRect); |
