diff options
Diffstat (limited to 'WebCore/rendering')
56 files changed, 731 insertions, 311 deletions
diff --git a/WebCore/rendering/EllipsisBox.cpp b/WebCore/rendering/EllipsisBox.cpp index 4a64fe4..9d36086 100644 --- a/WebCore/rendering/EllipsisBox.cpp +++ b/WebCore/rendering/EllipsisBox.cpp @@ -31,7 +31,7 @@ void EllipsisBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) { GraphicsContext* context = paintInfo.context; RenderStyle* style = m_renderer->style(m_firstLine); - Color textColor = style->color(); + Color textColor = style->visitedDependentColor(CSSPropertyColor); if (textColor != context->fillColor()) context->setFillColor(textColor, style->colorSpace()); bool setShadow = false; @@ -78,7 +78,7 @@ IntRect EllipsisBox::selectionRect(int tx, int ty) void EllipsisBox::paintSelection(GraphicsContext* context, int tx, int ty, RenderStyle* style, const Font& font) { - Color textColor = style->color(); + Color textColor = style->visitedDependentColor(CSSPropertyColor); Color c = m_renderer->selectionBackgroundColor(); if (!c.isValid() || !c.alpha()) return; diff --git a/WebCore/rendering/InlineFlowBox.cpp b/WebCore/rendering/InlineFlowBox.cpp index 05d8fcd..c329b23 100644 --- a/WebCore/rendering/InlineFlowBox.cpp +++ b/WebCore/rendering/InlineFlowBox.cpp @@ -213,7 +213,7 @@ void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, RenderObject* en // Check to see if all initial lines are unconstructed. If so, then // we know the inline began on this line (unless we are a continuation). RenderLineBoxList* lineBoxList = rendererLineBoxes(); - if (!lineBoxList->firstLineBox()->isConstructed() && !renderer()->isInlineContinuation()) { + if (!lineBoxList->firstLineBox()->isConstructed() && !renderer()->isInlineElementContinuation()) { if (ltr && lineBoxList->firstLineBox() == this) includeLeftEdge = true; else if (!ltr && lineBoxList->lastLineBox() == this) @@ -663,12 +663,12 @@ void InlineFlowBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) // outlines. if (renderer()->style()->visibility() == VISIBLE && renderer()->hasOutline() && !isRootInlineBox()) { RenderInline* inlineFlow = toRenderInline(renderer()); - if ((inlineFlow->continuation() || inlineFlow->isInlineContinuation()) && !boxModelObject()->hasSelfPaintingLayer()) { + if ((inlineFlow->continuation() || inlineFlow->isInlineElementContinuation()) && !boxModelObject()->hasSelfPaintingLayer()) { // Add ourselves to the containing block of the entire continuation so that it can // paint us atomically. RenderBlock* block = renderer()->containingBlock()->containingBlock(); block->addContinuationWithOutline(toRenderInline(renderer()->node()->renderer())); - } else if (!inlineFlow->isInlineContinuation()) + } else if (!inlineFlow->isInlineElementContinuation()) paintInfo.outlineObjects->add(inlineFlow); } } else if (paintInfo.phase == PaintPhaseMask) { diff --git a/WebCore/rendering/InlineTextBox.cpp b/WebCore/rendering/InlineTextBox.cpp index 292a9ac..0933ae4 100644 --- a/WebCore/rendering/InlineTextBox.cpp +++ b/WebCore/rendering/InlineTextBox.cpp @@ -467,9 +467,7 @@ void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) selectionStrokeWidth = strokeWidth; } - Color stroke = paintInfo.forceBlackText ? Color::black : pseudoStyle->textStrokeColor(); - if (!stroke.isValid()) - stroke = pseudoStyle->color(); + Color stroke = paintInfo.forceBlackText ? Color::black : pseudoStyle->visitedDependentColor(CSSPropertyWebkitTextStrokeColor); if (stroke != selectionStrokeColor) { if (!paintSelectedTextOnly) paintSelectedTextSeparately = true; diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp index 7b6c817..9ea5209 100644 --- a/WebCore/rendering/RenderBlock.cpp +++ b/WebCore/rendering/RenderBlock.cpp @@ -124,7 +124,7 @@ RenderBlock::RenderBlock(Node* node) : RenderBox(node) , m_floatingObjects(0) , m_positionedObjects(0) - , m_inlineContinuation(0) + , m_continuation(0) , m_maxMargin(0) , m_lineHeight(-1) { @@ -169,9 +169,9 @@ void RenderBlock::destroy() // Destroy our continuation before anything other than anonymous children. // The reason we don't destroy it before anonymous children is that they may // have continuations of their own that are anonymous children of our continuation. - if (m_inlineContinuation) { - m_inlineContinuation->destroy(); - m_inlineContinuation = 0; + if (m_continuation) { + m_continuation->destroy(); + m_continuation = 0; } if (!documentBeingDestroyed()) { @@ -500,7 +500,7 @@ void RenderBlock::removeLeftoverAnonymousBlock(RenderBlock* child) ASSERT(child->isAnonymousBlock()); ASSERT(!child->childrenInline()); - if (child->inlineContinuation()) + if (child->continuation()) return; RenderObject* firstAnChild = child->m_children.firstChild(); @@ -544,10 +544,10 @@ void RenderBlock::removeChild(RenderObject* oldChild) // fold the inline content back together. RenderObject* prev = oldChild->previousSibling(); RenderObject* next = oldChild->nextSibling(); - bool canDeleteAnonymousBlocks = !documentBeingDestroyed() && !isInline() && !oldChild->isInline() && - (!oldChild->isRenderBlock() || !toRenderBlock(oldChild)->inlineContinuation()) && - (!prev || (prev->isAnonymousBlock() && prev->childrenInline())) && - (!next || (next->isAnonymousBlock() && next->childrenInline())); + bool canDeleteAnonymousBlocks = !documentBeingDestroyed() && !isInline() && !oldChild->isInline() + && (!oldChild->isRenderBlock() || !toRenderBlock(oldChild)->continuation()) + && (!prev || (prev->isAnonymousBlock() && prev->childrenInline())) + && (!next || (next->isAnonymousBlock() && next->childrenInline())); if (canDeleteAnonymousBlocks && prev && next) { // Take all the children out of the |next| block and put them in // the |prev| block. @@ -756,7 +756,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren) int repaintTop = 0; int repaintBottom = 0; int maxFloatBottom = 0; - if (!firstChild()) + if (!firstChild() && !isAnonymousBlock()) setChildrenInline(true); if (childrenInline()) layoutInlineChildren(relayoutChildren, repaintTop, repaintBottom); @@ -1628,24 +1628,27 @@ void RenderBlock::paintColumnContents(PaintInfo& paintInfo, int tx, int ty, bool // For each rect, we clip to the rect, and then we adjust our coords. IntRect colRect = colRects->at(i); colRect.move(tx, ty); - context->save(); - - // Each strip pushes a clip, since column boxes are specified as being - // like overflow:hidden. - context->clip(colRect); - - // Adjust tx and ty to change where we paint. PaintInfo info(paintInfo); info.rect.intersect(colRect); - // Adjust our x and y when painting. - int finalX = tx + currXOffset; - int finalY = ty + currYOffset; - if (paintingFloats) - paintFloats(info, finalX, finalY, paintInfo.phase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip); - else - paintContents(info, finalX, finalY); + if (!info.rect.isEmpty()) { + context->save(); + + // Each strip pushes a clip, since column boxes are specified as being + // like overflow:hidden. + context->clip(colRect); + + // Adjust our x and y when painting. + int finalX = tx + currXOffset; + int finalY = ty + currYOffset; + if (paintingFloats) + paintFloats(info, finalX, finalY, paintInfo.phase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip); + else + paintContents(info, finalX, finalY); + context->restore(); + } + // Move to the next position. if (style()->direction() == LTR) currXOffset += colRect.width() + colGap; @@ -1653,8 +1656,6 @@ void RenderBlock::paintColumnContents(PaintInfo& paintInfo, int tx, int ty, bool currXOffset -= (colRect.width() + colGap); currYOffset -= colRect.height(); - - context->restore(); } } @@ -1791,8 +1792,9 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, int tx, int ty) // 6. paint continuation outlines. if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutlines)) { - if (inlineContinuation() && inlineContinuation()->hasOutline() && inlineContinuation()->style()->visibility() == VISIBLE) { - RenderInline* inlineRenderer = toRenderInline(inlineContinuation()->node()->renderer()); + RenderInline* inlineCont = inlineElementContinuation(); + if (inlineCont && inlineCont->hasOutline() && inlineCont->style()->visibility() == VISIBLE) { + RenderInline* inlineRenderer = toRenderInline(inlineCont->node()->renderer()); if (!inlineRenderer->hasSelfPaintingLayer()) containingBlock()->addContinuationWithOutline(inlineRenderer); else if (!inlineRenderer->firstLineBox()) @@ -1865,6 +1867,21 @@ void RenderBlock::paintEllipsisBoxes(PaintInfo& paintInfo, int tx, int ty) } } +RenderInline* RenderBlock::inlineElementContinuation() const +{ + return m_continuation && m_continuation->isInline() ? toRenderInline(m_continuation) : 0; +} + +RenderBlock* RenderBlock::blockElementContinuation() const +{ + if (!m_continuation || m_continuation->isInline()) + return 0; + RenderBlock* nextContinuation = toRenderBlock(m_continuation); + if (nextContinuation->isAnonymousBlock()) + return nextContinuation->blockElementContinuation(); + return 0; +} + static ContinuationOutlineTableMap* continuationOutlineTable() { DEFINE_STATIC_LOCAL(ContinuationOutlineTableMap, table, ()); @@ -1875,7 +1892,7 @@ void RenderBlock::addContinuationWithOutline(RenderInline* flow) { // We can't make this work if the inline is in a layer. We'll just rely on the broken // way of painting. - ASSERT(!flow->layer() && !flow->isInlineContinuation()); + ASSERT(!flow->layer() && !flow->isInlineElementContinuation()); ContinuationOutlineTableMap* table = continuationOutlineTable(); ListHashSet<RenderInline*>* continuations = table->get(this); @@ -2009,13 +2026,13 @@ void RenderBlock::paintSelection(PaintInfo& paintInfo, int tx, int ty) } #ifndef BUILDING_ON_TIGER -static void clipOutPositionedObjects(const RenderObject::PaintInfo* paintInfo, int tx, int ty, ListHashSet<RenderBox*>* positionedObjects) +static void clipOutPositionedObjects(const RenderObject::PaintInfo* paintInfo, int tx, int ty, RenderBlock::PositionedObjectsListHashSet* positionedObjects) { if (!positionedObjects) return; - ListHashSet<RenderBox*>::const_iterator end = positionedObjects->end(); - for (ListHashSet<RenderBox*>::const_iterator it = positionedObjects->begin(); it != end; ++it) { + RenderBlock::PositionedObjectsListHashSet::const_iterator end = positionedObjects->end(); + for (RenderBlock::PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) { RenderBox* r = *it; paintInfo->context->clipOut(IntRect(tx + r->x(), ty + r->y(), r->width(), r->height())); } @@ -2301,7 +2318,7 @@ void RenderBlock::insertPositionedObject(RenderBox* o) { // Create the list of special objects if we don't aleady have one if (!m_positionedObjects) - m_positionedObjects = new ListHashSet<RenderBox*>; + m_positionedObjects = new PositionedObjectsListHashSet; m_positionedObjects->add(o); } @@ -3420,17 +3437,19 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu bool RenderBlock::hitTestColumns(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction) { // We need to do multiple passes, breaking up our hit testing into strips. - // We can always go left to right, since column contents are clipped (meaning that there - // can't be any overlap). Vector<IntRect>* colRects = columnRects(); - unsigned colCount = colRects->size(); + int colCount = colRects->size(); if (!colCount) return false; - int currXOffset = style()->direction() == LTR ? 0 : contentWidth() - colRects->at(0).width(); + int left = borderLeft() + paddingLeft(); int currYOffset = 0; - int colGap = columnGap(); - for (unsigned i = 0; i < colCount; i++) { + int i; + for (i = 0; i < colCount; i++) + currYOffset -= colRects->at(i).height(); + for (i = colCount - 1; i >= 0; i--) { IntRect colRect = colRects->at(i); + int currXOffset = colRect.x() - left; + currYOffset += colRect.height(); colRect.move(tx, ty); #ifdef ANDROID_HITTEST_WITHSIZE @@ -3450,14 +3469,6 @@ bool RenderBlock::hitTestColumns(const HitTestRequest& request, HitTestResult& r #endif return hitTestContents(request, result, x, y, finalX, finalY, hitTestAction); } - - // Move to the next position. - if (style()->direction() == LTR) - currXOffset += colRect.width() + colGap; - else - currXOffset -= (colRect.width() + colGap); - - currYOffset -= colRect.height(); } return false; @@ -3962,11 +3973,13 @@ void RenderBlock::adjustRectForColumns(IntRect& r) const unsigned colCount = colRects->size(); if (!colCount) return; - int currXOffset = style()->direction() == LTR ? 0 : contentWidth() - colRects->at(0).width(); + + int left = borderLeft() + paddingLeft(); + int currYOffset = 0; - int colGap = columnGap(); for (unsigned i = 0; i < colCount; i++) { IntRect colRect = colRects->at(i); + int currXOffset = colRect.x() - left; IntRect repaintRect = r; repaintRect.move(currXOffset, currYOffset); @@ -3976,11 +3989,6 @@ void RenderBlock::adjustRectForColumns(IntRect& r) const result.unite(repaintRect); // Move to the next position. - if (style()->direction() == LTR) - currXOffset += colRect.width() + colGap; - else - currXOffset -= (colRect.width() + colGap); - currYOffset -= colRect.height(); } @@ -3993,23 +4001,18 @@ void RenderBlock::adjustForColumns(IntSize& offset, const IntPoint& point) const return; Vector<IntRect>& columnRects = *this->columnRects(); - - int gapWidth = columnGap(); - - int xOffset = style()->direction() == LTR ? 0 : contentWidth() - columnRects[0].width(); + + int left = borderLeft() + paddingLeft(); int yOffset = 0; size_t columnCount = columnRects.size(); for (size_t i = 0; i < columnCount; ++i) { IntRect columnRect = columnRects[i]; + int xOffset = columnRect.x() - left; if (point.y() < columnRect.bottom() + yOffset) { offset.expand(xOffset, -yOffset); return; } - if (style()->direction() == LTR) - xOffset += columnRect.width() + gapWidth; - else - xOffset -= columnRect.width() + gapWidth; yOffset += columnRect.height(); } } @@ -5009,12 +5012,12 @@ void RenderBlock::absoluteRects(Vector<IntRect>& rects, int tx, int ty) // For blocks inside inlines, we go ahead and include margins so that we run right up to the // inline boxes above and below us (thus getting merged with them to form a single irregular // shape). - if (inlineContinuation()) { + if (isAnonymousBlockContinuation()) { rects.append(IntRect(tx, ty - collapsedMarginTop(), width(), height() + collapsedMarginTop() + collapsedMarginBottom())); - inlineContinuation()->absoluteRects(rects, - tx - x() + inlineContinuation()->containingBlock()->x(), - ty - y() + inlineContinuation()->containingBlock()->y()); + continuation()->absoluteRects(rects, + tx - x() + inlineElementContinuation()->containingBlock()->x(), + ty - y() + inlineElementContinuation()->containingBlock()->y()); } else rects.append(IntRect(tx, ty, width(), height())); } @@ -5024,11 +5027,11 @@ void RenderBlock::absoluteQuads(Vector<FloatQuad>& quads) // For blocks inside inlines, we go ahead and include margins so that we run right up to the // inline boxes above and below us (thus getting merged with them to form a single irregular // shape). - if (inlineContinuation()) { + if (isAnonymousBlockContinuation()) { FloatRect localRect(0, -collapsedMarginTop(), width(), height() + collapsedMarginTop() + collapsedMarginBottom()); quads.append(localToAbsoluteQuad(localRect)); - inlineContinuation()->absoluteQuads(quads); + continuation()->absoluteQuads(quads); } else quads.append(RenderBox::localToAbsoluteQuad(FloatRect(0, 0, width(), height()))); } @@ -5036,26 +5039,26 @@ void RenderBlock::absoluteQuads(Vector<FloatQuad>& quads) IntRect RenderBlock::rectWithOutlineForRepaint(RenderBoxModelObject* repaintContainer, int outlineWidth) { IntRect r(RenderBox::rectWithOutlineForRepaint(repaintContainer, outlineWidth)); - if (inlineContinuation()) + if (isAnonymousBlockContinuation()) r.inflateY(collapsedMarginTop()); return r; } RenderObject* RenderBlock::hoverAncestor() const { - return inlineContinuation() ? inlineContinuation() : RenderBox::hoverAncestor(); + return isAnonymousBlockContinuation() ? continuation() : RenderBox::hoverAncestor(); } void RenderBlock::updateDragState(bool dragOn) { RenderBox::updateDragState(dragOn); - if (inlineContinuation()) - inlineContinuation()->updateDragState(dragOn); + if (continuation()) + continuation()->updateDragState(dragOn); } RenderStyle* RenderBlock::outlineStyleForRepaint() const { - return inlineContinuation() ? inlineContinuation()->style() : style(); + return isAnonymousBlockContinuation() ? continuation()->style() : style(); } void RenderBlock::childBecameNonInline(RenderObject*) @@ -5072,11 +5075,11 @@ void RenderBlock::updateHitTestResult(HitTestResult& result, const IntPoint& poi return; Node* n = node(); - if (inlineContinuation()) + if (isAnonymousBlockContinuation()) // We are in the margins of block elements that are part of a continuation. In - // this case we're actually still inside the enclosing inline element that was + // this case we're actually still inside the enclosing element that was // split. Go ahead and set our inner node accordingly. - n = inlineContinuation()->node(); + n = continuation()->node(); if (n) { result.setInnerNode(n); @@ -5169,11 +5172,11 @@ void RenderBlock::addFocusRingRects(Vector<IntRect>& rects, int tx, int ty) // For blocks inside inlines, we go ahead and include margins so that we run right up to the // inline boxes above and below us (thus getting merged with them to form a single irregular // shape). - if (inlineContinuation()) { + if (inlineElementContinuation()) { // FIXME: This check really isn't accurate. - bool nextInlineHasLineBox = inlineContinuation()->firstLineBox(); + bool nextInlineHasLineBox = inlineElementContinuation()->firstLineBox(); // FIXME: This is wrong. The principal renderer may not be the continuation preceding this block. - bool prevInlineHasLineBox = toRenderInline(inlineContinuation()->node()->renderer())->firstLineBox(); + bool prevInlineHasLineBox = toRenderInline(inlineElementContinuation()->node()->renderer())->firstLineBox(); int topMargin = prevInlineHasLineBox ? collapsedMarginTop() : 0; int bottomMargin = nextInlineHasLineBox ? collapsedMarginBottom() : 0; IntRect rect(tx, ty - topMargin, width(), height() + topMargin + bottomMargin); @@ -5205,10 +5208,10 @@ void RenderBlock::addFocusRingRects(Vector<IntRect>& rects, int tx, int ty) } } - if (inlineContinuation()) - inlineContinuation()->addFocusRingRects(rects, - tx - x() + inlineContinuation()->containingBlock()->x(), - ty - y() + inlineContinuation()->containingBlock()->y()); + if (inlineElementContinuation()) + inlineElementContinuation()->addFocusRingRects(rects, + tx - x() + inlineElementContinuation()->containingBlock()->x(), + ty - y() + inlineElementContinuation()->containingBlock()->y()); } RenderBlock* RenderBlock::createAnonymousBlock(bool isFlexibleBox) const diff --git a/WebCore/rendering/RenderBlock.h b/WebCore/rendering/RenderBlock.h index b54f66d..9eb1c0f 100644 --- a/WebCore/rendering/RenderBlock.h +++ b/WebCore/rendering/RenderBlock.h @@ -74,7 +74,9 @@ public: void insertPositionedObject(RenderBox*); void removePositionedObject(RenderBox*); void removePositionedObjects(RenderBlock*); - ListHashSet<RenderBox*>* positionedObjects() const { return m_positionedObjects; } + + typedef ListHashSet<RenderBox*, 4> PositionedObjectsListHashSet; + PositionedObjectsListHashSet* positionedObjects() const { return m_positionedObjects; } void addPercentHeightDescendant(RenderBox*); static void removePercentHeightDescendant(RenderBox*); @@ -131,8 +133,12 @@ public: void addContinuationWithOutline(RenderInline*); - RenderInline* inlineContinuation() const { return m_inlineContinuation; } - void setInlineContinuation(RenderInline* c) { m_inlineContinuation = c; } + RenderBoxModelObject* continuation() const { return m_continuation; } + void setContinuation(RenderBoxModelObject* c) { m_continuation = c; } + virtual RenderBoxModelObject* virtualContinuation() const { return continuation(); } + bool isAnonymousBlockContinuation() const { return continuation() && isAnonymousBlock(); } + RenderInline* inlineElementContinuation() const; + RenderBlock* blockElementContinuation() const; // This function is a convenience helper for creating an anonymous block that inherits its // style from this RenderBlock. @@ -141,6 +147,9 @@ public: static void appendRunsForObject(int start, int end, RenderObject*, InlineBidiResolver&); static bool requiresLineBox(const InlineIterator&, bool isLineEmpty = true, bool previousLineBrokeCleanly = true); + Vector<IntRect>* columnRects() const; + int columnGap() const; + protected: void moveChildTo(RenderObject* to, RenderObjectChildList* toChildList, RenderObject* child); void moveChildTo(RenderObject* to, RenderObjectChildList* toChildList, RenderObject* beforeChild, RenderObject* child); @@ -198,7 +207,7 @@ protected: virtual bool hasLineIfEmpty() const; bool layoutOnlyPositionedObjects(); - + private: virtual RenderObjectChildList* virtualChildren() { return children(); } virtual const RenderObjectChildList* virtualChildren() const { return children(); } @@ -346,6 +355,7 @@ private: int desiredColumnWidth() const; unsigned desiredColumnCount() const; +<<<<<<< HEAD #if PLATFORM(ANDROID) public: #endif @@ -362,6 +372,10 @@ public: private: #endif +======= + void setDesiredColumnCountAndWidth(int count, int width); + +>>>>>>> webkit.org at r60074 void paintContinuationOutlines(PaintInfo&, int tx, int ty); virtual IntRect localCaretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0); @@ -495,15 +509,16 @@ private: void setCollapsedBottomMargin(const MarginInfo&); // End helper functions and structs used by layoutBlockChildren. - typedef ListHashSet<RenderBox*>::const_iterator Iterator; + typedef PositionedObjectsListHashSet::const_iterator Iterator; DeprecatedPtrList<FloatingObject>* m_floatingObjects; - ListHashSet<RenderBox*>* m_positionedObjects; + + PositionedObjectsListHashSet* m_positionedObjects; // An inline can be split with blocks occurring in between the inline content. // When this occurs we need a pointer to our next object. We can basically be // split into a sequence of inlines and blocks. The continuation will either be // an anonymous block (that houses other blocks) or it will be an inline flow. - RenderInline* m_inlineContinuation; + RenderBoxModelObject* m_continuation; // Allocated only when some of these fields have non-default values struct MaxMargin : Noncopyable { diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp index 4c5d702..12bfced 100644 --- a/WebCore/rendering/RenderBox.cpp +++ b/WebCore/rendering/RenderBox.cpp @@ -193,7 +193,7 @@ void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle // Set the text color if we're the body. if (isBody()) - document()->setTextColor(style()->color()); + document()->setTextColor(style()->visitedDependentColor(CSSPropertyColor)); } void RenderBox::updateBoxModelInfoFromStyle() @@ -599,9 +599,9 @@ void RenderBox::paint(PaintInfo& paintInfo, int tx, int ty) void RenderBox::paintRootBoxDecorations(PaintInfo& paintInfo, int tx, int ty) { const FillLayer* bgLayer = style()->backgroundLayers(); - Color bgColor = style()->backgroundColor(); + Color bgColor = style()->visitedDependentColor(CSSPropertyBackgroundColor); RenderObject* bodyObject = 0; - if (!style()->hasBackground() && node() && node()->hasTagName(HTMLNames::htmlTag)) { + if (!hasBackground() && node() && node()->hasTagName(HTMLNames::htmlTag)) { // Locate the <body> element using the DOM. This is easier than trying // to crawl around a render tree with potential :before/:after content and // anonymous blocks created by inline <body> tags etc. We can locate the <body> @@ -610,7 +610,7 @@ void RenderBox::paintRootBoxDecorations(PaintInfo& paintInfo, int tx, int ty) bodyObject = (body && body->hasLocalName(bodyTag)) ? body->renderer() : 0; if (bodyObject) { bgLayer = bodyObject->style()->backgroundLayers(); - bgColor = bodyObject->style()->backgroundColor(); + bgColor = bodyObject->style()->visitedDependentColor(CSSPropertyBackgroundColor); } } @@ -671,8 +671,8 @@ void RenderBox::paintBoxDecorationsWithSize(PaintInfo& paintInfo, int tx, int ty // The <body> only paints its background if the root element has defined a background // independent of the body. Go through the DOM to get to the root element's render object, // since the root could be inline and wrapped in an anonymous block. - if (!isBody() || document()->documentElement()->renderer()->style()->hasBackground()) - paintFillLayers(paintInfo, style()->backgroundColor(), style()->backgroundLayers(), tx, ty, width, height); + if (!isBody() || document()->documentElement()->renderer()->hasBackground()) + paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), tx, ty, width, height); if (style()->hasAppearance()) theme()->paintDecorations(this, paintInfo, IntRect(tx, ty, width, height)); } @@ -818,7 +818,7 @@ bool RenderBox::repaintLayerRectsForImage(WrappedImagePtr image, const FillLayer // Now that we know this image is being used, compute the renderer and the rect // if we haven't already if (!layerRenderer) { - bool drawingRootBackground = drawingBackground && (isRoot() || (isBody() && !document()->documentElement()->renderer()->style()->hasBackground())); + bool drawingRootBackground = drawingBackground && (isRoot() || (isBody() && !document()->documentElement()->renderer()->hasBackground())); if (drawingRootBackground) { layerRenderer = view(); @@ -1210,22 +1210,11 @@ void RenderBox::computeRectForRepaint(RenderBoxModelObject* repaintContainer, In EPosition position = style()->position(); - if (o->isBlockFlow() && position != AbsolutePosition && position != FixedPosition) { - RenderBlock* cb = toRenderBlock(o); - if (cb->hasColumns()) { - IntRect repaintRect(topLeft, rect.size()); - cb->adjustRectForColumns(repaintRect); - topLeft = repaintRect.location(); - rect = repaintRect; - } - } - // We are now in our parent container's coordinate space. Apply our transform to obtain a bounding box // in the parent's coordinate space that encloses us. if (layer() && layer()->transform()) { fixed = position == FixedPosition; rect = layer()->transform()->mapRect(rect); - // FIXME: this clobbers topLeft adjustment done for multicol above topLeft = rect.location(); topLeft.move(x(), y()); } else if (position == FixedPosition) @@ -1241,6 +1230,16 @@ void RenderBox::computeRectForRepaint(RenderBoxModelObject* repaintContainer, In topLeft += layer()->relativePositionOffset(); } + if (o->isBlockFlow() && position != AbsolutePosition && position != FixedPosition) { + RenderBlock* cb = toRenderBlock(o); + if (cb->hasColumns()) { + IntRect repaintRect(topLeft, rect.size()); + cb->adjustRectForColumns(repaintRect); + topLeft = repaintRect.location(); + rect = repaintRect; + } + } + // FIXME: We ignore the lightweight clipping rect that controls use, since if |o| is in mid-layout, // its controlClipRect will be wrong. For overflow clip we use the values cached by the layer. if (o->hasOverflowClip()) { diff --git a/WebCore/rendering/RenderBoxModelObject.cpp b/WebCore/rendering/RenderBoxModelObject.cpp index 9caf46f..1a72957 100644 --- a/WebCore/rendering/RenderBoxModelObject.cpp +++ b/WebCore/rendering/RenderBoxModelObject.cpp @@ -304,7 +304,7 @@ void RenderBoxModelObject::updateBoxModelInfoFromStyle() { // Set the appropriate bits for a box model object. Since all bits are cleared in styleWillChange, // we only check for bits that could possibly be set to true. - setHasBoxDecorations(style()->hasBorder() || style()->hasBackground() || style()->hasAppearance() || style()->boxShadow()); + setHasBoxDecorations(hasBackground() || style()->hasBorder() || style()->hasAppearance() || style()->boxShadow()); setInline(style()->isDisplayInlineType()); setRelPositioned(style()->position() == RelativePosition); } @@ -1321,7 +1321,7 @@ void RenderBoxModelObject::paintBoxShadow(GraphicsContext* context, int tx, int rect.setHeight(rect.height() - borderTop() - borderBottom()); } - bool hasOpaqueBackground = s->backgroundColor().isValid() && s->backgroundColor().alpha() == 255; + bool hasOpaqueBackground = s->visitedDependentColor(CSSPropertyBackgroundColor).isValid() && s->visitedDependentColor(CSSPropertyBackgroundColor).alpha() == 255; for (const ShadowData* shadow = s->boxShadow(); shadow; shadow = shadow->next()) { if (shadow->style() != shadowStyle) continue; diff --git a/WebCore/rendering/RenderButton.h b/WebCore/rendering/RenderButton.h index 7fd6ab0..1fc5eb6 100644 --- a/WebCore/rendering/RenderButton.h +++ b/WebCore/rendering/RenderButton.h @@ -57,12 +57,14 @@ public: virtual bool canHaveChildren() const; -protected: +private: virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle); virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); virtual bool hasLineIfEmpty() const { return true; } + virtual bool requiresForcedStyleRecalcPropagation() const { return true; } + void timerFired(Timer<RenderButton>*); RenderTextFragment* m_buttonText; diff --git a/WebCore/rendering/RenderDataGrid.h b/WebCore/rendering/RenderDataGrid.h index 467edcc..ce221ea 100644 --- a/WebCore/rendering/RenderDataGrid.h +++ b/WebCore/rendering/RenderDataGrid.h @@ -53,6 +53,8 @@ public: private: virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); + virtual bool requiresForcedStyleRecalcPropagation() const { return true; } + RenderStyle* columnStyle(DataGridColumn*); RenderStyle* headerStyle(DataGridColumn*); void recalcStyleForColumns(); diff --git a/WebCore/rendering/RenderFieldset.cpp b/WebCore/rendering/RenderFieldset.cpp index 306e111..734c348 100644 --- a/WebCore/rendering/RenderFieldset.cpp +++ b/WebCore/rendering/RenderFieldset.cpp @@ -136,7 +136,7 @@ void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty) paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Normal); - paintFillLayers(paintInfo, style()->backgroundColor(), style()->backgroundLayers(), tx, ty, w, h); + paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), tx, ty, w, h); paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Inset); if (!style()->hasBorder()) diff --git a/WebCore/rendering/RenderFileUploadControl.cpp b/WebCore/rendering/RenderFileUploadControl.cpp index fa2a998..1ae149b 100644 --- a/WebCore/rendering/RenderFileUploadControl.cpp +++ b/WebCore/rendering/RenderFileUploadControl.cpp @@ -228,7 +228,7 @@ void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, int tx, int ty) + buttonRenderer->marginTop() + buttonRenderer->borderTop() + buttonRenderer->paddingTop() + buttonRenderer->baselinePosition(true, false); - paintInfo.context->setFillColor(style()->color(), style()->colorSpace()); + paintInfo.context->setFillColor(style()->visitedDependentColor(CSSPropertyColor), style()->colorSpace()); // Draw the filename paintInfo.context->drawBidiText(style()->font(), textRun, IntPoint(textX, textY)); diff --git a/WebCore/rendering/RenderFileUploadControl.h b/WebCore/rendering/RenderFileUploadControl.h index 1427dbf..25d2639 100644 --- a/WebCore/rendering/RenderFileUploadControl.h +++ b/WebCore/rendering/RenderFileUploadControl.h @@ -56,6 +56,8 @@ private: virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); + virtual bool requiresForcedStyleRecalcPropagation() const { return true; } + // FileChooserClient methods. void valueChanged(); void repaint() { RenderBlock::repaint(); } diff --git a/WebCore/rendering/RenderFrameSet.cpp b/WebCore/rendering/RenderFrameSet.cpp index 35867f5..3ab2fff 100644 --- a/WebCore/rendering/RenderFrameSet.cpp +++ b/WebCore/rendering/RenderFrameSet.cpp @@ -90,7 +90,7 @@ void RenderFrameSet::paintColumnBorder(const PaintInfo& paintInfo, const IntRect // Fill first. GraphicsContext* context = paintInfo.context; ColorSpace colorSpace = style()->colorSpace(); - context->fillRect(borderRect, frameSet()->hasBorderColor() ? style()->borderLeftColor() : borderFillColor(), colorSpace); + context->fillRect(borderRect, frameSet()->hasBorderColor() ? style()->visitedDependentColor(CSSPropertyBorderLeftColor) : borderFillColor(), colorSpace); // Now stroke the edges but only if we have enough room to paint both edges with a little // bit of the fill color showing through. @@ -110,7 +110,7 @@ void RenderFrameSet::paintRowBorder(const PaintInfo& paintInfo, const IntRect& b // Fill first. GraphicsContext* context = paintInfo.context; ColorSpace colorSpace = style()->colorSpace(); - context->fillRect(borderRect, frameSet()->hasBorderColor() ? style()->borderLeftColor() : borderFillColor(), colorSpace); + context->fillRect(borderRect, frameSet()->hasBorderColor() ? style()->visitedDependentColor(CSSPropertyBorderLeftColor) : borderFillColor(), colorSpace); // Now stroke the edges but only if we have enough room to paint both edges with a little // bit of the fill color showing through. diff --git a/WebCore/rendering/RenderImage.cpp b/WebCore/rendering/RenderImage.cpp index 6fd38a6..2e376e7 100644 --- a/WebCore/rendering/RenderImage.cpp +++ b/WebCore/rendering/RenderImage.cpp @@ -407,7 +407,7 @@ void RenderImage::paintReplaced(PaintInfo& paintInfo, int tx, int ty) if (!m_altText.isEmpty()) { String text = document()->displayStringModifiedByEncoding(m_altText); - context->setFillColor(style()->color(), style()->colorSpace()); + context->setFillColor(style()->visitedDependentColor(CSSPropertyColor), style()->colorSpace()); int ax = tx + leftBorder + leftPad; int ay = ty + topBorder + topPad; const Font& font = style()->font(); diff --git a/WebCore/rendering/RenderInline.cpp b/WebCore/rendering/RenderInline.cpp index 69e6eab..7531f93 100644 --- a/WebCore/rendering/RenderInline.cpp +++ b/WebCore/rendering/RenderInline.cpp @@ -92,11 +92,11 @@ void RenderInline::destroy() RenderBoxModelObject::destroy(); } -RenderInline* RenderInline::inlineContinuation() const +RenderInline* RenderInline::inlineElementContinuation() const { if (!m_continuation || m_continuation->isInline()) return toRenderInline(m_continuation); - return toRenderBlock(m_continuation)->inlineContinuation(); + return toRenderBlock(m_continuation)->inlineElementContinuation(); } void RenderInline::updateBoxModelInfoFromStyle() @@ -120,7 +120,7 @@ void RenderInline::styleDidChange(StyleDifference diff, const RenderStyle* oldSt // e.g., <font>foo <h4>goo</h4> moo</font>. The <font> inlines before // and after the block share the same style, but the block doesn't // need to pass its style on to anyone else. - for (RenderInline* currCont = inlineContinuation(); currCont; currCont = currCont->inlineContinuation()) { + for (RenderInline* currCont = inlineElementContinuation(); currCont; currCont = currCont->inlineElementContinuation()) { RenderBoxModelObject* nextCont = currCont->continuation(); currCont->setContinuation(0); currCont->setStyle(style()); @@ -147,7 +147,7 @@ static RenderBoxModelObject* nextContinuation(RenderObject* renderer) { if (renderer->isInline() && !renderer->isReplaced()) return toRenderInline(renderer)->continuation(); - return toRenderBlock(renderer)->inlineContinuation(); + return toRenderBlock(renderer)->inlineElementContinuation(); } RenderBoxModelObject* RenderInline::continuationBefore(RenderObject* beforeChild) @@ -240,7 +240,7 @@ void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock, } // Hook |clone| up as the continuation of the middle block. - middleBlock->setInlineContinuation(clone); + middleBlock->setContinuation(clone); // We have been reparented and are now under the fromBlock. We need // to walk up our inline parent chain until we hit the containing block. @@ -516,7 +516,7 @@ VisiblePosition RenderInline::positionForPoint(const IntPoint& point) RenderBox* contBlock = c->isInline() ? c->containingBlock() : toRenderBlock(c); if (c->isInline() || c->firstChild()) return c->positionForCoordinates(parentBlockX - contBlock->x(), parentBlockY - contBlock->y()); - c = toRenderBlock(c)->inlineContinuation(); + c = toRenderBlock(c)->inlineElementContinuation(); } return RenderBoxModelObject::positionForPoint(point); @@ -815,7 +815,7 @@ void RenderInline::updateHitTestResult(HitTestResult& result, const IntPoint& po Node* n = node(); IntPoint localPoint(point); if (n) { - if (isInlineContinuation()) { + if (isInlineElementContinuation()) { // We're in the continuation of a split inline. Adjust our local point to be in the coordinate space // of the principal renderer's containing block. This will end up being the innerNonSharedNode. RenderBlock* firstBlock = n->renderer()->containingBlock(); diff --git a/WebCore/rendering/RenderInline.h b/WebCore/rendering/RenderInline.h index 4084b6e..a719a50 100644 --- a/WebCore/rendering/RenderInline.h +++ b/WebCore/rendering/RenderInline.h @@ -60,6 +60,9 @@ public: InlineFlowBox* lastLineBox() const { return m_lineBoxes.lastLineBox(); } RenderBoxModelObject* continuation() const { return m_continuation; } + void setContinuation(RenderBoxModelObject* c) { m_continuation = c; } + virtual RenderBoxModelObject* virtualContinuation() const { return continuation(); } + RenderInline* inlineElementContinuation() const; virtual void updateDragState(bool dragOn); @@ -71,8 +74,6 @@ public: int verticalPositionFromCache(bool firstLine) const; void invalidateVerticalPosition() { m_verticalPosition = PositionUndefined; } - RenderInline* inlineContinuation() const; - private: virtual RenderObjectChildList* virtualChildren() { return children(); } virtual const RenderObjectChildList* virtualChildren() const { return children(); } @@ -127,8 +128,6 @@ private: virtual void dirtyLinesFromChangedChild(RenderObject* child) { m_lineBoxes.dirtyLinesFromChangedChild(this, child); } virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const; - - void setContinuation(RenderBoxModelObject* c) { m_continuation = c; } virtual void childBecameNonInline(RenderObject* child); diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp index 80e334a..8c7f23d 100644 --- a/WebCore/rendering/RenderLayer.cpp +++ b/WebCore/rendering/RenderLayer.cpp @@ -166,6 +166,7 @@ RenderLayer::RenderLayer(RenderBoxModelObject* renderer) , m_hasVisibleContent(false) , m_visibleDescendantStatusDirty(false) , m_hasVisibleDescendant(false) + , m_isPaginated(false) , m_3DTransformedDescendantStatusDirty(true) , m_has3DTransformedDescendant(false) #if USE(ACCELERATED_COMPOSITING) @@ -308,7 +309,12 @@ void RenderLayer::updateLayerPositions(UpdateLayerPositionsFlags flags, IntPoint updateVisibilityStatus(); updateTransform(); - + + if (flags & UpdatePagination) + updatePagination(); + else + m_isPaginated = false; + if (m_hasVisibleContent) { RenderView* view = renderer()->view(); ASSERT(view); @@ -351,6 +357,9 @@ void RenderLayer::updateLayerPositions(UpdateLayerPositionsFlags flags, IntPoint flags &= ~IsCompositingUpdateRoot; #endif + if (renderer()->hasColumns()) + flags |= UpdatePagination; + for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) child->updateLayerPositions(flags, cachedOffset); @@ -449,6 +458,30 @@ TransformationMatrix RenderLayer::renderableTransform(PaintBehavior paintBehavio return *m_transform; } +void RenderLayer::updatePagination() +{ + m_isPaginated = false; + if (isComposited() || !parent() || renderer()->isPositioned()) + return; // FIXME: We will have to deal with paginated compositing layers someday. + // FIXME: For now the RenderView can't be paginated. Eventually printing will move to a model where it is though. + + if (isNormalFlowOnly()) { + m_isPaginated = parent()->renderer()->hasColumns(); + return; + } + + // If we're not normal flow, then we need to look for a multi-column object between us and our stacking context. + RenderLayer* ancestorStackingContext = stackingContext(); + for (RenderLayer* curr = parent(); curr; curr = curr->parent()) { + if (curr->renderer()->hasColumns()) { + m_isPaginated = true; + return; + } + if (curr == ancestorStackingContext || (curr->parent() && curr->parent()->renderer()->isPositioned())) + return; + } +} + void RenderLayer::setHasVisibleContent(bool b) { if (m_hasVisibleContent == b && !m_visibleContentStatusDirty) @@ -644,10 +677,14 @@ void RenderLayer::updateLayerPosition() localPoint += offset; } } else if (parent()) { - IntSize columnOffset; - parent()->renderer()->adjustForColumns(columnOffset, localPoint); - localPoint += columnOffset; - + if (isComposited()) { + // FIXME: Composited layers ignore pagination, so about the best we can do is make sure they're offset into the appropriate column. + // They won't split across columns properly. + IntSize columnOffset; + parent()->renderer()->adjustForColumns(columnOffset, localPoint); + localPoint += columnOffset; + } + IntSize scrollOffset = parent()->scrolledContentOffset(); localPoint -= scrollOffset; } @@ -2386,10 +2423,8 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, } // Now walk the sorted list of children with negative z-indices. - if (m_negZOrderList) - for (Vector<RenderLayer*>::iterator it = m_negZOrderList->begin(); it != m_negZOrderList->end(); ++it) - it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags); - + paintList(m_negZOrderList, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags); + // Now establish the appropriate clip and paint our child RenderObjects. if (shouldPaint && !clipRectToApply.isEmpty()) { // Begin transparency layers lazily now that we know we have to paint something. @@ -2425,15 +2460,11 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, } // Paint any child layers that have overflow. - if (m_normalFlowList) - for (Vector<RenderLayer*>::iterator it = m_normalFlowList->begin(); it != m_normalFlowList->end(); ++it) - it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags); - - // Now walk the sorted list of children with positive z-indices. - if (m_posZOrderList) - for (Vector<RenderLayer*>::iterator it = m_posZOrderList->begin(); it != m_posZOrderList->end(); ++it) - it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags); + paintList(m_normalFlowList, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags); + // Now walk the sorted list of children with positive z-indices. + paintList(m_posZOrderList, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags); + if (renderer()->hasMask() && shouldPaint && !selectionOnly && !damageRect.isEmpty()) { setClip(p, paintDirtyRect, damageRect); @@ -2453,6 +2484,119 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, } } +void RenderLayer::paintList(Vector<RenderLayer*>* list, RenderLayer* rootLayer, GraphicsContext* p, + const IntRect& paintDirtyRect, PaintBehavior paintBehavior, + RenderObject* paintingRoot, RenderObject::OverlapTestRequestMap* overlapTestRequests, + PaintLayerFlags paintFlags) +{ + if (!list) + return; + + for (size_t i = 0; i < list->size(); ++i) { + RenderLayer* childLayer = list->at(i); + if (!childLayer->isPaginated()) + childLayer->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags); + else + paintPaginatedChildLayer(childLayer, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags); + } +} + +void RenderLayer::paintPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, GraphicsContext* context, + const IntRect& paintDirtyRect, PaintBehavior paintBehavior, + RenderObject* paintingRoot, RenderObject::OverlapTestRequestMap* overlapTestRequests, + PaintLayerFlags paintFlags) +{ + // We need to do multiple passes, breaking up our child layer into strips. + ASSERT(!renderer()->isPositioned()); + Vector<RenderLayer*> columnLayers; + RenderLayer* ancestorLayer = isNormalFlowOnly() ? parent() : stackingContext(); + for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) { + if (curr->renderer()->hasColumns()) + columnLayers.append(curr); + if (curr == ancestorLayer || (curr->parent() && curr->parent()->renderer()->isPositioned())) + break; + } + + ASSERT(columnLayers.size()); + + paintChildLayerIntoColumns(childLayer, rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags, columnLayers, columnLayers.size() - 1); +} + +void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLayer* rootLayer, GraphicsContext* context, + const IntRect& paintDirtyRect, PaintBehavior paintBehavior, + RenderObject* paintingRoot, RenderObject::OverlapTestRequestMap* overlapTestRequests, + PaintLayerFlags paintFlags, const Vector<RenderLayer*>& columnLayers, size_t colIndex) +{ + RenderBlock* columnBlock = toRenderBlock(columnLayers[colIndex]->renderer()); + + ASSERT(columnBlock && columnBlock->hasColumns()); + if (!columnBlock || !columnBlock->hasColumns()) + return; + + int layerX = 0; + int layerY = 0; + columnBlock->layer()->convertToLayerCoords(rootLayer, layerX, layerY); + + Vector<IntRect>* colRects = columnBlock->columnRects(); + unsigned colCount = colRects->size(); + int currYOffset = 0; + for (unsigned i = 0; i < colCount; i++) { + // For each rect, we clip to the rect, and then we adjust our coords. + IntRect colRect = colRects->at(i); + int currXOffset = colRect.x() - (columnBlock->borderLeft() + columnBlock->paddingLeft()); + colRect.move(layerX, layerY); + + IntRect localDirtyRect(paintDirtyRect); + localDirtyRect.intersect(colRect); + + if (!localDirtyRect.isEmpty()) { + context->save(); + + // Each strip pushes a clip, since column boxes are specified as being + // like overflow:hidden. + context->clip(colRect); + + if (!colIndex) { + // Apply a translation transform to change where the layer paints. + TransformationMatrix oldTransform; + bool oldHasTransform = childLayer->transform(); + if (oldHasTransform) + oldTransform = *childLayer->transform(); + TransformationMatrix newTransform(oldTransform); + newTransform.translateRight(currXOffset, currYOffset); + + childLayer->m_transform.set(new TransformationMatrix(newTransform)); + childLayer->paintLayer(rootLayer, context, localDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags); + if (oldHasTransform) + childLayer->m_transform.set(new TransformationMatrix(oldTransform)); + else + childLayer->m_transform.clear(); + } else { + // Adjust the transform such that the renderer's upper left corner will paint at (0,0) in user space. + // This involves subtracting out the position of the layer in our current coordinate space. + int childX = 0; + int childY = 0; + columnLayers[colIndex - 1]->convertToLayerCoords(rootLayer, childX, childY); + TransformationMatrix transform; + transform.translateRight(childX + currXOffset, childY + currYOffset); + + // Apply the transform. + context->concatCTM(transform.toAffineTransform()); + + // Now do a paint with the root layer shifted to be the next multicol block. + paintChildLayerIntoColumns(childLayer, columnLayers[colIndex - 1], context, transform.inverse().mapRect(localDirtyRect), paintBehavior, + paintingRoot, overlapTestRequests, paintFlags, + columnLayers, colIndex - 1); + } + + context->restore(); + } + + // Move to the next position. + currYOffset -= colRect.height(); + } +} + static inline IntRect frameVisibleRect(RenderObject* renderer) { FrameView* frameView = renderer->document()->view(); @@ -2585,8 +2729,8 @@ static bool isHitCandidate(const RenderLayer* hitLayer, bool canDepthSort, doubl // If zOffset is non-null (which indicates that the caller wants z offset information), // *zOffset on return is the z offset of the hit point relative to the containing flattening layer. RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result, - const IntRect& hitTestRect, const IntPoint& hitTestPoint, bool appliedTransform, - const HitTestingTransformState* transformState, double* zOffset) + const IntRect& hitTestRect, const IntPoint& hitTestPoint, bool appliedTransform, + const HitTestingTransformState* transformState, double* zOffset) { // The natural thing would be to keep HitTestingTransformState on the stack, but it's big, so we heap-allocate. @@ -2700,6 +2844,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont RenderLayer* candidateLayer = 0; // Begin by walking our list of positive layers from highest z-index down to the lowest z-index. +<<<<<<< HEAD if (m_posZOrderList) { for (int i = m_posZOrderList->size() - 1; i >= 0; --i) { #ifdef ANDROID_HITTEST_WITHSIZE @@ -2750,6 +2895,23 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont candidateLayer = hitLayer; } } +======= + RenderLayer* hitLayer = hitTestList(m_posZOrderList, rootLayer, request, result, hitTestRect, hitTestPoint, + localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants); + if (hitLayer) { + if (!depthSortDescendants) + return hitLayer; + candidateLayer = hitLayer; + } + + // Now check our overflow objects. + hitLayer = hitTestList(m_normalFlowList, rootLayer, request, result, hitTestRect, hitTestPoint, + localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants); + if (hitLayer) { + if (!depthSortDescendants) + return hitLayer; + candidateLayer = hitLayer; +>>>>>>> webkit.org at r60074 } // Next we want to see if the mouse pos is inside the child RenderObjects of the layer. @@ -2784,6 +2946,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont } // Now check our negative z-index children. +<<<<<<< HEAD if (m_negZOrderList) { for (int i = m_negZOrderList->size() - 1; i >= 0; --i) { #ifdef ANDROID_HITTEST_WITHSIZE @@ -2807,8 +2970,16 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont candidateLayer = hitLayer; } } +======= + hitLayer = hitTestList(m_negZOrderList, rootLayer, request, result, hitTestRect, hitTestPoint, + localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants); + if (hitLayer) { + if (!depthSortDescendants) + return hitLayer; + candidateLayer = hitLayer; +>>>>>>> webkit.org at r60074 } - + // If we found a layer, return. Child layers, and foreground always render in front of background. if (candidateLayer) return candidateLayer; @@ -2865,6 +3036,127 @@ bool RenderLayer::hitTestContents(const HitTestRequest& request, HitTestResult& return true; } +RenderLayer* RenderLayer::hitTestList(Vector<RenderLayer*>* list, RenderLayer* rootLayer, + const HitTestRequest& request, HitTestResult& result, + const IntRect& hitTestRect, const IntPoint& hitTestPoint, + const HitTestingTransformState* transformState, + double* zOffsetForDescendants, double* zOffset, + const HitTestingTransformState* unflattenedTransformState, + bool depthSortDescendants) +{ + if (!list) + return 0; + + RenderLayer* resultLayer = 0; + for (int i = list->size() - 1; i >= 0; --i) { + RenderLayer* childLayer = list->at(i); + RenderLayer* hitLayer = 0; + HitTestResult tempResult(result.point()); + if (childLayer->isPaginated()) + hitLayer = hitTestPaginatedChildLayer(childLayer, rootLayer, request, tempResult, hitTestRect, hitTestPoint, transformState, zOffsetForDescendants); + else + hitLayer = childLayer->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestPoint, false, transformState, zOffsetForDescendants); + if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState)) { + resultLayer = hitLayer; + result = tempResult; + if (!depthSortDescendants) + break; + } + } + + return resultLayer; +} + +RenderLayer* RenderLayer::hitTestPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result, + const IntRect& hitTestRect, const IntPoint& hitTestPoint, const HitTestingTransformState* transformState, double* zOffset) +{ + ASSERT(!renderer()->isPositioned()); + Vector<RenderLayer*> columnLayers; + RenderLayer* ancestorLayer = isNormalFlowOnly() ? parent() : stackingContext(); + for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) { + if (curr->renderer()->hasColumns()) + columnLayers.append(curr); + if (curr == ancestorLayer || (curr->parent() && curr->parent()->renderer()->isPositioned())) + break; + } + + ASSERT(columnLayers.size()); + return hitTestChildLayerColumns(childLayer, rootLayer, request, result, hitTestRect, hitTestPoint, transformState, zOffset, + columnLayers, columnLayers.size() - 1); +} + +RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result, + const IntRect& hitTestRect, const IntPoint& hitTestPoint, const HitTestingTransformState* transformState, double* zOffset, + const Vector<RenderLayer*>& columnLayers, size_t columnIndex) +{ + RenderBlock* columnBlock = toRenderBlock(columnLayers[columnIndex]->renderer()); + + ASSERT(columnBlock && columnBlock->hasColumns()); + if (!columnBlock || !columnBlock->hasColumns()) + return 0; + + int layerX = 0; + int layerY = 0; + columnBlock->layer()->convertToLayerCoords(rootLayer, layerX, layerY); + + Vector<IntRect>* colRects = columnBlock->columnRects(); + int colCount = colRects->size(); + + // We have to go backwards from the last column to the first. + int left = columnBlock->borderLeft() + columnBlock->paddingLeft(); + int currYOffset = 0; + int i; + for (i = 0; i < colCount; i++) + currYOffset -= colRects->at(i).height(); + for (i = colCount - 1; i >= 0; i--) { + // For each rect, we clip to the rect, and then we adjust our coords. + IntRect colRect = colRects->at(i); + int currXOffset = colRect.x() - left; + currYOffset += colRect.height(); + colRect.move(layerX, layerY); + + IntRect localClipRect(hitTestRect); + localClipRect.intersect(colRect); + + if (!localClipRect.isEmpty() && localClipRect.contains(hitTestPoint)) { + RenderLayer* hitLayer = 0; + if (!columnIndex) { + // Apply a translation transform to change where the layer paints. + TransformationMatrix oldTransform; + bool oldHasTransform = childLayer->transform(); + if (oldHasTransform) + oldTransform = *childLayer->transform(); + TransformationMatrix newTransform(oldTransform); + newTransform.translateRight(currXOffset, currYOffset); + + childLayer->m_transform.set(new TransformationMatrix(newTransform)); + hitLayer = childLayer->hitTestLayer(rootLayer, columnLayers[0], request, result, localClipRect, hitTestPoint, false, transformState, zOffset); + if (oldHasTransform) + childLayer->m_transform.set(new TransformationMatrix(oldTransform)); + else + childLayer->m_transform.clear(); + } else { + // Adjust the transform such that the renderer's upper left corner will be at (0,0) in user space. + // This involves subtracting out the position of the layer in our current coordinate space. + RenderLayer* nextLayer = columnLayers[columnIndex - 1]; + RefPtr<HitTestingTransformState> newTransformState = nextLayer->createLocalTransformState(rootLayer, nextLayer, localClipRect, hitTestPoint, transformState); + newTransformState->translate(currXOffset, currYOffset, HitTestingTransformState::AccumulateTransform); + IntPoint localPoint = roundedIntPoint(newTransformState->mappedPoint()); + IntRect localHitTestRect = newTransformState->mappedQuad().enclosingBoundingBox(); + newTransformState->flatten(); + + hitLayer = hitTestChildLayerColumns(childLayer, columnLayers[columnIndex - 1], request, result, localHitTestRect, localPoint, + newTransformState.get(), zOffset, columnLayers, columnIndex - 1); + } + + if (hitLayer) + return hitLayer; + } + } + + return 0; +} + void RenderLayer::updateClipRects(const RenderLayer* rootLayer) { if (m_clipRects) { diff --git a/WebCore/rendering/RenderLayer.h b/WebCore/rendering/RenderLayer.h index 746c6fa..f300d76 100644 --- a/WebCore/rendering/RenderLayer.h +++ b/WebCore/rendering/RenderLayer.h @@ -303,6 +303,7 @@ public: CheckForRepaint = 1 << 1, IsCompositingUpdateRoot = 1 << 2, UpdateCompositingLayers = 1 << 3, + UpdatePagination = 1 << 4 }; typedef unsigned UpdateLayerPositionsFlags; void updateLayerPositions(UpdateLayerPositionsFlags = DoFullRepaint | IsCompositingUpdateRoot | UpdateCompositingLayers, IntPoint* cachedOffset = 0); @@ -486,12 +487,35 @@ private: void paintLayer(RenderLayer* rootLayer, GraphicsContext*, const IntRect& paintDirtyRect, PaintBehavior, RenderObject* paintingRoot, RenderObject::OverlapTestRequestMap* = 0, - PaintLayerFlags paintFlags = 0); + PaintLayerFlags = 0); + void paintList(Vector<RenderLayer*>*, RenderLayer* rootLayer, GraphicsContext* p, + const IntRect& paintDirtyRect, PaintBehavior, + RenderObject* paintingRoot, RenderObject::OverlapTestRequestMap*, + PaintLayerFlags); + void paintPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, GraphicsContext*, + const IntRect& paintDirtyRect, PaintBehavior, + RenderObject* paintingRoot, RenderObject::OverlapTestRequestMap*, + PaintLayerFlags); + void paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLayer* rootLayer, GraphicsContext*, + const IntRect& paintDirtyRect, PaintBehavior, + RenderObject* paintingRoot, RenderObject::OverlapTestRequestMap*, + PaintLayerFlags, const Vector<RenderLayer*>& columnLayers, size_t columnIndex); RenderLayer* hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result, - const IntRect& hitTestRect, const IntPoint& hitTestPoint, bool appliedTransform, - const HitTestingTransformState* transformState = 0, double* zOffset = 0); - + const IntRect& hitTestRect, const IntPoint& hitTestPoint, bool appliedTransform, + const HitTestingTransformState* transformState = 0, double* zOffset = 0); + RenderLayer* hitTestList(Vector<RenderLayer*>*, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result, + const IntRect& hitTestRect, const IntPoint& hitTestPoint, + const HitTestingTransformState* transformState, double* zOffsetForDescendants, double* zOffset, + const HitTestingTransformState* unflattenedTransformState, bool depthSortDescendants); + RenderLayer* hitTestPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result, + const IntRect& hitTestRect, const IntPoint& hitTestPoint, + const HitTestingTransformState* transformState, double* zOffset); + RenderLayer* hitTestChildLayerColumns(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result, + const IntRect& hitTestRect, const IntPoint& hitTestPoint, + const HitTestingTransformState* transformState, double* zOffset, + const Vector<RenderLayer*>& columnLayers, size_t columnIndex); + PassRefPtr<HitTestingTransformState> createLocalTransformState(RenderLayer* rootLayer, RenderLayer* containerLayer, const IntRect& hitTestRect, const IntPoint& hitTestPoint, const HitTestingTransformState* containerTransformState) const; @@ -548,6 +572,9 @@ private: void updateScrollCornerStyle(); void updateResizerStyle(); + 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; } @@ -641,6 +668,8 @@ protected: bool m_visibleDescendantStatusDirty : 1; bool m_hasVisibleDescendant : 1; + bool m_isPaginated : 1; // If we think this layer is split by a multi-column ancestor, then this bit will be set. + bool m_3DTransformedDescendantStatusDirty : 1; bool m_has3DTransformedDescendant : 1; // Set on a stacking context layer that has 3D descendants anywhere // in a preserves3D hierarchy. Hint to do 3D-aware hit testing. diff --git a/WebCore/rendering/RenderLayerBacking.cpp b/WebCore/rendering/RenderLayerBacking.cpp index 4957265..97c5544 100644 --- a/WebCore/rendering/RenderLayerBacking.cpp +++ b/WebCore/rendering/RenderLayerBacking.cpp @@ -62,7 +62,7 @@ namespace WebCore { using namespace HTMLNames; static bool hasBorderOutlineOrShadow(const RenderStyle*); -static bool hasBoxDecorationsOrBackground(const RenderStyle*); +static bool hasBoxDecorationsOrBackground(const RenderObject*); static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle*); static inline bool is3DCanvas(RenderObject* renderer) @@ -96,19 +96,7 @@ void RenderLayerBacking::createGraphicsLayer() m_graphicsLayer = GraphicsLayer::create(this); #ifndef NDEBUG - if (renderer()->node()) { - if (renderer()->node()->isDocumentNode()) - m_graphicsLayer->setName("Document Node"); - else { - if (renderer()->node()->isHTMLElement() && renderer()->node()->hasID()) - m_graphicsLayer->setName(renderer()->renderName() + String(" ") + static_cast<HTMLElement*>(renderer()->node())->getIDAttribute()); - else - m_graphicsLayer->setName(renderer()->renderName()); - } - } else if (m_owningLayer->isReflection()) - m_graphicsLayer->setName("Reflection"); - else - m_graphicsLayer->setName("Anonymous Node"); + m_graphicsLayer->setName(nameForLayer()); #endif // NDEBUG updateLayerOpacity(renderer()->style()); @@ -466,7 +454,7 @@ bool RenderLayerBacking::updateForegroundLayer(bool needsForegroundLayer) if (!m_foregroundLayer) { m_foregroundLayer = GraphicsLayer::create(this); #ifndef NDEBUG - m_foregroundLayer->setName("Foreground"); + m_foregroundLayer->setName(nameForLayer() + " (foreground)"); #endif m_foregroundLayer->setDrawsContent(true); m_foregroundLayer->setPaintingPhase(GraphicsLayerPaintForeground); @@ -545,9 +533,9 @@ static bool hasBorderOutlineOrShadow(const RenderStyle* style) return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow(); } -static bool hasBoxDecorationsOrBackground(const RenderStyle* style) +static bool hasBoxDecorationsOrBackground(const RenderObject* renderer) { - return hasBorderOutlineOrShadow(style) || style->hasBackground(); + return hasBorderOutlineOrShadow(renderer->style()) || renderer->hasBackground(); } static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle* style) @@ -563,36 +551,32 @@ bool RenderLayerBacking::rendererHasBackground() const if (!htmlObject) return false; - RenderStyle* style = htmlObject->style(); - if (style->hasBackground()) + if (htmlObject->hasBackground()) return true; RenderObject* bodyObject = htmlObject->firstChild(); if (!bodyObject) return false; - style = bodyObject->style(); - return style->hasBackground(); + return bodyObject->hasBackground(); } - return renderer()->style()->hasBackground(); + return renderer()->hasBackground(); } -const Color& RenderLayerBacking::rendererBackgroundColor() const +const Color RenderLayerBacking::rendererBackgroundColor() const { // FIXME: share more code here if (renderer()->node() && renderer()->node()->isDocumentNode()) { RenderObject* htmlObject = renderer()->firstChild(); - RenderStyle* style = htmlObject->style(); - if (style->hasBackground()) - return style->backgroundColor(); + if (htmlObject->hasBackground()) + return htmlObject->style()->visitedDependentColor(CSSPropertyBackgroundColor); RenderObject* bodyObject = htmlObject->firstChild(); - style = bodyObject->style(); - return style->backgroundColor(); + return bodyObject->style()->visitedDependentColor(CSSPropertyBackgroundColor); } - return renderer()->style()->backgroundColor(); + return renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor); } // A "simple container layer" is a RenderLayer which has no visible content to render. @@ -610,7 +594,7 @@ bool RenderLayerBacking::isSimpleContainerCompositingLayer() const // Reject anything that has a border, a border-radius or outline, // or any background (color or image). // FIXME: we could optimize layers for simple backgrounds. - if (hasBoxDecorationsOrBackground(style)) + if (hasBoxDecorationsOrBackground(renderObject)) return false; // If we have got this far and the renderer has no children, then we're ok. @@ -720,7 +704,7 @@ bool RenderLayerBacking::containsPaintedContent() const // FIXME: we could optimize cases where the image, video or canvas is known to fill the border box entirely, // and set background color on the layer in that case, instead of allocating backing store and painting. if (renderer()->isVideo() || is3DCanvas(renderer())) - return hasBoxDecorationsOrBackground(renderer()->style()); + return hasBoxDecorationsOrBackground(renderer()); return true; } @@ -730,7 +714,7 @@ bool RenderLayerBacking::containsPaintedContent() const bool RenderLayerBacking::isDirectlyCompositedImage() const { RenderObject* renderObject = renderer(); - return renderObject->isImage() && !hasBoxDecorationsOrBackground(renderObject->style()); + return renderObject->isImage() && !hasBoxDecorationsOrBackground(renderObject); } void RenderLayerBacking::rendererContentChanged() @@ -1262,6 +1246,25 @@ AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(int cssPropert return AnimatedPropertyInvalid; } +#ifndef NDEBUG +String RenderLayerBacking::nameForLayer() const +{ + String name = renderer()->renderName(); + if (Node* node = renderer()->node()) { + if (node->isElementNode()) + name += " " + static_cast<Element *>(node)->tagName(); + + if (node->isHTMLElement() && static_cast<HTMLElement *>(node)->hasID()) + name += " \'" + static_cast<Element *>(node)->getIDAttribute() + "\'"; + } + + if (m_owningLayer->isReflection()) + name += " (reflection)"; + + return name; +} +#endif + } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/rendering/RenderLayerBacking.h b/WebCore/rendering/RenderLayerBacking.h index ff8c76c..faa553c 100644 --- a/WebCore/rendering/RenderLayerBacking.h +++ b/WebCore/rendering/RenderLayerBacking.h @@ -159,7 +159,7 @@ private: void updateImageContents(); bool rendererHasBackground() const; - const Color& rendererBackgroundColor() const; + const Color rendererBackgroundColor() const; bool hasNonCompositingContent() const; @@ -169,6 +169,10 @@ private: static int graphicsLayerToCSSProperty(AnimatedPropertyID); static AnimatedPropertyID cssToGraphicsLayerProperty(int); +#ifndef NDEBUG + String nameForLayer() const; +#endif + private: RenderLayer* m_owningLayer; diff --git a/WebCore/rendering/RenderListBox.cpp b/WebCore/rendering/RenderListBox.cpp index 68591d6..1c21af4 100644 --- a/WebCore/rendering/RenderListBox.cpp +++ b/WebCore/rendering/RenderListBox.cpp @@ -312,7 +312,7 @@ void RenderListBox::paintItemForeground(PaintInfo& paintInfo, int tx, int ty, in if (!itemStyle) itemStyle = style(); - Color textColor = element->renderStyle() ? element->renderStyle()->color() : style()->color(); + Color textColor = element->renderStyle() ? element->renderStyle()->visitedDependentColor(CSSPropertyColor) : style()->visitedDependentColor(CSSPropertyColor); if (optionElement && optionElement->selected()) { if (document()->frame()->selection()->isFocusedAndActive() && document()->focusedNode() == node()) textColor = theme()->activeListBoxSelectionForegroundColor(); @@ -355,7 +355,7 @@ void RenderListBox::paintItemBackground(PaintInfo& paintInfo, int tx, int ty, in else backColor = theme()->inactiveListBoxSelectionBackgroundColor(); } else - backColor = element->renderStyle() ? element->renderStyle()->backgroundColor() : style()->backgroundColor(); + backColor = element->renderStyle() ? element->renderStyle()->visitedDependentColor(CSSPropertyBackgroundColor) : style()->visitedDependentColor(CSSPropertyBackgroundColor); // Draw the background for this list box item if (!element->renderStyle() || element->renderStyle()->visibility() != HIDDEN) { diff --git a/WebCore/rendering/RenderListItem.h b/WebCore/rendering/RenderListItem.h index 2ad9a41..13d81f2 100644 --- a/WebCore/rendering/RenderListItem.h +++ b/WebCore/rendering/RenderListItem.h @@ -65,6 +65,8 @@ private: virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); + virtual bool requiresForcedStyleRecalcPropagation() const { return true; } + void updateMarkerLocation(); inline int calcValue() const; void updateValueNow() const; diff --git a/WebCore/rendering/RenderListMarker.cpp b/WebCore/rendering/RenderListMarker.cpp index d0353ee..e148c81 100644 --- a/WebCore/rendering/RenderListMarker.cpp +++ b/WebCore/rendering/RenderListMarker.cpp @@ -101,8 +101,10 @@ static inline String toAlphabeticOrNumeric(int number, const UChar* sequence, in int length = 1; if (type == AlphabeticSequence) { - while ((numberShadow /= sequenceSize) > 0) - letters[lettersSize - ++length] = sequence[numberShadow % sequenceSize - 1]; + while ((numberShadow /= sequenceSize) > 0) { + --numberShadow; + letters[lettersSize - ++length] = sequence[numberShadow % sequenceSize]; + } } else { while ((numberShadow /= sequenceSize) > 0) letters[lettersSize - ++length] = sequence[numberShadow % sequenceSize]; @@ -1007,7 +1009,7 @@ void RenderListMarker::paint(PaintInfo& paintInfo, int tx, int ty) context->fillRect(selRect, selectionBackgroundColor(), style()->colorSpace()); } - const Color color(style()->color()); + const Color color(style()->visitedDependentColor(CSSPropertyColor)); context->setStrokeColor(color, style()->colorSpace()); context->setStrokeStyle(SolidStroke); context->setStrokeThickness(1.0f); diff --git a/WebCore/rendering/RenderMedia.h b/WebCore/rendering/RenderMedia.h index 0d24c4c..32d6d65 100644 --- a/WebCore/rendering/RenderMedia.h +++ b/WebCore/rendering/RenderMedia.h @@ -118,6 +118,8 @@ private: virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); + virtual bool requiresForcedStyleRecalcPropagation() const { return true; } + RefPtr<HTMLElement> m_controlsShadowRoot; RefPtr<MediaControlElement> m_panel; RefPtr<MediaControlMuteButtonElement> m_muteButton; diff --git a/WebCore/rendering/RenderMediaControlsChromium.cpp b/WebCore/rendering/RenderMediaControlsChromium.cpp index 50feb46..ede3d11 100644 --- a/WebCore/rendering/RenderMediaControlsChromium.cpp +++ b/WebCore/rendering/RenderMediaControlsChromium.cpp @@ -99,6 +99,12 @@ static bool paintMediaPlayButton(RenderObject* object, const RenderObject::Paint return paintMediaButton(paintInfo.context, rect, mediaElement->paused() ? mediaPlay : mediaPause); } +static Image* getMediaSliderThumb() +{ + static Image* mediaSliderThumb = platformResource("mediaSliderThumb"); + return mediaSliderThumb; +} + static bool paintMediaSlider(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) { HTMLMediaElement* mediaElement = toParentMediaElement(object); @@ -114,9 +120,9 @@ static bool paintMediaSlider(RenderObject* object, const RenderObject::PaintInfo context->save(); context->setShouldAntialias(true); context->setStrokeStyle(SolidStroke); - context->setStrokeColor(style->borderLeftColor(), DeviceColorSpace); + context->setStrokeColor(style->visitedDependentColor(CSSPropertyBorderLeftColor), DeviceColorSpace); context->setStrokeThickness(style->borderLeftWidth()); - context->setFillColor(style->backgroundColor(), DeviceColorSpace); + context->setFillColor(style->visitedDependentColor(CSSPropertyBackgroundColor), DeviceColorSpace); context->drawRect(rect); context->restore(); @@ -124,7 +130,18 @@ static bool paintMediaSlider(RenderObject* object, const RenderObject::PaintInfo // FIXME: Draw multiple ranges if there are multiple buffered ranges. IntRect bufferedRect = rect; bufferedRect.inflate(-style->borderLeftWidth()); - bufferedRect.setWidth((bufferedRect.width() * mediaElement->percentLoaded())); + + double bufferedWidth = 0.0; + if (mediaElement->percentLoaded() > 0.0) { + // Account for the width of the slider thumb. + Image* mediaSliderThumb = getMediaSliderThumb(); + double thumbWidth = mediaSliderThumb->width() / 2.0 + 1.0; + double rectWidth = bufferedRect.width() - thumbWidth; + if (rectWidth < 0.0) + rectWidth = 0.0; + bufferedWidth = rectWidth * mediaElement->percentLoaded() + thumbWidth; + } + bufferedRect.setWidth(bufferedWidth); // Don't bother drawing an empty area. if (!bufferedRect.isEmpty()) { @@ -133,7 +150,7 @@ static bool paintMediaSlider(RenderObject* object, const RenderObject::PaintInfo sliderTopRight.move(0, bufferedRect.height()); RefPtr<Gradient> gradient = Gradient::create(sliderTopLeft, sliderTopRight); - Color startColor = object->style()->color(); + 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())); @@ -159,7 +176,7 @@ static bool paintMediaSliderThumb(RenderObject* object, const RenderObject::Pain if (!hasSource(mediaElement)) return true; - static Image* mediaSliderThumb = platformResource("mediaSliderThumb"); + Image* mediaSliderThumb = getMediaSliderThumb(); return paintMediaButton(paintInfo.context, rect, mediaSliderThumb); } @@ -207,13 +224,13 @@ static bool paintMediaTimelineContainer(RenderObject* object, const RenderObject // Draw the left border using CSS defined width and color. context->setStrokeThickness(object->style()->borderLeftWidth()); - context->setStrokeColor(object->style()->borderLeftColor().rgb(), DeviceColorSpace); + context->setStrokeColor(object->style()->visitedDependentColor(CSSPropertyBorderLeftColor).rgb(), DeviceColorSpace); context->drawLine(IntPoint(rect.x() + 1, rect.y()), IntPoint(rect.x() + 1, rect.y() + rect.height())); // Draw the right border using CSS defined width and color. context->setStrokeThickness(object->style()->borderRightWidth()); - context->setStrokeColor(object->style()->borderRightColor().rgb(), DeviceColorSpace); + context->setStrokeColor(object->style()->visitedDependentColor(CSSPropertyBorderRightColor).rgb(), DeviceColorSpace); context->drawLine(IntPoint(rect.x() + rect.width() - 1, rect.y()), IntPoint(rect.x() + rect.width() - 1, rect.y() + rect.height())); diff --git a/WebCore/rendering/RenderMenuList.cpp b/WebCore/rendering/RenderMenuList.cpp index e2c6fd5..871c10f 100644 --- a/WebCore/rendering/RenderMenuList.cpp +++ b/WebCore/rendering/RenderMenuList.cpp @@ -409,7 +409,7 @@ PopupMenuStyle RenderMenuList::itemStyle(unsigned listIndex) const Element* element = listItems[listIndex]; RenderStyle* style = element->renderStyle() ? element->renderStyle() : element->computedStyle(); - return style ? PopupMenuStyle(style->color(), itemBackgroundColor(listIndex), style->font(), style->visibility() == VISIBLE, style->textIndent(), style->direction()) : menuStyle(); + return style ? PopupMenuStyle(style->visitedDependentColor(CSSPropertyColor), itemBackgroundColor(listIndex), style->font(), style->visibility() == VISIBLE, style->textIndent(), style->direction()) : menuStyle(); } Color RenderMenuList::itemBackgroundColor(unsigned listIndex) const @@ -417,18 +417,18 @@ Color RenderMenuList::itemBackgroundColor(unsigned listIndex) const SelectElement* select = toSelectElement(static_cast<Element*>(node())); const Vector<Element*>& listItems = select->listItems(); if (listIndex >= listItems.size()) - return style()->backgroundColor(); + return style()->visitedDependentColor(CSSPropertyBackgroundColor); Element* element = listItems[listIndex]; Color backgroundColor; if (element->renderStyle()) - backgroundColor = element->renderStyle()->backgroundColor(); + backgroundColor = element->renderStyle()->visitedDependentColor(CSSPropertyBackgroundColor); // If the item has an opaque background color, return that. if (!backgroundColor.hasAlpha()) return backgroundColor; // Otherwise, the item's background is overlayed on top of the menu background. - backgroundColor = style()->backgroundColor().blend(backgroundColor); + backgroundColor = style()->visitedDependentColor(CSSPropertyBackgroundColor).blend(backgroundColor); if (!backgroundColor.hasAlpha()) return backgroundColor; @@ -439,7 +439,7 @@ Color RenderMenuList::itemBackgroundColor(unsigned listIndex) const PopupMenuStyle RenderMenuList::menuStyle() const { RenderStyle* s = m_innerBlock ? m_innerBlock->style() : style(); - return PopupMenuStyle(s->color(), s->backgroundColor(), s->font(), s->visibility() == VISIBLE, s->textIndent(), s->direction()); + return PopupMenuStyle(s->visitedDependentColor(CSSPropertyColor), s->visitedDependentColor(CSSPropertyBackgroundColor), s->font(), s->visibility() == VISIBLE, s->textIndent(), s->direction()); } HostWindow* RenderMenuList::hostWindow() const diff --git a/WebCore/rendering/RenderMenuList.h b/WebCore/rendering/RenderMenuList.h index aeb6205..5ee8588 100644 --- a/WebCore/rendering/RenderMenuList.h +++ b/WebCore/rendering/RenderMenuList.h @@ -78,6 +78,8 @@ private: virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); + virtual bool requiresForcedStyleRecalcPropagation() const { return true; } + // PopupMenuClient methods virtual String itemText(unsigned listIndex) const; virtual String itemToolTip(unsigned listIndex) const; diff --git a/WebCore/rendering/RenderObject.cpp b/WebCore/rendering/RenderObject.cpp index d7df436..2893d67 100644 --- a/WebCore/rendering/RenderObject.cpp +++ b/WebCore/rendering/RenderObject.cpp @@ -1385,9 +1385,9 @@ Color RenderObject::selectionBackgroundColor() const { Color color; if (style()->userSelect() != SELECT_NONE) { - RefPtr<RenderStyle> pseudoStyle = getUncachedPseudoStyle(SELECTION); - if (pseudoStyle && pseudoStyle->backgroundColor().isValid()) - color = pseudoStyle->backgroundColor().blendWithWhite(); + RefPtr<RenderStyle> pseudoStyle = getUncachedPseudoStyle(SELECTION); + if (pseudoStyle && pseudoStyle->visitedDependentColor(CSSPropertyBackgroundColor).isValid()) + color = pseudoStyle->visitedDependentColor(CSSPropertyBackgroundColor).blendWithWhite(); else color = document()->frame()->selection()->isFocusedAndActive() ? theme()->activeSelectionBackgroundColor() : @@ -1404,9 +1404,9 @@ Color RenderObject::selectionForegroundColor() const return color; if (RefPtr<RenderStyle> pseudoStyle = getUncachedPseudoStyle(SELECTION)) { - color = pseudoStyle->textFillColor(); + color = pseudoStyle->visitedDependentColor(CSSPropertyWebkitTextFillColor); if (!color.isValid()) - color = pseudoStyle->color(); + color = pseudoStyle->visitedDependentColor(CSSPropertyColor); } else color = document()->frame()->selection()->isFocusedAndActive() ? theme()->activeSelectionForegroundColor() : @@ -2224,8 +2224,8 @@ void RenderObject::getTextDecorationColors(int decorations, Color& underline, Co } } curr = curr->parent(); - if (curr && curr->isRenderBlock() && toRenderBlock(curr)->inlineContinuation()) - curr = toRenderBlock(curr)->inlineContinuation(); + if (curr && curr->isAnonymousBlock() && toRenderBlock(curr)->continuation()) + curr = toRenderBlock(curr)->continuation(); } while (curr && decorations && (!quirksMode || !curr->node() || (!curr->node()->hasTagName(aTag) && !curr->node()->hasTagName(fontTag)))); diff --git a/WebCore/rendering/RenderObject.h b/WebCore/rendering/RenderObject.h index 3fce1ee..0c3e66d 100644 --- a/WebCore/rendering/RenderObject.h +++ b/WebCore/rendering/RenderObject.h @@ -325,6 +325,8 @@ public: bool cellWidthChanged() const { return m_cellWidthChanged; } void setCellWidthChanged(bool b = true) { m_cellWidthChanged = b; } + virtual bool requiresForcedStyleRecalcPropagation() const { return false; } + #if ENABLE(MATHML) virtual bool isRenderMathMLBlock() const { return false; } #endif // ENABLE(MATHML) @@ -384,7 +386,11 @@ public: { return m_isAnonymous && style()->display() == BLOCK && style()->styleType() == NOPSEUDO && !isListMarker(); } - bool isInlineContinuation() const { return (node() ? node()->renderer() != this : false) && isRenderInline(); } + bool isElementContinuation() const { return node() && node()->renderer() != this; } + bool isInlineElementContinuation() const { return isElementContinuation() && isInline(); } + bool isBlockElementContinuation() const { return isElementContinuation() && !isInline(); } + virtual RenderBoxModelObject* virtualContinuation() const { return 0; } + bool isFloating() const { return m_floating; } bool isPositioned() const { return m_positioned; } // absolute or fixed positioning bool isRelPositioned() const { return m_relPositioned; } // relative positioning @@ -399,6 +405,13 @@ public: bool hasBoxDecorations() const { return m_paintBackground; } bool mustRepaintBackgroundOrBorder() const; + bool hasBackground() const + { + Color color = style()->visitedDependentColor(CSSPropertyBackgroundColor); + if (color.isValid() && color.alpha() > 0) + return true; + return style()->hasBackgroundImage(); + } bool needsLayout() const { return m_needsLayout || m_normalChildNeedsLayout || m_posChildNeedsLayout || m_needsPositionedMovementLayout; } bool selfNeedsLayout() const { return m_needsLayout; } @@ -422,7 +435,6 @@ public: void drawArcForBoxSide(GraphicsContext*, int x, int y, float thickness, IntSize radius, int angleStart, int angleSpan, BoxSide, Color, EBorderStyle, bool firstCorner); -public: // 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; @@ -870,7 +882,7 @@ private: bool m_isDragging : 1; bool m_hasLayer : 1; - bool m_hasOverflowClip : 1; + bool m_hasOverflowClip : 1; // Set in the case of overflow:auto/scroll/hidden bool m_hasTransform : 1; bool m_hasReflection : 1; diff --git a/WebCore/rendering/RenderObjectChildList.cpp b/WebCore/rendering/RenderObjectChildList.cpp index 6d76f34..aa8f50f 100644 --- a/WebCore/rendering/RenderObjectChildList.cpp +++ b/WebCore/rendering/RenderObjectChildList.cpp @@ -340,12 +340,12 @@ void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, Pseudo // For <q><p/></q>, if this object is the inline continuation of the <q>, we only want to generate // :after content and not :before content. - if (newContentWanted && type == BEFORE && owner->isRenderInline() && toRenderInline(owner)->isInlineContinuation()) + if (newContentWanted && type == BEFORE && owner->isElementContinuation()) newContentWanted = false; // Similarly, if we're the beginning of a <q>, and there's an inline continuation for our object, // then we don't generate the :after content. - if (newContentWanted && type == AFTER && owner->isRenderInline() && toRenderInline(owner)->continuation()) + if (newContentWanted && type == AFTER && owner->virtualContinuation()) newContentWanted = false; // If we don't want generated content any longer, or if we have generated content, but it's no longer diff --git a/WebCore/rendering/RenderProgress.h b/WebCore/rendering/RenderProgress.h index 2070974..1137e99 100644 --- a/WebCore/rendering/RenderProgress.h +++ b/WebCore/rendering/RenderProgress.h @@ -36,6 +36,8 @@ public: double position() const { return m_position; } double animationProgress() const; + double animationStartTime() const { return m_animationStartTime; } + bool isDeterminate() const; HTMLProgressElement* progressElement() const; @@ -48,6 +50,8 @@ private: virtual void paint(PaintInfo&, int tx, int ty); virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); + virtual bool requiresForcedStyleRecalcPropagation() const { return true; } + void animationTimerFired(Timer<RenderProgress>*); void updateAnimationState(); void updateValuePartState(); diff --git a/WebCore/rendering/RenderRubyBase.cpp b/WebCore/rendering/RenderRubyBase.cpp index 9b2dc9e..b088937 100644 --- a/WebCore/rendering/RenderRubyBase.cpp +++ b/WebCore/rendering/RenderRubyBase.cpp @@ -118,7 +118,7 @@ void RenderRubyBase::moveBlockChildren(RenderRubyBase* toBase, RenderObject* fro if (child->isAnonymousBlock()) { RenderBlock* anonBlock = toRenderBlock(child); ASSERT(anonBlock->childrenInline()); - ASSERT(!anonBlock->inlineContinuation()); + ASSERT(!anonBlock->inlineElementContinuation()); anonBlock->moveAllChildrenTo(toBase, toBase->children()); anonBlock->deleteLineBoxTree(); anonBlock->destroy(); @@ -145,7 +145,7 @@ void RenderRubyBase::moveBlockChildren(RenderRubyBase* toBase, RenderObject* fro RenderBlock* anonBlock = toRenderBlock(child); ASSERT(anonBlock->childrenInline()); - ASSERT(!anonBlock->inlineContinuation()); + ASSERT(!anonBlock->inlineElementContinuation()); // Move inline children out of anonymous block. anonBlock->moveAllChildrenTo(this, children(), anonBlock); anonBlock->deleteLineBoxTree(); diff --git a/WebCore/rendering/RenderSVGResource.cpp b/WebCore/rendering/RenderSVGResource.cpp index 821e58a..129d800 100644 --- a/WebCore/rendering/RenderSVGResource.cpp +++ b/WebCore/rendering/RenderSVGResource.cpp @@ -44,7 +44,7 @@ static inline void registerPendingResource(const AtomicString& id, const SVGPain object->document()->accessSVGExtensions()->addPendingResource(id, static_cast<SVGStyledElement*>(svgElement)); } -static inline void adjustColorForPseudoRules(const RenderStyle* style, bool useFillPaint, Color& color) +inline void RenderSVGResource::adjustColorForPseudoRules(const RenderStyle* style, bool useFillPaint, Color& color) { if (style->insideLink() != InsideVisitedLink) return; @@ -95,7 +95,7 @@ RenderSVGResource* RenderSVGResource::fillPaintingResource(const RenderObject* o Color fillColor; if (fillPaint->paintType() == SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR) - fillColor = style->color(); + fillColor = style->visitedDependentColor(CSSPropertyColor); else fillColor = fillPaint->color(); @@ -149,7 +149,7 @@ RenderSVGResource* RenderSVGResource::strokePaintingResource(const RenderObject* Color strokeColor; if (strokePaint->paintType() == SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR) - strokeColor = style->color(); + strokeColor = style->visitedDependentColor(CSSPropertyColor); else strokeColor = strokePaint->color(); diff --git a/WebCore/rendering/RenderSVGResource.h b/WebCore/rendering/RenderSVGResource.h index 4e33e55..5334025 100644 --- a/WebCore/rendering/RenderSVGResource.h +++ b/WebCore/rendering/RenderSVGResource.h @@ -44,6 +44,7 @@ enum RenderSVGResourceMode { ApplyToTextMode = 1 << 3 // used in combination with ApplyTo{Fill|Stroke}Mode }; +class Color; class FloatRect; class GraphicsContext; class RenderObject; @@ -78,6 +79,9 @@ public: static RenderSVGResource* strokePaintingResource(const RenderObject*, const RenderStyle*); static RenderSVGResourceSolidColor* sharedSolidPaintingResource(); +private: + static void adjustColorForPseudoRules(const RenderStyle*, bool useFillPaint, Color&); + protected: void markForLayoutAndResourceInvalidation(RenderObject*); }; diff --git a/WebCore/rendering/RenderSlider.h b/WebCore/rendering/RenderSlider.h index 92ad73b..fc8ce24 100644 --- a/WebCore/rendering/RenderSlider.h +++ b/WebCore/rendering/RenderSlider.h @@ -58,6 +58,8 @@ namespace WebCore { virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); + virtual bool requiresForcedStyleRecalcPropagation() const { return true; } + PassRefPtr<RenderStyle> createThumbStyle(const RenderStyle* parentStyle); int trackSize(); diff --git a/WebCore/rendering/RenderTable.cpp b/WebCore/rendering/RenderTable.cpp index eac5c5d..6541ccd 100644 --- a/WebCore/rendering/RenderTable.cpp +++ b/WebCore/rendering/RenderTable.cpp @@ -571,7 +571,7 @@ void RenderTable::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty) paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Normal); - paintFillLayers(paintInfo, style()->backgroundColor(), style()->backgroundLayers(), tx, ty, w, h); + paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), tx, ty, w, h); paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Inset); if (style()->hasBorder() && !collapseBorders()) diff --git a/WebCore/rendering/RenderTable.h b/WebCore/rendering/RenderTable.h index ea81d64..3d0714f 100644 --- a/WebCore/rendering/RenderTable.h +++ b/WebCore/rendering/RenderTable.h @@ -25,6 +25,7 @@ #ifndef RenderTable_h #define RenderTable_h +#include "CSSPropertyNames.h" #include "RenderBlock.h" #include <wtf/Vector.h> @@ -50,7 +51,7 @@ public: int borderTop() const; int borderBottom() const; - const Color& bgColor() const { return style()->backgroundColor(); } + const Color bgColor() const { return style()->visitedDependentColor(CSSPropertyBackgroundColor); } int outerBorderTop() const; int outerBorderBottom() const; diff --git a/WebCore/rendering/RenderTableCell.cpp b/WebCore/rendering/RenderTableCell.cpp index 5779422..bce659a 100644 --- a/WebCore/rendering/RenderTableCell.cpp +++ b/WebCore/rendering/RenderTableCell.cpp @@ -876,7 +876,7 @@ void RenderTableCell::paintBackgroundsBehindCell(PaintInfo& paintInfo, int tx, i int w = width(); int h = height(); - Color c = backgroundObject->style()->backgroundColor(); + Color c = backgroundObject->style()->visitedDependentColor(CSSPropertyBackgroundColor); const FillLayer* bgLayer = backgroundObject->style()->backgroundLayers(); if (bgLayer->hasImage() || c.isValid()) { diff --git a/WebCore/rendering/RenderText.cpp b/WebCore/rendering/RenderText.cpp index bede6a6..cfd6026 100644 --- a/WebCore/rendering/RenderText.cpp +++ b/WebCore/rendering/RenderText.cpp @@ -29,6 +29,7 @@ #include "CharacterNames.h" #include "EllipsisBox.h" #include "FloatQuad.h" +#include "FontTranscoder.h" #include "FrameView.h" #include "InlineTextBox.h" #include "Range.h" @@ -139,7 +140,9 @@ bool RenderText::isWordBreak() const void RenderText::updateNeedsTranscoding() { - m_needsTranscoding = document()->decoder() && document()->decoder()->encoding().backslashAsCurrencySymbol() != '\\'; + const AtomicString& fontFamily = style()->font().family().family(); + const TextEncoding* encoding = document()->decoder() ? &document()->decoder()->encoding() : 0; + m_needsTranscoding = fontTranscoder().needsTranscoding(fontFamily, encoding); } void RenderText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) @@ -157,6 +160,9 @@ void RenderText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyl if (!oldStyle) { updateNeedsTranscoding(); needsResetText = m_needsTranscoding; + } else if (oldStyle->font().needsTranscoding() != style()->font().needsTranscoding() || (style()->font().needsTranscoding() && oldStyle->font().family().family() != style()->font().family().family())) { + updateNeedsTranscoding(); + needsResetText = true; } ETextTransform oldTransform = oldStyle ? oldStyle->textTransform() : TTNONE; @@ -252,7 +258,7 @@ void RenderText::deleteTextBoxes() PassRefPtr<StringImpl> RenderText::originalText() const { Node* e = node(); - return e ? static_cast<Text*>(e)->dataImpl() : 0; + return (e && e->isTextNode()) ? static_cast<Text*>(e)->dataImpl() : 0; } void RenderText::absoluteRects(Vector<IntRect>& rects, int tx, int ty) @@ -1036,10 +1042,12 @@ void RenderText::transformText(String& text) const void RenderText::setTextInternal(PassRefPtr<StringImpl> text) { ASSERT(text); - if (m_needsTranscoding) - m_text = document()->displayStringModifiedByEncoding(text); - else - m_text = text; + m_text = text; + if (m_needsTranscoding) { + const AtomicString& fontFamily = style()->font().family().family(); + const TextEncoding* encoding = document()->decoder() ? &document()->decoder()->encoding() : 0; + fontTranscoder().convert(m_text, fontFamily, encoding); + } ASSERT(m_text); #if ENABLE(SVG) diff --git a/WebCore/rendering/RenderTextControl.cpp b/WebCore/rendering/RenderTextControl.cpp index 1e80ff0..deb7168 100644 --- a/WebCore/rendering/RenderTextControl.cpp +++ b/WebCore/rendering/RenderTextControl.cpp @@ -134,7 +134,7 @@ void RenderTextControl::adjustInnerTextStyle(const RenderStyle* startStyle, Rend bool disabled = updateUserModifyProperty(node(), textBlockStyle); if (disabled) - textBlockStyle->setColor(disabledTextColor(textBlockStyle->color(), startStyle->backgroundColor())); + textBlockStyle->setColor(disabledTextColor(textBlockStyle->visitedDependentColor(CSSPropertyColor), startStyle->visitedDependentColor(CSSPropertyBackgroundColor))); } void RenderTextControl::createSubtreeIfNeeded(TextControlInnerElement* innerBlock) diff --git a/WebCore/rendering/RenderTextControl.h b/WebCore/rendering/RenderTextControl.h index b76d1f2..de0b21b 100644 --- a/WebCore/rendering/RenderTextControl.h +++ b/WebCore/rendering/RenderTextControl.h @@ -105,6 +105,8 @@ private: virtual bool canBeProgramaticallyScrolled(bool) const { return true; } + virtual bool requiresForcedStyleRecalcPropagation() const { return true; } + String finishText(Vector<UChar>&) const; bool m_wasChangedSinceLastChangeEvent; diff --git a/WebCore/rendering/RenderTextControlSingleLine.cpp b/WebCore/rendering/RenderTextControlSingleLine.cpp index f454c63..8c8bf7f 100644 --- a/WebCore/rendering/RenderTextControlSingleLine.cpp +++ b/WebCore/rendering/RenderTextControlSingleLine.cpp @@ -799,7 +799,7 @@ PopupMenuStyle RenderTextControlSingleLine::itemStyle(unsigned) const PopupMenuStyle RenderTextControlSingleLine::menuStyle() const { - return PopupMenuStyle(style()->color(), style()->backgroundColor(), style()->font(), style()->visibility() == VISIBLE, style()->textIndent(), style()->direction()); + return PopupMenuStyle(style()->visitedDependentColor(CSSPropertyColor), style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->font(), style()->visibility() == VISIBLE, style()->textIndent(), style()->direction()); } int RenderTextControlSingleLine::clientInsetLeft() const diff --git a/WebCore/rendering/RenderTextFragment.cpp b/WebCore/rendering/RenderTextFragment.cpp index 2164ae1..0556284 100644 --- a/WebCore/rendering/RenderTextFragment.cpp +++ b/WebCore/rendering/RenderTextFragment.cpp @@ -47,7 +47,7 @@ RenderTextFragment::RenderTextFragment(Node* node, StringImpl* str) PassRefPtr<StringImpl> RenderTextFragment::originalText() const { Node* e = node(); - RefPtr<StringImpl> result = (e ? static_cast<Text*>(e)->dataImpl() : contentString()); + RefPtr<StringImpl> result = ((e && e->isTextNode()) ? static_cast<Text*>(e)->dataImpl() : contentString()); if (result && (start() > 0 || start() < result->length())) result = result->substring(start(), end()); return result.release(); @@ -80,7 +80,7 @@ UChar RenderTextFragment::previousCharacter() const { if (start()) { Node* e = node(); - StringImpl* original = (e ? static_cast<Text*>(e)->dataImpl() : contentString()); + StringImpl* original = ((e && e->isTextNode()) ? static_cast<Text*>(e)->dataImpl() : contentString()); if (original) return (*original)[start() - 1]; } diff --git a/WebCore/rendering/RenderTheme.cpp b/WebCore/rendering/RenderTheme.cpp index b1c23b1..7a1afda 100644 --- a/WebCore/rendering/RenderTheme.cpp +++ b/WebCore/rendering/RenderTheme.cpp @@ -646,7 +646,7 @@ bool RenderTheme::isControlStyled(const RenderStyle* style, const BorderData& bo // Test the style to see if the UA border and background match. return (style->border() != border || *style->backgroundLayers() != background || - style->backgroundColor() != backgroundColor); + style->visitedDependentColor(CSSPropertyBackgroundColor) != backgroundColor); default: return false; } diff --git a/WebCore/rendering/RenderThemeChromiumSkia.cpp b/WebCore/rendering/RenderThemeChromiumSkia.cpp index 8b3b388..0956e38 100644 --- a/WebCore/rendering/RenderThemeChromiumSkia.cpp +++ b/WebCore/rendering/RenderThemeChromiumSkia.cpp @@ -308,8 +308,8 @@ static void paintButtonLike(RenderTheme* theme, RenderObject* o, const RenderObj const int right = rect.x() + rect.width(); const int bottom = rect.y() + rect.height(); SkColor baseColor = SkColorSetARGB(0xff, 0xdd, 0xdd, 0xdd); - if (o->style()->hasBackground()) - baseColor = o->style()->backgroundColor().rgb(); + if (o->hasBackground()) + baseColor = o->style()->visitedDependentColor(CSSPropertyBackgroundColor).rgb(); double h, s, l; Color(baseColor).getHSL(h, s, l); // Our standard gradient is from 0xdd to 0xf8. This is the amount of diff --git a/WebCore/rendering/RenderThemeChromiumWin.cpp b/WebCore/rendering/RenderThemeChromiumWin.cpp index 5d39698..cc7570c 100644 --- a/WebCore/rendering/RenderThemeChromiumWin.cpp +++ b/WebCore/rendering/RenderThemeChromiumWin.cpp @@ -31,6 +31,7 @@ #include "ChromiumBridge.h" #include "CSSValueKeywords.h" +#include "CurrentTime.h" #include "FontSelector.h" #include "FontUtilsChromiumWin.h" #include "GraphicsContext.h" @@ -615,8 +616,8 @@ bool RenderThemeChromiumWin::paintTextFieldInternal(RenderObject* o, // Fallback to white if the specified color object is invalid. // (Note ChromiumBridge::paintTextField duplicates this check). Color backgroundColor(Color::white); - if (o->style()->backgroundColor().isValid()) - backgroundColor = o->style()->backgroundColor(); + if (o->style()->visitedDependentColor(CSSPropertyBackgroundColor).isValid()) + backgroundColor = o->style()->visitedDependentColor(CSSPropertyBackgroundColor); // If we have background-image, don't fill the content area to expose the // parent's background. Also, we shouldn't fill the content area if the @@ -659,11 +660,6 @@ bool RenderThemeChromiumWin::paintTextFieldInternal(RenderObject* o, // MSDN says that update intervals for the bar is 30ms. // http://msdn.microsoft.com/en-us/library/bb760842(v=VS.85).aspx static const double progressAnimationFrameRate = 0.033; -// There is no documentation about the animation speed, frame-rate, nor -// size of moving overlay of the indeterminate progress bar. -// So we just observed real-world programs and guessed following parameters. -static const double progressIndeterminateOverlayPixelsPerSecond = 175; -static const int progressIndeterminateOverlayWidth = 120; double RenderThemeChromiumWin::animationRepeatIntervalForProgressBar(RenderProgress*) const { @@ -672,9 +668,9 @@ double RenderThemeChromiumWin::animationRepeatIntervalForProgressBar(RenderProgr double RenderThemeChromiumWin::animationDurationForProgressBar(RenderProgress* renderProgress) const { - if (renderProgress->isDeterminate()) - return 0; - return (renderProgress->width() + progressIndeterminateOverlayWidth) / progressIndeterminateOverlayPixelsPerSecond; + // On Chromium Windows port, animationProgress() and associated values aren't used. + // So here we can return arbitrary positive value. + return progressAnimationFrameRate; } void RenderThemeChromiumWin::adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const @@ -685,26 +681,22 @@ bool RenderThemeChromiumWin::paintProgressBar(RenderObject* o, const RenderObjec { RenderProgress* renderProgress = toRenderProgress(o); - int valuePart; IntRect valueRect; if (renderProgress->isDeterminate()) { - valuePart = PP_FILL; int dx = r.width() * renderProgress->position(); if (renderProgress->style()->direction() == RTL) valueRect = IntRect(r.x() + r.width() - dx, r.y(), dx, r.height()); else valueRect = IntRect(r.x(), r.y(), dx, r.height()); } else { - valuePart = PP_MOVEOVERLAY; - int dx = (r.width() + progressIndeterminateOverlayWidth) * renderProgress->animationProgress() - progressIndeterminateOverlayWidth; - valueRect = IntRect(r.x() + dx, r.y(), progressIndeterminateOverlayWidth, r.height()); + // For indeterminate bar, valueRect is ignored and it is computed by the theme engine + // because the animation is a platform detail and WebKit doesn't need to know how. + valueRect = IntRect(0, 0, 0, 0); } + double animatedSeconds = renderProgress->animationStartTime() ? WTF::currentTime() - renderProgress->animationStartTime() : 0; ThemePainter painter(i.context, r); - ChromiumBridge::paintProgressBar(painter.context(), - r, - valuePart, - valueRect); + ChromiumBridge::paintProgressBar(painter.context(), r, valueRect, renderProgress->isDeterminate(), animatedSeconds); return true; } diff --git a/WebCore/rendering/RenderThemeMac.mm b/WebCore/rendering/RenderThemeMac.mm index d1a3965..f1de775 100644 --- a/WebCore/rendering/RenderThemeMac.mm +++ b/WebCore/rendering/RenderThemeMac.mm @@ -994,7 +994,7 @@ bool RenderThemeMac::paintMenuListButton(RenderObject* o, const RenderObject::Pa paintInfo.context->save(); - paintInfo.context->setFillColor(o->style()->color(), o->style()->colorSpace()); + paintInfo.context->setFillColor(o->style()->visitedDependentColor(CSSPropertyColor), o->style()->colorSpace()); paintInfo.context->setStrokeStyle(NoStroke); FloatPoint arrow1[3]; diff --git a/WebCore/rendering/RenderThemeSafari.cpp b/WebCore/rendering/RenderThemeSafari.cpp index 9e97079..6a62384 100644 --- a/WebCore/rendering/RenderThemeSafari.cpp +++ b/WebCore/rendering/RenderThemeSafari.cpp @@ -830,7 +830,7 @@ bool RenderThemeSafari::paintMenuListButton(RenderObject* o, const RenderObject: paintInfo.context->save(); - paintInfo.context->setFillColor(o->style()->color(), DeviceColorSpace); + paintInfo.context->setFillColor(o->style()->visitedDependentColor(CSSPropertyColor), DeviceColorSpace); paintInfo.context->setStrokeColor(NoStroke, DeviceColorSpace); FloatPoint arrow[3]; diff --git a/WebCore/rendering/RenderTreeAsText.cpp b/WebCore/rendering/RenderTreeAsText.cpp index fd63c0e..cf76f0b 100644 --- a/WebCore/rendering/RenderTreeAsText.cpp +++ b/WebCore/rendering/RenderTreeAsText.cpp @@ -180,7 +180,7 @@ String quoteAndEscapeNonPrintables(const String& s) return String::adopt(result); } -static void writeRenderObject(TextStream& ts, const RenderObject& o, RenderAsTextBehavior behavior) +void RenderTreeAsText::writeRenderObject(TextStream& ts, const RenderObject& o, RenderAsTextBehavior behavior) { ts << o.renderName(); @@ -429,7 +429,7 @@ void write(TextStream& ts, const RenderObject& o, int indent, RenderAsTextBehavi writeIndent(ts, indent); - writeRenderObject(ts, o, behavior); + RenderTreeAsText::writeRenderObject(ts, o, behavior); ts << "\n"; if (o.isText() && !o.isBR()) { diff --git a/WebCore/rendering/RenderTreeAsText.h b/WebCore/rendering/RenderTreeAsText.h index ecee7f9..1635e79 100644 --- a/WebCore/rendering/RenderTreeAsText.h +++ b/WebCore/rendering/RenderTreeAsText.h @@ -49,6 +49,14 @@ String externalRepresentation(Frame*, RenderAsTextBehavior = RenderAsTextBehavio void write(TextStream&, const RenderObject&, int indent = 0, RenderAsTextBehavior = RenderAsTextBehaviorNormal); void writeIndent(TextStream&, int indent); +class RenderTreeAsText { +// FIXME: This is a cheesy hack to allow easy access to RenderStyle colors. It won't be needed if we convert +// it to use visitedDependentColor instead. (This just involves rebaselining many results though, so for now it's +// not being done). +public: +static void writeRenderObject(TextStream& ts, const RenderObject& o, RenderAsTextBehavior behavior); +}; + // Helper function shared with SVGRenderTreeAsText String quoteAndEscapeNonPrintables(const String&); diff --git a/WebCore/rendering/SVGInlineTextBox.cpp b/WebCore/rendering/SVGInlineTextBox.cpp index 3ae272e..8bd7fef 100644 --- a/WebCore/rendering/SVGInlineTextBox.cpp +++ b/WebCore/rendering/SVGInlineTextBox.cpp @@ -477,7 +477,7 @@ void SVGInlineTextBox::paintSelection(int boxStartOffset, const SVGChar& svgChar if (startPos >= endPos) return; - Color textColor = style->color(); + Color textColor = style->visitedDependentColor(CSSPropertyColor); Color color = renderer()->selectionBackgroundColor(); if (!color.isValid() || !color.alpha()) return; diff --git a/WebCore/rendering/SVGRenderTreeAsText.cpp b/WebCore/rendering/SVGRenderTreeAsText.cpp index 8b4c563..8668780 100644 --- a/WebCore/rendering/SVGRenderTreeAsText.cpp +++ b/WebCore/rendering/SVGRenderTreeAsText.cpp @@ -433,8 +433,8 @@ static void writeRenderSVGTextBox(TextStream& ts, const RenderBlock& text) Vector<SVGTextChunk>& chunks = const_cast<Vector<SVGTextChunk>& >(box->svgTextChunks()); ts << " at (" << text.x() << "," << text.y() << ") size " << box->width() << "x" << box->height() << " contains " << chunks.size() << " chunk(s)"; - if (text.parent() && (text.parent()->style()->color() != text.style()->color())) - writeNameValuePair(ts, "color", text.style()->color().name()); + if (text.parent() && (text.parent()->style()->visitedDependentColor(CSSPropertyColor) != text.style()->visitedDependentColor(CSSPropertyColor))) + writeNameValuePair(ts, "color", text.style()->visitedDependentColor(CSSPropertyColor).name()); } static inline bool containsInlineTextBox(SVGTextChunk& chunk, SVGInlineTextBox* box) diff --git a/WebCore/rendering/style/RenderStyle.cpp b/WebCore/rendering/style/RenderStyle.cpp index 7ef580f..220e657 100644 --- a/WebCore/rendering/style/RenderStyle.cpp +++ b/WebCore/rendering/style/RenderStyle.cpp @@ -995,42 +995,42 @@ static EBorderStyle borderStyleForColorProperty(const RenderStyle* style, int co return borderStyle; } -static Color colorIncludingFallback(const RenderStyle* style, int colorProperty, EBorderStyle borderStyle) +const Color RenderStyle::colorIncludingFallback(int colorProperty, EBorderStyle borderStyle) const { Color result; switch (colorProperty) { case CSSPropertyBackgroundColor: - return style->backgroundColor(); // Background color doesn't fall back. + return backgroundColor(); // Background color doesn't fall back. case CSSPropertyBorderLeftColor: - result = style->borderLeftColor(); - borderStyle = style->borderLeftStyle(); + result = borderLeftColor(); + borderStyle = borderLeftStyle(); break; case CSSPropertyBorderRightColor: - result = style->borderRightColor(); - borderStyle = style->borderRightStyle(); + result = borderRightColor(); + borderStyle = borderRightStyle(); break; case CSSPropertyBorderTopColor: - result = style->borderTopColor(); - borderStyle = style->borderTopStyle(); + result = borderTopColor(); + borderStyle = borderTopStyle(); break; case CSSPropertyBorderBottomColor: - result = style->borderBottomColor(); - borderStyle = style->borderBottomStyle(); + result = borderBottomColor(); + borderStyle = borderBottomStyle(); break; case CSSPropertyColor: - result = style->color(); + result = color(); break; case CSSPropertyOutlineColor: - result = style->outlineColor(); + result = outlineColor(); break; case CSSPropertyWebkitColumnRuleColor: - result = style->columnRuleColor(); + result = columnRuleColor(); break; case CSSPropertyWebkitTextFillColor: - result = style->textFillColor(); + result = textFillColor(); break; case CSSPropertyWebkitTextStrokeColor: - result = style->textStrokeColor(); + result = textStrokeColor(); break; default: ASSERT_NOT_REACHED(); @@ -1043,23 +1043,23 @@ static Color colorIncludingFallback(const RenderStyle* style, int colorProperty, && (borderStyle == INSET || borderStyle == OUTSET || borderStyle == RIDGE || borderStyle == GROOVE)) result.setRGB(238, 238, 238); else - result = style->color(); + result = color(); } return result; } -Color RenderStyle::visitedDependentColor(int colorProperty) const +const Color RenderStyle::visitedDependentColor(int colorProperty) const { EBorderStyle borderStyle = borderStyleForColorProperty(this, colorProperty); - Color unvisitedColor = colorIncludingFallback(this, colorProperty, borderStyle); + Color unvisitedColor = colorIncludingFallback(colorProperty, borderStyle); if (insideLink() != InsideVisitedLink) return unvisitedColor; RenderStyle* visitedStyle = getCachedPseudoStyle(VISITED_LINK); if (!visitedStyle) return unvisitedColor; - Color visitedColor = colorIncludingFallback(visitedStyle, colorProperty, borderStyle); + Color visitedColor = visitedStyle->colorIncludingFallback(colorProperty, borderStyle); // Take the alpha from the unvisited color, but get the RGB values from the visited color. return Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), unvisitedColor.alpha()); diff --git a/WebCore/rendering/style/RenderStyle.h b/WebCore/rendering/style/RenderStyle.h index 970b26a..e8f4d2f 100644 --- a/WebCore/rendering/style/RenderStyle.h +++ b/WebCore/rendering/style/RenderStyle.h @@ -32,6 +32,7 @@ #include "CSSHelper.h" #include "CSSImageGeneratorValue.h" #include "CSSPrimitiveValue.h" +#include "CSSPropertyNames.h" #include "CSSReflectionDirection.h" #include "CSSValueList.h" #include "CachedImage.h" @@ -113,7 +114,13 @@ class StyleImage; typedef Vector<RefPtr<RenderStyle>, 4> PseudoStyleCache; class RenderStyle: public RefCounted<RenderStyle> { - friend class CSSStyleSelector; + friend class AnimationBase; // Used by CSS animations. We can't allow them to animate based off visited colors. + friend class ApplyStyleCommand; // Editing has to only reveal unvisited info. + friend class CSSStyleSelector; // Sets members directly. + friend class CSSComputedStyleDeclaration; // Ignores visited styles, so needs to be able to see unvisited info. + friend class PropertyWrapperMaybeInvalidColor; // Used by CSS animations. We can't allow them to animate based off visited colors. + friend class RenderSVGResource; // FIXME: Needs to alter the visited state by hand. Should clean the SVG code up and move it into RenderStyle perhaps. + friend class RenderTreeAsText; // FIXME: Only needed so the render tree can keep lying and dump the wrong colors. Rebaselining would allow this to be yanked. protected: // The following bitfield is 32-bits long, which optimizes padding with the @@ -341,12 +348,6 @@ public: bool hasPadding() const { return surround->padding.nonZero(); } bool hasOffset() const { return surround->offset.nonZero(); } - bool hasBackground() const - { - if (backgroundColor().isValid() && backgroundColor().alpha() > 0) - return true; - return m_background->background().hasImage(); - } bool hasBackgroundImage() const { return m_background->background().hasImage(); } bool hasFixedBackgroundImage() const { return m_background->background().hasFixedImage(); } bool hasAppearance() const { return appearance() != NoControlPart; } @@ -401,19 +402,15 @@ public: unsigned short borderLeftWidth() const { return surround->border.borderLeftWidth(); } EBorderStyle borderLeftStyle() const { return surround->border.left().style(); } - const Color& borderLeftColor() const { return surround->border.left().color(); } bool borderLeftIsTransparent() const { return surround->border.left().isTransparent(); } unsigned short borderRightWidth() const { return surround->border.borderRightWidth(); } EBorderStyle borderRightStyle() const { return surround->border.right().style(); } - const Color& borderRightColor() const { return surround->border.right().color(); } bool borderRightIsTransparent() const { return surround->border.right().isTransparent(); } unsigned short borderTopWidth() const { return surround->border.borderTopWidth(); } EBorderStyle borderTopStyle() const { return surround->border.top().style(); } - const Color& borderTopColor() const { return surround->border.top().color(); } bool borderTopIsTransparent() const { return surround->border.top().isTransparent(); } unsigned short borderBottomWidth() const { return surround->border.borderBottomWidth(); } EBorderStyle borderBottomStyle() const { return surround->border.bottom().style(); } - const Color& borderBottomColor() const { return surround->border.bottom().color(); } bool borderBottomIsTransparent() const { return surround->border.bottom().isTransparent(); } unsigned short outlineSize() const { return max(0, outlineWidth() + outlineOffset()); } @@ -426,8 +423,7 @@ public: bool hasOutline() const { return outlineWidth() > 0 && outlineStyle() > BHIDDEN; } EBorderStyle outlineStyle() const { return m_background->outline().style(); } bool outlineStyleIsAuto() const { return m_background->outline().isAuto(); } - const Color& outlineColor() const { return m_background->outline().color(); } - + EOverflow overflowX() const { return static_cast<EOverflow>(noninherited_flags._overflowX); } EOverflow overflowY() const { return static_cast<EOverflow>(noninherited_flags._overflowY); } @@ -451,7 +447,6 @@ public: const FontDescription& fontDescription() const { return inherited->font.fontDescription(); } int fontSize() const { return inherited->font.pixelSize(); } - const Color& color() const { return inherited->color; } Length textIndent() const { return rareInheritedData->indent; } ETextAlign textAlign() const { return static_cast<ETextAlign>(inherited_flags._text_align); } ETextTransform textTransform() const { return static_cast<ETextTransform>(inherited_flags._text_transform); } @@ -535,7 +530,6 @@ public: return wordBreak() == BreakWordBreak || wordWrap() == BreakWordWrap; } - const Color& backgroundColor() const { return m_background->color(); } StyleImage* backgroundImage() const { return m_background->background().image(); } EFillRepeat backgroundRepeatX() const { return static_cast<EFillRepeat>(m_background->background().repeatX()); } EFillRepeat backgroundRepeatY() const { return static_cast<EFillRepeat>(m_background->background().repeatY()); } @@ -616,9 +610,7 @@ public: } const ShadowData* textShadow() const { return rareInheritedData->textShadow; } - const Color& textStrokeColor() const { return rareInheritedData->textStrokeColor; } float textStrokeWidth() const { return rareInheritedData->textStrokeWidth; } - const Color& textFillColor() const { return rareInheritedData->textFillColor; } ColorSpace colorSpace() const { return static_cast<ColorSpace>(rareInheritedData->colorSpace); } float opacity() const { return rareNonInheritedData->opacity; } ControlPart appearance() const { return static_cast<ControlPart>(rareNonInheritedData->m_appearance); } @@ -664,10 +656,10 @@ public: bool specifiesColumns() const { return !hasAutoColumnCount() || !hasAutoColumnWidth(); } float columnGap() const { return rareNonInheritedData->m_multiCol->m_gap; } bool hasNormalColumnGap() const { return rareNonInheritedData->m_multiCol->m_normalGap; } - const Color& columnRuleColor() const { return rareNonInheritedData->m_multiCol->m_rule.color(); } EBorderStyle columnRuleStyle() const { return rareNonInheritedData->m_multiCol->m_rule.style(); } unsigned short columnRuleWidth() const { return rareNonInheritedData->m_multiCol->ruleWidth(); } bool columnRuleIsTransparent() const { return rareNonInheritedData->m_multiCol->m_rule.isTransparent(); } + bool columnSpan() const { return rareNonInheritedData->m_multiCol->m_columnSpan; } EPageBreak columnBreakBefore() const { return static_cast<EPageBreak>(rareNonInheritedData->m_multiCol->m_breakBefore); } EPageBreak columnBreakInside() const { return static_cast<EPageBreak>(rareNonInheritedData->m_multiCol->m_breakInside); } EPageBreak columnBreakAfter() const { return static_cast<EPageBreak>(rareNonInheritedData->m_multiCol->m_breakAfter); } @@ -1002,6 +994,7 @@ public: void setColumnRuleStyle(EBorderStyle b) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_rule.m_style, b); } void setColumnRuleWidth(unsigned short w) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_rule.m_width, w); } void resetColumnRule() { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_rule, BorderValue()) } + void setColumnSpan(bool b) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_columnSpan, b); } void setColumnBreakBefore(EPageBreak p) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_breakBefore, p); } void setColumnBreakInside(EPageBreak p) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_breakInside, p); } void setColumnBreakAfter(EPageBreak p) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_breakAfter, p); } @@ -1120,7 +1113,7 @@ public: unsigned childIndex() const { return m_childIndex; } void setChildIndex(unsigned index) { m_childIndex = index; } - Color visitedDependentColor(int colorProperty) const; + const Color visitedDependentColor(int colorProperty) const; // Initial values for all the properties static bool initialBorderCollapse() { return false; } @@ -1200,6 +1193,7 @@ public: static bool initialVisuallyOrdered() { return false; } static float initialTextStrokeWidth() { return 0; } static unsigned short initialColumnCount() { return 1; } + static bool initialColumnSpan() { return false; } static const TransformOperations& initialTransform() { DEFINE_STATIC_LOCAL(TransformOperations, ops, ()); return ops; } static Length initialTransformOriginX() { return Length(50.0, Percent); } static Length initialTransformOriginY() { return Length(50.0, Percent); } @@ -1221,9 +1215,26 @@ public: static const Vector<StyleDashboardRegion>& noneDashboardRegions(); #endif +<<<<<<< HEAD #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR static Color initialTapHighlightColor() { return Color::tap; } #endif +======= +private: + // Color accessors are all private to make sure callers use visitedDependentColor instead to access them. + const Color& borderLeftColor() const { return surround->border.left().color(); } + const Color& borderRightColor() const { return surround->border.right().color(); } + const Color& borderTopColor() const { return surround->border.top().color(); } + const Color& borderBottomColor() const { return surround->border.bottom().color(); } + const Color& backgroundColor() const { return m_background->color(); } + const Color& color() const { return inherited->color; } + const Color& columnRuleColor() const { return rareNonInheritedData->m_multiCol->m_rule.color(); } + const Color& outlineColor() const { return m_background->outline().color(); } + const Color& textFillColor() const { return rareInheritedData->textFillColor; } + const Color& textStrokeColor() const { return rareInheritedData->textStrokeColor; } + + const Color colorIncludingFallback(int colorProperty, EBorderStyle borderStyle) const; +>>>>>>> webkit.org at r60074 }; } // namespace WebCore diff --git a/WebCore/rendering/style/StyleMultiColData.cpp b/WebCore/rendering/style/StyleMultiColData.cpp index bff4fb3..3366e9f 100644 --- a/WebCore/rendering/style/StyleMultiColData.cpp +++ b/WebCore/rendering/style/StyleMultiColData.cpp @@ -33,6 +33,7 @@ StyleMultiColData::StyleMultiColData() , m_autoWidth(true) , m_autoCount(true) , m_normalGap(true) + , m_columnSpan(false) , m_breakBefore(RenderStyle::initialPageBreak()) , m_breakAfter(RenderStyle::initialPageBreak()) , m_breakInside(RenderStyle::initialPageBreak()) @@ -48,6 +49,7 @@ StyleMultiColData::StyleMultiColData(const StyleMultiColData& o) , m_autoWidth(o.m_autoWidth) , m_autoCount(o.m_autoCount) , m_normalGap(o.m_normalGap) + , m_columnSpan(o.m_columnSpan) , m_breakBefore(o.m_breakBefore) , m_breakAfter(o.m_breakAfter) , m_breakInside(o.m_breakInside) @@ -56,10 +58,10 @@ StyleMultiColData::StyleMultiColData(const StyleMultiColData& o) 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_breakBefore == o.m_breakBefore && - m_autoWidth == o.m_autoWidth && m_autoCount == o.m_autoCount && m_normalGap == o.m_normalGap && - m_breakAfter == o.m_breakAfter && m_breakInside == o.m_breakInside; + return m_width == o.m_width && m_count == o.m_count && m_gap == o.m_gap + && m_rule == o.m_rule && 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; } } // namespace WebCore diff --git a/WebCore/rendering/style/StyleMultiColData.h b/WebCore/rendering/style/StyleMultiColData.h index d3fe720..9948846 100644 --- a/WebCore/rendering/style/StyleMultiColData.h +++ b/WebCore/rendering/style/StyleMultiColData.h @@ -57,10 +57,11 @@ public: unsigned short m_count; float m_gap; BorderValue m_rule; - + bool m_autoWidth : 1; bool m_autoCount : 1; bool m_normalGap : 1; + bool m_columnSpan : 1; unsigned m_breakBefore : 2; // EPageBreak unsigned m_breakAfter : 2; // EPageBreak unsigned m_breakInside : 2; // EPageBreak |