diff options
author | Ben Murdoch <benm@google.com> | 2010-06-15 19:36:43 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2010-06-16 14:52:28 +0100 |
commit | 545e470e52f0ac6a3a072bf559c796b42c6066b6 (patch) | |
tree | c0c14763654d84d37577dde512c3d3b4699a9e86 /WebCore/rendering | |
parent | 719298a66237d38ea5c05f1547123ad8aacbc237 (diff) | |
download | external_webkit-545e470e52f0ac6a3a072bf559c796b42c6066b6.zip external_webkit-545e470e52f0ac6a3a072bf559c796b42c6066b6.tar.gz external_webkit-545e470e52f0ac6a3a072bf559c796b42c6066b6.tar.bz2 |
Merge webkit.org at r61121: Initial merge by git.
Change-Id: Icd6db395c62285be384d137164d95d7466c98760
Diffstat (limited to 'WebCore/rendering')
73 files changed, 1135 insertions, 431 deletions
diff --git a/WebCore/rendering/HitTestRequest.h b/WebCore/rendering/HitTestRequest.h index ca1445a..97d8680 100644 --- a/WebCore/rendering/HitTestRequest.h +++ b/WebCore/rendering/HitTestRequest.h @@ -27,11 +27,12 @@ namespace WebCore { class HitTestRequest { public: enum RequestType { - ReadOnly = 0x1, - Active = 0x2, - MouseMove = 0x4, - MouseUp = 0x8, - IgnoreClipping = 0x10 + ReadOnly = 1 << 1, + Active = 1 << 2, + MouseMove = 1 << 3, + MouseUp = 1 << 4, + IgnoreClipping = 1 << 5, + SVGClipContent = 1 << 6 }; HitTestRequest(int requestType) @@ -44,6 +45,7 @@ public: bool mouseMove() const { return m_requestType & MouseMove; } bool mouseUp() const { return m_requestType & MouseUp; } bool ignoreClipping() const { return m_requestType & IgnoreClipping; } + bool svgClipContent() const { return m_requestType & SVGClipContent; } private: int m_requestType; diff --git a/WebCore/rendering/InlineTextBox.cpp b/WebCore/rendering/InlineTextBox.cpp index 0933ae4..2fc5823 100644 --- a/WebCore/rendering/InlineTextBox.cpp +++ b/WebCore/rendering/InlineTextBox.cpp @@ -382,8 +382,8 @@ void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) GraphicsContext* context = paintInfo.context; // Determine whether or not we have composition underlines to draw. - bool containsComposition = renderer()->node() && renderer()->document()->frame()->editor()->compositionNode() == renderer()->node(); - bool useCustomUnderlines = containsComposition && renderer()->document()->frame()->editor()->compositionUsesCustomUnderlines(); + bool containsComposition = renderer()->node() && renderer()->frame()->editor()->compositionNode() == renderer()->node(); + bool useCustomUnderlines = containsComposition && renderer()->frame()->editor()->compositionUsesCustomUnderlines(); // Set our font. RenderStyle* styleToUse = renderer()->style(m_firstLine); @@ -401,8 +401,8 @@ void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) if (containsComposition && !useCustomUnderlines) paintCompositionBackground(context, tx, ty, styleToUse, font, - renderer()->document()->frame()->editor()->compositionStart(), - renderer()->document()->frame()->editor()->compositionEnd()); + renderer()->frame()->editor()->compositionStart(), + renderer()->frame()->editor()->compositionEnd()); paintDocumentMarkers(context, tx, ty, styleToUse, font, true); @@ -531,7 +531,7 @@ void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) paintDocumentMarkers(context, tx, ty, styleToUse, font, false); if (useCustomUnderlines) { - const Vector<CompositionUnderline>& underlines = renderer()->document()->frame()->editor()->customCompositionUnderlines(); + const Vector<CompositionUnderline>& underlines = renderer()->frame()->editor()->customCompositionUnderlines(); size_t numUnderlines = underlines.size(); for (size_t index = 0; index < numUnderlines; ++index) { @@ -634,7 +634,7 @@ void InlineTextBox::paintCompositionBackground(GraphicsContext* context, int tx, void InlineTextBox::paintCustomHighlight(int tx, int ty, const AtomicString& type) { - Frame* frame = renderer()->document()->frame(); + Frame* frame = renderer()->frame(); if (!frame) return; Page* page = frame->page(); @@ -818,7 +818,7 @@ void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, int tx, int ty, co renderer()->document()->setRenderedRectForMarker(renderer()->node(), marker, markerRect); // Optionally highlight the text - if (renderer()->document()->frame()->markedTextMatchesAreHighlighted()) { + if (renderer()->frame()->markedTextMatchesAreHighlighted()) { Color color = marker.activeMatch ? renderer()->theme()->platformActiveTextSearchHighlightColor() : renderer()->theme()->platformInactiveTextSearchHighlightColor(); diff --git a/WebCore/rendering/LayoutState.cpp b/WebCore/rendering/LayoutState.cpp index c94e77b..18c3da7 100644 --- a/WebCore/rendering/LayoutState.cpp +++ b/WebCore/rendering/LayoutState.cpp @@ -90,6 +90,13 @@ LayoutState::LayoutState(RenderObject* root) RenderObject* container = root->container(); FloatPoint absContentPoint = container->localToAbsolute(FloatPoint(), false, true); m_offset = IntSize(absContentPoint.x(), absContentPoint.y()); + + if (container->hasOverflowClip()) { + RenderLayer* layer = toRenderBoxModelObject(container)->layer(); + m_clipped = true; + m_clipRect = IntRect(toPoint(m_offset), layer->size()); + m_offset -= layer->scrolledContentOffset(); + } } #ifndef NDEBUG diff --git a/WebCore/rendering/PointerEventsHitRules.cpp b/WebCore/rendering/PointerEventsHitRules.cpp index ababcfd..cc5aae4 100644 --- a/WebCore/rendering/PointerEventsHitRules.cpp +++ b/WebCore/rendering/PointerEventsHitRules.cpp @@ -22,13 +22,16 @@ namespace WebCore { -PointerEventsHitRules::PointerEventsHitRules(EHitTesting hitTesting, EPointerEvents pointerEvents) +PointerEventsHitRules::PointerEventsHitRules(EHitTesting hitTesting, const HitTestRequest& request, EPointerEvents pointerEvents) : requireVisible(false) , requireFill(false) , requireStroke(false) , canHitStroke(false) , canHitFill(false) { + if (request.svgClipContent()) + pointerEvents = PE_FILL; + if (hitTesting == SVG_PATH_HITTESTING) { switch (pointerEvents) { diff --git a/WebCore/rendering/PointerEventsHitRules.h b/WebCore/rendering/PointerEventsHitRules.h index c17c19c..72fbc45 100644 --- a/WebCore/rendering/PointerEventsHitRules.h +++ b/WebCore/rendering/PointerEventsHitRules.h @@ -20,6 +20,7 @@ #ifndef PointerEventsHitRules_h #define PointerEventsHitRules_h +#include "HitTestRequest.h" #include "RenderStyleConstants.h" namespace WebCore { @@ -32,7 +33,7 @@ public: SVG_TEXT_HITTESTING }; - PointerEventsHitRules(EHitTesting, EPointerEvents); + PointerEventsHitRules(EHitTesting, const HitTestRequest&, EPointerEvents); bool requireVisible; bool requireFill; diff --git a/WebCore/rendering/RenderApplet.cpp b/WebCore/rendering/RenderApplet.cpp index 7411c54..a1689a5 100644 --- a/WebCore/rendering/RenderApplet.cpp +++ b/WebCore/rendering/RenderApplet.cpp @@ -70,7 +70,7 @@ void RenderApplet::createWidgetIfNecessary() } } - Frame* frame = document()->frame(); + Frame* frame = this->frame(); ASSERT(frame); setWidget(frame->loader()->createJavaAppletWidget(IntSize(contentWidth, contentHeight), element, m_args)); } diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp index 5ac57f0..f60b13c 100644 --- a/WebCore/rendering/RenderBlock.cpp +++ b/WebCore/rendering/RenderBlock.cpp @@ -36,6 +36,7 @@ #include "RenderFlexibleBox.h" #include "RenderImage.h" #include "RenderInline.h" +#include "RenderLayer.h" #include "RenderMarquee.h" #include "RenderReplica.h" #include "RenderTableCell.h" @@ -234,6 +235,16 @@ void RenderBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldSty { RenderBox::styleDidChange(diff, oldStyle); + if (!isAnonymousBlock()) { + // Ensure that all of our continuation blocks pick up the new style. + for (RenderBlock* currCont = blockElementContinuation(); currCont; currCont = currCont->blockElementContinuation()) { + RenderBoxModelObject* nextCont = currCont->continuation(); + currCont->setContinuation(0); + currCont->setStyle(style()); + currCont->setContinuation(nextCont); + } + } + // FIXME: We could save this call when the change only affected non-inherited properties for (RenderObject* child = firstChild(); child; child = child->nextSibling()) { if (child->isAnonymousBlock()) { @@ -268,6 +279,68 @@ void RenderBlock::updateBeforeAfterContent(PseudoId pseudoId) return children()->updateBeforeAfterContent(this, pseudoId); } +RenderBlock* RenderBlock::continuationBefore(RenderObject* beforeChild) +{ + if (beforeChild && beforeChild->parent() == this) + return this; + + RenderBlock* curr = toRenderBlock(continuation()); + RenderBlock* nextToLast = this; + RenderBlock* last = this; + while (curr) { + if (beforeChild && beforeChild->parent() == curr) { + if (curr->firstChild() == beforeChild) + return last; + return curr; + } + + nextToLast = last; + last = curr; + curr = toRenderBlock(curr->continuation()); + } + + if (!beforeChild && !last->firstChild()) + return nextToLast; + return last; +} + +void RenderBlock::addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild) +{ + RenderBlock* flow = continuationBefore(beforeChild); + ASSERT(!beforeChild || beforeChild->parent()->isAnonymousColumnSpanBlock() || beforeChild->parent()->isRenderBlock()); + RenderBoxModelObject* beforeChildParent = 0; + if (beforeChild) + beforeChildParent = toRenderBoxModelObject(beforeChild->parent()); + else { + RenderBoxModelObject* cont = flow->continuation(); + if (cont) + beforeChildParent = cont; + else + beforeChildParent = flow; + } + + if (newChild->isFloatingOrPositioned()) + return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild); + + // A continuation always consists of two potential candidates: a block or an anonymous + // column span box holding column span children. + bool childIsNormal = newChild->isInline() || !newChild->style()->columnSpan(); + bool bcpIsNormal = beforeChildParent->isInline() || !beforeChildParent->style()->columnSpan(); + bool flowIsNormal = flow->isInline() || !flow->style()->columnSpan(); + + if (flow == beforeChildParent) + return flow->addChildIgnoringContinuation(newChild, beforeChild); + + // The goal here is to match up if we can, so that we can coalesce and create the + // minimal # of continuations needed for the inline. + if (childIsNormal == bcpIsNormal) + return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild); + if (flowIsNormal == childIsNormal) + return flow->addChildIgnoringContinuation(newChild, 0); // Just treat like an append. + return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild); +} + + void RenderBlock::addChildToAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild) { ASSERT(!continuation()); // We don't yet support column spans that aren't immediate children of the multi-column block. @@ -314,12 +387,158 @@ void RenderBlock::addChildToAnonymousColumnBlocks(RenderObject* newChild, Render return; } +RenderBlock* RenderBlock::containingColumnsBlock(bool allowAnonymousColumnBlock) +{ + for (RenderObject* curr = this; curr; curr = curr->parent()) { + if (!curr->isRenderBlock() || curr->isFloatingOrPositioned() || curr->isTableCell() || curr->isRoot() || curr->isRenderView() || curr->hasOverflowClip() + || curr->isInlineBlockOrInlineTable()) + return 0; + + RenderBlock* currBlock = toRenderBlock(curr); + if (currBlock->style()->specifiesColumns() && (allowAnonymousColumnBlock || !currBlock->isAnonymousColumnsBlock())) + return currBlock; + + if (currBlock->isAnonymousColumnSpanBlock()) + return 0; + } + return 0; +} + +RenderBlock* RenderBlock::clone() const +{ + RenderBlock* o = new (renderArena()) RenderBlock(node()); + o->setStyle(style()); + o->setChildrenInline(childrenInline()); + return o; +} + +void RenderBlock::splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock, + RenderBlock* middleBlock, + RenderObject* beforeChild, RenderBoxModelObject* oldCont) +{ + // Create a clone of this inline. + RenderBlock* cloneBlock = clone(); + cloneBlock->setContinuation(oldCont); + + // Now take all of the children from beforeChild to the end and remove + // them from |this| and place them in the clone. + if (!beforeChild && isAfterContent(lastChild())) + beforeChild = lastChild(); + moveChildrenTo(cloneBlock, beforeChild, 0); + + // Hook |clone| up as the continuation of the middle block. + middleBlock->setContinuation(cloneBlock); + + // We have been reparented and are now under the fromBlock. We need + // to walk up our block parent chain until we hit the containing anonymous columns block. + // Once we hit the anonymous columns block we're done. + RenderBoxModelObject* curr = toRenderBoxModelObject(parent()); + RenderBoxModelObject* currChild = this; + + while (curr && curr != fromBlock) { + ASSERT(curr->isRenderBlock() && !curr->isAnonymousBlock()); + + RenderBlock* blockCurr = toRenderBlock(curr); + + // Create a new clone. + RenderBlock* cloneChild = cloneBlock; + cloneBlock = blockCurr->clone(); + + // Insert our child clone as the first child. + cloneBlock->children()->appendChildNode(cloneBlock, cloneChild); + + // Hook the clone up as a continuation of |curr|. Note we do encounter + // anonymous blocks possibly as we walk up the block chain. When we split an + // anonymous block, there's no need to do any continuation hookup, since we haven't + // actually split a real element. + if (!blockCurr->isAnonymousBlock()) { + oldCont = blockCurr->continuation(); + blockCurr->setContinuation(cloneBlock); + cloneBlock->setContinuation(oldCont); + } + + // Someone may have indirectly caused a <q> to split. When this happens, the :after content + // has to move into the inline continuation. Call updateBeforeAfterContent to ensure that the inline's :after + // content gets properly destroyed. + if (document()->usesBeforeAfterRules()) + blockCurr->children()->updateBeforeAfterContent(blockCurr, AFTER); + + // Now we need to take all of the children starting from the first child + // *after* currChild and append them all to the clone. + RenderObject* afterContent = isAfterContent(cloneBlock->lastChild()) ? cloneBlock->lastChild() : 0; + blockCurr->moveChildrenTo(cloneBlock, currChild->nextSibling(), 0, afterContent); + + // Keep walking up the chain. + currChild = curr; + curr = toRenderBoxModelObject(curr->parent()); + } + + // Now we are at the columns block level. We need to put the clone into the toBlock. + toBlock->children()->appendChildNode(toBlock, cloneBlock); + + // Now take all the children after currChild and remove them from the fromBlock + // and put them in the toBlock. + fromBlock->moveChildrenTo(toBlock, currChild->nextSibling(), 0); +} + +void RenderBlock::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox, + RenderObject* newChild, RenderBoxModelObject* oldCont) +{ + RenderBlock* pre = 0; + RenderBlock* block = containingColumnsBlock(); + + // Delete our line boxes before we do the inline split into continuations. + block->deleteLineBoxTree(); + + bool madeNewBeforeBlock = false; + if (block->isAnonymousColumnsBlock()) { + // We can reuse this block and make it the preBlock of the next continuation. + pre = block; + pre->removePositionedObjects(0); + block = toRenderBlock(block->parent()); + } else { + // No anonymous block available for use. Make one. + pre = block->createAnonymousColumnsBlock(); + pre->setChildrenInline(false); + madeNewBeforeBlock = true; + } + + RenderBlock* post = block->createAnonymousColumnsBlock(); + post->setChildrenInline(false); + + RenderObject* boxFirst = madeNewBeforeBlock ? block->firstChild() : pre->nextSibling(); + if (madeNewBeforeBlock) + block->children()->insertChildNode(block, pre, boxFirst); + block->children()->insertChildNode(block, newBlockBox, boxFirst); + block->children()->insertChildNode(block, post, boxFirst); + block->setChildrenInline(false); + + if (madeNewBeforeBlock) + block->moveChildrenTo(pre, boxFirst, 0); + + splitBlocks(pre, post, newBlockBox, beforeChild, oldCont); + + // We already know the newBlockBox isn't going to contain inline kids, so avoid wasting + // time in makeChildrenNonInline by just setting this explicitly up front. + newBlockBox->setChildrenInline(false); + + // We delayed adding the newChild until now so that the |newBlockBox| would be fully + // connected, thus allowing newChild access to a renderArena should it need + // to wrap itself in additional boxes (e.g., table construction). + newBlockBox->addChild(newChild); + + // Always just do a full layout in order to ensure that line boxes (especially wrappers for images) + // get deleted properly. Because objects moves from the pre block into the post block, we want to + // make new line boxes instead of leaving the old line boxes around. + pre->setNeedsLayoutAndPrefWidthsRecalc(); + block->setNeedsLayoutAndPrefWidthsRecalc(); + post->setNeedsLayoutAndPrefWidthsRecalc(); +} + RenderObject* RenderBlock::splitAnonymousBlocksAroundChild(RenderObject* beforeChild) { while (beforeChild->parent() != this) { RenderBlock* blockToSplit = toRenderBlock(beforeChild->parent()); - ASSERT(blockToSplit->isAnonymousBlock() && !blockToSplit->continuation()); - if (blockToSplit->firstChild() != beforeChild) { // We have to split the parentBlock into two blocks. RenderBlock* post = createAnonymousBlockWithSameTypeAs(blockToSplit); @@ -333,7 +552,6 @@ RenderObject* RenderBlock::splitAnonymousBlocksAroundChild(RenderObject* beforeC } else beforeChild = blockToSplit; } - return beforeChild; } @@ -346,10 +564,10 @@ void RenderBlock::makeChildrenAnonymousColumnBlocks(RenderObject* beforeChild, R // Delete the block's line boxes before we do the split. block->deleteLineBoxTree(); - + if (beforeChild && beforeChild->parent() != this) beforeChild = splitAnonymousBlocksAroundChild(beforeChild); - + if (beforeChild != firstChild()) { pre = block->createAnonymousColumnsBlock(); pre->setChildrenInline(block->childrenInline()); @@ -391,19 +609,24 @@ void RenderBlock::makeChildrenAnonymousColumnBlocks(RenderObject* beforeChild, R post->setNeedsLayoutAndPrefWidthsRecalc(); } -static RenderBlock* columnsBlockForSpanningElement(RenderBlock* block, RenderObject* newChild) +RenderBlock* RenderBlock::columnsBlockForSpanningElement(RenderObject* newChild) { - // FIXME: The style of this function may seem weird. - // This function is the gateway for the addition of column-span support. Support will be added in three stages: + // FIXME: This function is the gateway for the addition of column-span support. It will + // be added to in three stages: // (1) Immediate children of a multi-column block can span. // (2) Nested block-level children with only block-level ancestors between them and the multi-column block can span. // (3) Nested children with block or inline ancestors between them and the multi-column block can span (this is when we // cross the streams and have to cope with both types of continuations mixed together). - // This function currently only supports (1). - if (!newChild->isText() && newChild->style()->columnSpan() && !newChild->isFloatingOrPositioned() - && !newChild->isInline() && !block->isAnonymousColumnSpanBlock() && block->style()->specifiesColumns()) - return block; - return 0; + // This function currently supports (1) and (2). + RenderBlock* columnsBlockAncestor = 0; + if (!newChild->isText() && newChild->style()->columnSpan() && !newChild->isFloatingOrPositioned() + && !newChild->isInline() && !isAnonymousColumnSpanBlock()) { + if (style()->specifiesColumns()) + columnsBlockAncestor = this; + else + columnsBlockAncestor = toRenderBlock(parent())->containingColumnsBlock(false); + } + return columnsBlockAncestor; } void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild) @@ -418,26 +641,34 @@ void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild, } // Check for a spanning element in columns. - RenderBlock* columnsBlockAncestor = columnsBlockForSpanningElement(this, newChild); + RenderBlock* columnsBlockAncestor = columnsBlockForSpanningElement(newChild); if (columnsBlockAncestor) { - ASSERT(columnsBlockAncestor == this); - - // We are placing a column-span element inside a block. We have to perform a split of this - // block's children. This involves creating an anonymous block box to hold - // the column-spanning |newChild|. We take all of the children from before |newChild| and put them into - // one anonymous columns block, and all of the children after |newChild| go into another anonymous block. + // We are placing a column-span element inside a block. RenderBlock* newBox = createAnonymousColumnSpanBlock(); - // Someone may have put the spanning element inside an element with generated content, causing a split. When this happens, - // the :after content has to move into the last anonymous block. Call updateBeforeAfterContent to ensure that our :after - // content gets properly destroyed. - bool isLastChild = (beforeChild == lastChild()); - if (document()->usesBeforeAfterRules()) - children()->updateBeforeAfterContent(this, AFTER); - if (isLastChild && beforeChild != lastChild()) - beforeChild = 0; // We destroyed the last child, so now we need to update our insertion - // point to be 0. It's just a straight append now. + if (columnsBlockAncestor != this) { + // We are nested inside a multi-column element and are being split by the span. We have to break up + // our block into continuations. + RenderBoxModelObject* oldContinuation = continuation(); + setContinuation(newBox); + + // Someone may have put a <p> inside a <q>, causing a split. When this happens, the :after content + // has to move into the inline continuation. Call updateBeforeAfterContent to ensure that our :after + // content gets properly destroyed. + bool isLastChild = (beforeChild == lastChild()); + if (document()->usesBeforeAfterRules()) + children()->updateBeforeAfterContent(this, AFTER); + if (isLastChild && beforeChild != lastChild()) + beforeChild = 0; // We destroyed the last child, so now we need to update our insertion + // point to be 0. It's just a straight append now. + + splitFlow(beforeChild, newBox, newChild, oldContinuation); + return; + } + // We have to perform a split of this block's children. This involves creating an anonymous block box to hold + // the column-spanning |newChild|. We take all of the children from before |newChild| and put them into + // one anonymous columns block, and all of the children after |newChild| go into another anonymous block. makeChildrenAnonymousColumnBlocks(beforeChild, newBox, newChild); return; } @@ -521,7 +752,14 @@ void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild, void RenderBlock::addChild(RenderObject* newChild, RenderObject* beforeChild) { - if (!isAnonymous() && firstChild() && (firstChild()->isAnonymousColumnsBlock() || firstChild()->isAnonymousColumnSpanBlock())) + if (continuation() && !isAnonymousBlock()) + return addChildToContinuation(newChild, beforeChild); + return addChildIgnoringContinuation(newChild, beforeChild); +} + +void RenderBlock::addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild) +{ + if (!isAnonymousBlock() && firstChild() && (firstChild()->isAnonymousColumnsBlock() || firstChild()->isAnonymousColumnSpanBlock())) return addChildToAnonymousColumnBlocks(newChild, beforeChild); return addChildIgnoringAnonymousColumnBlocks(newChild, beforeChild); } @@ -1885,11 +2123,13 @@ void RenderBlock::paintChildren(PaintInfo& paintInfo, int tx, int ty) PaintInfo info(paintInfo); info.phase = newPhase; info.paintingRoot = paintingRootForChildren(paintInfo); - bool isPrinting = document()->printing(); + bool checkPageBreaks = document()->printing() && !document()->settings()->paginateDuringLayoutEnabled(); + bool checkColumnBreaks = !checkPageBreaks && !view()->printRect().isEmpty() && !document()->settings()->paginateDuringLayoutEnabled(); for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) { // Check for page-break-before: always, and if it's set, break and bail. - if (isPrinting && !childrenInline() && child->style()->pageBreakBefore() == PBALWAYS + bool checkBeforeAlways = !childrenInline() && (checkPageBreaks && child->style()->pageBreakBefore() == PBALWAYS || checkColumnBreaks && child->style()->columnBreakBefore() == PBALWAYS); + if (checkBeforeAlways && (ty + child->y()) > paintInfo.rect.y() && (ty + child->y()) < paintInfo.rect.bottom()) { view()->setBestTruncatedAt(ty + child->y(), this, true); @@ -1897,7 +2137,8 @@ void RenderBlock::paintChildren(PaintInfo& paintInfo, int tx, int ty) } // Check for page-break-inside: avoid, and it it's set, break and bail. - if (isPrinting && !childrenInline() && child->style()->pageBreakInside() == PBAVOID + bool checkInsideAvoid = !childrenInline() && (checkPageBreaks && child->style()->pageBreakInside() == PBAVOID || checkColumnBreaks && child->style()->columnBreakInside() == PBAVOID); + if (checkInsideAvoid && ty + child->y() > paintInfo.rect.y() && ty + child->y() < paintInfo.rect.bottom() && ty + child->y() + child->height() > paintInfo.rect.bottom()) { @@ -1909,7 +2150,8 @@ void RenderBlock::paintChildren(PaintInfo& paintInfo, int tx, int ty) child->paint(info, tx, ty); // Check for page-break-after: always, and if it's set, break and bail. - if (isPrinting && !childrenInline() && child->style()->pageBreakAfter() == PBALWAYS + bool checkAfterAlways = !childrenInline() && (checkPageBreaks && child->style()->pageBreakAfter() == PBALWAYS || checkColumnBreaks && child->style()->columnBreakAfter() == PBALWAYS); + if (checkAfterAlways && (ty + child->y() + child->height()) > paintInfo.rect.y() && (ty + child->y() + child->height()) < paintInfo.rect.bottom()) { view()->setBestTruncatedAt(ty + child->y() + child->height() + max(0, child->collapsedMarginBottom()), this, true); @@ -1920,10 +2162,10 @@ void RenderBlock::paintChildren(PaintInfo& paintInfo, int tx, int ty) void RenderBlock::paintCaret(PaintInfo& paintInfo, int tx, int ty, CaretType type) { - SelectionController* selection = type == CursorCaret ? document()->frame()->selection() : document()->frame()->dragCaretController(); + SelectionController* selection = type == CursorCaret ? frame()->selection() : frame()->dragCaretController(); // Paint the caret if the SelectionController says so or if caret browsing is enabled - bool caretBrowsing = document()->frame()->settings() && document()->frame()->settings()->caretBrowsingEnabled(); + bool caretBrowsing = frame()->settings() && frame()->settings()->caretBrowsingEnabled(); RenderObject* caretPainter = selection->caretRenderer(); if (caretPainter == this && (selection->isContentEditable() || caretBrowsing)) { // Convert the painting offset into the local coordinate system of this renderer, @@ -1931,9 +2173,9 @@ void RenderBlock::paintCaret(PaintInfo& paintInfo, int tx, int ty, CaretType typ offsetForContents(tx, ty); if (type == CursorCaret) - document()->frame()->selection()->paintCaret(paintInfo.context, tx, ty, paintInfo.rect); + frame()->selection()->paintCaret(paintInfo.context, tx, ty, paintInfo.rect); else - document()->frame()->paintDragCaret(paintInfo.context, tx, ty, paintInfo.rect); + frame()->paintDragCaret(paintInfo.context, tx, ty, paintInfo.rect); } } @@ -2082,7 +2324,7 @@ RenderBlock* RenderBlock::blockElementContinuation() const RenderBlock* nextContinuation = toRenderBlock(m_continuation); if (nextContinuation->isAnonymousBlock()) return nextContinuation->blockElementContinuation(); - return 0; + return nextContinuation; } static ContinuationOutlineTableMap* continuationOutlineTable() @@ -3209,6 +3451,12 @@ void RenderBlock::clearFloats() m_floatingObjects->clear(); } + // We should not process floats if the parent node is not a RenderBlock. Otherwise, we will add + // floats in an invalid context. This will cause a crash arising from a bad cast on the parent. + // See <rdar://problem/8049753>, where float property is applied on a text node in a SVG. + if (!parent() || !parent()->isRenderBlock()) + return; + // Attempt to locate a previous sibling with overhanging floats. We skip any elements that are // out of flow (like floating/positioned elements), and we also skip over any objects that may have shifted // to avoid floats. @@ -3777,16 +4025,15 @@ VisiblePosition RenderBlock::positionForPointWithInlineChildren(const IntPoint& } } - Settings* settings = document()->settings(); - bool useWindowsBehavior = settings && settings->editingBehavior() == EditingWindowsBehavior; + bool moveCaretToBoundary = document()->frame()->editor()->behavior().shouldMoveCaretToHorizontalBoundaryWhenPastTopOrBottom(); - if (useWindowsBehavior && !closestBox && lastRootBoxWithChildren) { + if (!moveCaretToBoundary && !closestBox && lastRootBoxWithChildren) { // y coordinate is below last root line box, pretend we hit it closestBox = lastRootBoxWithChildren->closestLeafChildForXPos(pointInContents.x()); } if (closestBox) { - if (!useWindowsBehavior && pointInContents.y() < firstRootBoxWithChildren->lineTop() - verticalLineClickFudgeFactor) { + if (moveCaretToBoundary && pointInContents.y() < firstRootBoxWithChildren->lineTop() - verticalLineClickFudgeFactor) { // y coordinate is above first root line box, so return the start of the first return VisiblePosition(positionForBox(firstRootBoxWithChildren->firstLeafChild(), true), DOWNSTREAM); } @@ -3797,7 +4044,7 @@ VisiblePosition RenderBlock::positionForPointWithInlineChildren(const IntPoint& if (lastRootBoxWithChildren) { // We hit this case for Mac behavior when the Y coordinate is below the last box. - ASSERT(!useWindowsBehavior); + ASSERT(moveCaretToBoundary); return VisiblePosition(positionForBox(lastRootBoxWithChildren->lastLeafChild(), false), DOWNSTREAM); } @@ -3932,7 +4179,8 @@ void RenderBlock::setDesiredColumnCountAndWidth(int count, int width) bool destroyColumns = !firstChild() || (count == 1 && style()->hasAutoColumnWidth()) || firstChild()->isAnonymousColumnsBlock() - || firstChild()->isAnonymousColumnSpanBlock(); + || firstChild()->isAnonymousColumnSpanBlock() + || document()->settings()->paginateDuringLayoutEnabled(); if (destroyColumns) { if (hasColumns()) { delete gColumnInfoMap->take(this); @@ -3997,7 +4245,7 @@ int RenderBlock::layoutColumns(int endOfContent, int requestedColumnHeight) if (computeIntrinsicHeight && requestedColumnHeight >= 0) colHeight = requestedColumnHeight; else if (computeIntrinsicHeight) - colHeight = availableHeight / desiredColumnCount + columnSlop; + colHeight = min(availableHeight, availableHeight / desiredColumnCount + columnSlop); else colHeight = availableHeight; int originalColHeight = colHeight; diff --git a/WebCore/rendering/RenderBlock.h b/WebCore/rendering/RenderBlock.h index 7d9e2fc..8c61e2c 100644 --- a/WebCore/rendering/RenderBlock.h +++ b/WebCore/rendering/RenderBlock.h @@ -243,6 +243,8 @@ private: virtual void dirtyLinesFromChangedChild(RenderObject* child) { m_lineBoxes.dirtyLinesFromChangedChild(this, child); } + void addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild); + void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild); void addChildToAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild); virtual void addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild = 0); @@ -410,6 +412,14 @@ private: void updateScrollInfoAfterLayout(); RenderObject* splitAnonymousBlocksAroundChild(RenderObject* beforeChild); + void splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock, RenderBlock* middleBlock, + RenderObject* beforeChild, RenderBoxModelObject* oldCont); + void splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox, + RenderObject* newChild, RenderBoxModelObject* oldCont); + RenderBlock* clone() const; + RenderBlock* continuationBefore(RenderObject* beforeChild); + RenderBlock* containingColumnsBlock(bool allowAnonymousColumnBlock = true); + RenderBlock* columnsBlockForSpanningElement(RenderObject* newChild); struct FloatingObject : Noncopyable { enum Type { diff --git a/WebCore/rendering/RenderBlockLineLayout.cpp b/WebCore/rendering/RenderBlockLineLayout.cpp index 96b4c6e..2cf3865 100644 --- a/WebCore/rendering/RenderBlockLineLayout.cpp +++ b/WebCore/rendering/RenderBlockLineLayout.cpp @@ -29,6 +29,7 @@ #include "Logging.h" #include "RenderArena.h" #include "RenderInline.h" +#include "RenderLayer.h" #include "RenderListMarker.h" #include "RenderView.h" #include "TrailingFloatsRootInlineBox.h" diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp index caadbf0..c845ba7 100644 --- a/WebCore/rendering/RenderBox.cpp +++ b/WebCore/rendering/RenderBox.cpp @@ -858,7 +858,7 @@ bool RenderBox::repaintLayerRectsForImage(WrappedImagePtr image, const FillLayer void RenderBox::paintCustomHighlight(int tx, int ty, const AtomicString& type, bool behindText) { - Frame* frame = document()->frame(); + Frame* frame = this->frame(); if (!frame) return; Page* page = frame->page(); diff --git a/WebCore/rendering/RenderDataGrid.cpp b/WebCore/rendering/RenderDataGrid.cpp index 00cbd7c..916d253 100644 --- a/WebCore/rendering/RenderDataGrid.cpp +++ b/WebCore/rendering/RenderDataGrid.cpp @@ -182,7 +182,7 @@ void RenderDataGrid::invalidateScrollbarRect(Scrollbar*, const IntRect&) bool RenderDataGrid::isActive() const { - Page* page = document()->frame()->page(); + Page* page = frame()->page(); return page && page->focusController()->isActive(); } diff --git a/WebCore/rendering/RenderFileUploadControl.cpp b/WebCore/rendering/RenderFileUploadControl.cpp index d4d73bc..f42a657 100644 --- a/WebCore/rendering/RenderFileUploadControl.cpp +++ b/WebCore/rendering/RenderFileUploadControl.cpp @@ -28,6 +28,7 @@ #include "GraphicsContext.h" #include "HTMLInputElement.h" #include "HTMLNames.h" +#include "ShadowElement.h" #include "Icon.h" #include "LocalizedStrings.h" #include "Page.h" @@ -50,30 +51,6 @@ const int iconFilenameSpacing = 2; const int defaultWidthNumChars = 34; const int buttonShadowHeight = 2; -class ShadowInputElement : public HTMLInputElement { -public: - static PassRefPtr<ShadowInputElement> create(Node* shadowParent); - -private: - ShadowInputElement(Node* shadowParent); - - virtual bool isShadowNode() const { return true; } - virtual Node* shadowParentNode() { return m_shadowParent; } - - Node* m_shadowParent; -}; - -inline ShadowInputElement::ShadowInputElement(Node* shadowParent) - : HTMLInputElement(inputTag, shadowParent->document()) - , m_shadowParent(shadowParent) -{ -} - -inline PassRefPtr<ShadowInputElement> ShadowInputElement::create(Node* shadowParent) -{ - return new ShadowInputElement(shadowParent); -} - RenderFileUploadControl::RenderFileUploadControl(HTMLInputElement* input) : RenderBlock(input) , m_button(0) diff --git a/WebCore/rendering/RenderFrameSet.cpp b/WebCore/rendering/RenderFrameSet.cpp index 3ab2fff..600d65e 100644 --- a/WebCore/rendering/RenderFrameSet.cpp +++ b/WebCore/rendering/RenderFrameSet.cpp @@ -749,7 +749,7 @@ void RenderFrameSet::positionFramesWithFlattening() bool RenderFrameSet::flattenFrameSet() const { - return document()->frame() && document()->frame()->settings()->frameFlatteningEnabled(); + return frame() && frame()->settings()->frameFlatteningEnabled(); } void RenderFrameSet::startResizing(GridAxis& axis, int position) @@ -817,7 +817,7 @@ void RenderFrameSet::setIsResizing(bool isResizing) if (ancestor->isFrameSet()) toRenderFrameSet(ancestor)->m_isChildResizing = isResizing; } - if (Frame* frame = document()->frame()) + if (Frame* frame = this->frame()) frame->eventHandler()->setResizingFrameSet(isResizing ? frameSet() : 0); } diff --git a/WebCore/rendering/RenderIFrame.cpp b/WebCore/rendering/RenderIFrame.cpp index 146e028..8421c9e 100644 --- a/WebCore/rendering/RenderIFrame.cpp +++ b/WebCore/rendering/RenderIFrame.cpp @@ -27,6 +27,7 @@ #include "RenderIFrame.h" #include "FrameView.h" +#include "HTMLNames.h" #include "HTMLIFrameElement.h" #include "RenderView.h" #include "Settings.h" diff --git a/WebCore/rendering/RenderImage.cpp b/WebCore/rendering/RenderImage.cpp index 2e376e7..98b0f47 100644 --- a/WebCore/rendering/RenderImage.cpp +++ b/WebCore/rendering/RenderImage.cpp @@ -36,6 +36,7 @@ #include "HTMLNames.h" #include "HitTestResult.h" #include "Page.h" +#include "RenderLayer.h" #include "RenderTheme.h" #include "RenderView.h" #include "SelectionController.h" @@ -451,7 +452,7 @@ void RenderImage::paint(PaintInfo& paintInfo, int tx, int ty) void RenderImage::paintFocusRings(PaintInfo& paintInfo, const RenderStyle* style) { // Don't draw focus rings if printing. - if (document()->printing() || !document()->frame()->selection()->isFocusedAndActive()) + if (document()->printing() || !frame()->selection()->isFocusedAndActive()) return; if (paintInfo.context->paintingDisabled() && !paintInfo.context->updatingControlTints()) diff --git a/WebCore/rendering/RenderInline.cpp b/WebCore/rendering/RenderInline.cpp index 7531f93..e91822e 100644 --- a/WebCore/rendering/RenderInline.cpp +++ b/WebCore/rendering/RenderInline.cpp @@ -30,6 +30,7 @@ #include "Page.h" #include "RenderArena.h" #include "RenderBlock.h" +#include "RenderLayer.h" #include "RenderView.h" #include "TransformState.h" #include "VisiblePosition.h" @@ -1114,8 +1115,8 @@ void RenderInline::addDashboardRegions(Vector<DashboardRegionValue>& regions) region.bounds.setX(absPos.x() + region.bounds.x()); region.bounds.setY(absPos.y() + region.bounds.y()); - if (document()->frame()) { - float pageScaleFactor = document()->frame()->page()->chrome()->scaleFactor(); + if (frame()) { + float pageScaleFactor = frame()->page()->chrome()->scaleFactor(); if (pageScaleFactor != 1.0f) { region.bounds.scale(pageScaleFactor); region.clip.scale(pageScaleFactor); diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp index 3eab1f8..5d206dd 100644 --- a/WebCore/rendering/RenderLayer.cpp +++ b/WebCore/rendering/RenderLayer.cpp @@ -189,7 +189,7 @@ RenderLayer::RenderLayer(RenderBoxModelObject* renderer) RenderLayer::~RenderLayer() { if (inResizeMode() && !renderer()->documentBeingDestroyed()) { - if (Frame* frame = renderer()->document()->frame()) + if (Frame* frame = renderer()->frame()) frame->eventHandler()->resizeLayerDestroyed(); } @@ -1216,7 +1216,7 @@ static inline int adjustedScrollDelta(int beginningDelta) { void RenderLayer::panScrollFromPoint(const IntPoint& sourcePoint) { - Frame* frame = renderer()->document()->frame(); + Frame* frame = renderer()->frame(); if (!frame) return; @@ -1267,7 +1267,7 @@ void RenderLayer::scrollByRecursively(int xDelta, int yDelta) nextRenderer = nextRenderer->parent(); } - Frame* frame = renderer()->document()->frame(); + Frame* frame = renderer()->frame(); if (frame) frame->eventHandler()->updateAutoscrollRenderer(); } @@ -1347,7 +1347,7 @@ void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repai RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint(); IntRect rectForRepaint = renderer()->clippedOverflowRectForRepaint(repaintContainer); - Frame* frame = renderer()->document()->frame(); + Frame* frame = renderer()->frame(); if (frame) { // The caret rect needs to be invalidated after scrolling frame->selection()->setNeedsLayout(); @@ -1538,7 +1538,7 @@ IntRect RenderLayer::getRectToExpose(const IntRect &visibleRect, const IntRect & void RenderLayer::autoscroll() { - Frame* frame = renderer()->document()->frame(); + Frame* frame = renderer()->frame(); if (!frame) return; @@ -1645,7 +1645,7 @@ void RenderLayer::valueChanged(Scrollbar*) bool RenderLayer::isActive() const { - Page* page = renderer()->document()->frame()->page(); + Page* page = renderer()->frame()->page(); return page && page->focusController()->isActive(); } @@ -3896,7 +3896,7 @@ void showLayerTree(const WebCore::RenderLayer* layer) if (!layer) return; - if (WebCore::Frame* frame = layer->renderer()->document()->frame()) { + if (WebCore::Frame* frame = layer->renderer()->frame()) { WebCore::String output = externalRepresentation(frame, WebCore::RenderAsTextShowAllLayers | WebCore::RenderAsTextShowLayerNesting | WebCore::RenderAsTextShowCompositedLayers | WebCore::RenderAsTextShowAddresses); fprintf(stderr, "%s\n", output.utf8().data()); } diff --git a/WebCore/rendering/RenderLayerBacking.cpp b/WebCore/rendering/RenderLayerBacking.cpp index 97c5544..b55a474 100644 --- a/WebCore/rendering/RenderLayerBacking.cpp +++ b/WebCore/rendering/RenderLayerBacking.cpp @@ -1029,7 +1029,7 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* #if ENABLE(INSPECTOR) static InspectorTimelineAgent* inspectorTimelineAgent(RenderObject* renderer) { - Frame* frame = renderer->document()->frame(); + Frame* frame = renderer->frame(); if (!frame) return 0; Page* page = frame->page(); @@ -1252,10 +1252,9 @@ 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() + "\'"; + name += " " + static_cast<Element*>(node)->tagName(); + if (node->hasID()) + name += " \'" + static_cast<Element*>(node)->getIdAttribute() + "\'"; } if (m_owningLayer->isReflection()) diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp index ff6e3b2..f68623b 100644 --- a/WebCore/rendering/RenderLayerCompositor.cpp +++ b/WebCore/rendering/RenderLayerCompositor.cpp @@ -29,19 +29,16 @@ #include "RenderLayerCompositor.h" #include "AnimationController.h" +#include "CSSPropertyNames.h" #include "Chrome.h" #include "ChromeClient.h" -#include "CSSPropertyNames.h" #include "Frame.h" #include "FrameView.h" #include "GraphicsLayer.h" -#include "HitTestResult.h" #include "HTMLCanvasElement.h" #include "HTMLIFrameElement.h" -#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) -#include "HTMLMediaElement.h" #include "HTMLNames.h" -#endif +#include "HitTestResult.h" #include "NodeList.h" #include "Page.h" #include "RenderEmbeddedObject.h" @@ -52,6 +49,10 @@ #include "RenderView.h" #include "Settings.h" +#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) +#include "HTMLMediaElement.h" +#endif + #if PROFILE_LAYER_REBUILD #include <wtf/CurrentTime.h> #endif @@ -1439,7 +1440,8 @@ void RenderLayerCompositor::detachRootPlatformLayer() else m_rootPlatformLayer->removeFromParent(); - m_renderView->document()->ownerElement()->setNeedsStyleRecalc(SyntheticStyleChange); + if (Element* ownerElement = m_renderView->document()->ownerElement()) + ownerElement->setNeedsStyleRecalc(SyntheticStyleChange); break; } case RootLayerAttachedViaChromeClient: { diff --git a/WebCore/rendering/RenderLineBoxList.cpp b/WebCore/rendering/RenderLineBoxList.cpp index 92952b7..2d3ee7e 100644 --- a/WebCore/rendering/RenderLineBoxList.cpp +++ b/WebCore/rendering/RenderLineBoxList.cpp @@ -37,6 +37,7 @@ #include "RenderInline.h" #include "RenderView.h" #include "RootInlineBox.h" +#include "Settings.h" // FIXME: This include can be removed when paginateDuringLayoutEnabled is taken out. using namespace std; @@ -162,7 +163,7 @@ void RenderLineBoxList::paint(RenderBoxModelObject* renderer, RenderObject::Pain return; RenderView* v = renderer->view(); - bool usePrintRect = !v->printRect().isEmpty(); + bool usePrintRect = !v->printRect().isEmpty() && !renderer->document()->settings()->paginateDuringLayoutEnabled(); // We can check the first box and last box and avoid painting if we don't // intersect. This is a quick short-circuit that we can take to avoid walking any lines. diff --git a/WebCore/rendering/RenderListBox.cpp b/WebCore/rendering/RenderListBox.cpp index 1c21af4..2ecc2d0 100644 --- a/WebCore/rendering/RenderListBox.cpp +++ b/WebCore/rendering/RenderListBox.cpp @@ -314,7 +314,7 @@ void RenderListBox::paintItemForeground(PaintInfo& paintInfo, int tx, int ty, in Color textColor = element->renderStyle() ? element->renderStyle()->visitedDependentColor(CSSPropertyColor) : style()->visitedDependentColor(CSSPropertyColor); if (optionElement && optionElement->selected()) { - if (document()->frame()->selection()->isFocusedAndActive() && document()->focusedNode() == node()) + if (frame()->selection()->isFocusedAndActive() && document()->focusedNode() == node()) textColor = theme()->activeListBoxSelectionForegroundColor(); // Honor the foreground color for disabled items else if (!element->disabled()) @@ -350,7 +350,7 @@ void RenderListBox::paintItemBackground(PaintInfo& paintInfo, int tx, int ty, in Color backColor; if (optionElement && optionElement->selected()) { - if (document()->frame()->selection()->isFocusedAndActive() && document()->focusedNode() == node()) + if (frame()->selection()->isFocusedAndActive() && document()->focusedNode() == node()) backColor = theme()->activeListBoxSelectionBackgroundColor(); else backColor = theme()->inactiveListBoxSelectionBackgroundColor(); @@ -408,7 +408,7 @@ void RenderListBox::panScroll(const IntPoint& panStartMousePosition) // FIXME: This doesn't work correctly with transforms. FloatPoint absOffset = localToAbsolute(); - IntPoint currentMousePosition = document()->frame()->eventHandler()->currentMousePosition(); + IntPoint currentMousePosition = frame()->eventHandler()->currentMousePosition(); // We need to check if the current mouse position is out of the window. When the mouse is out of the window, the position is incoherent static IntPoint previousMousePosition; if (currentMousePosition.y() < 0) @@ -466,7 +466,7 @@ int RenderListBox::scrollToward(const IntPoint& destination) void RenderListBox::autoscroll() { - IntPoint pos = document()->frame()->view()->windowToContents(document()->frame()->eventHandler()->currentMousePosition()); + IntPoint pos = frame()->view()->windowToContents(frame()->eventHandler()->currentMousePosition()); int endIndex = scrollToward(pos); if (endIndex >= 0) { @@ -613,7 +613,7 @@ IntRect RenderListBox::controlClipRect(int tx, int ty) const bool RenderListBox::isActive() const { - Page* page = document()->frame()->page(); + Page* page = frame()->page(); return page && page->focusController()->isActive(); } diff --git a/WebCore/rendering/RenderMenuList.h b/WebCore/rendering/RenderMenuList.h index 5ee8588..9e51996 100644 --- a/WebCore/rendering/RenderMenuList.h +++ b/WebCore/rendering/RenderMenuList.h @@ -101,6 +101,8 @@ private: virtual bool valueShouldChangeOnHotTrack() const { return true; } virtual bool shouldPopOver() const { return !POPUP_MENU_PULLS_DOWN; } virtual void valueChanged(unsigned listIndex, bool fireOnChange = true); + virtual void selectionChanged(unsigned, bool) {} + virtual void selectionCleared() {} virtual FontSelector* fontSelector() const; virtual HostWindow* hostWindow() const; virtual PassRefPtr<Scrollbar> createScrollbar(ScrollbarClient*, ScrollbarOrientation, ScrollbarControlSize); diff --git a/WebCore/rendering/RenderMeter.cpp b/WebCore/rendering/RenderMeter.cpp index 9dc6a26..d443ceb 100644 --- a/WebCore/rendering/RenderMeter.cpp +++ b/WebCore/rendering/RenderMeter.cpp @@ -19,11 +19,13 @@ */ #include "config.h" + #if ENABLE(METER_TAG) #include "RenderMeter.h" #include "HTMLMeterElement.h" +#include "HTMLNames.h" #include "RenderTheme.h" using namespace std; @@ -37,6 +39,18 @@ RenderMeter::RenderMeter(HTMLMeterElement* element) { } +void RenderMeter::calcWidth() +{ + RenderBox::calcWidth(); + setWidth(theme()->meterSizeForBounds(this, frameRect()).width()); +} + +void RenderMeter::calcHeight() +{ + RenderBox::calcHeight(); + setHeight(theme()->meterSizeForBounds(this, frameRect()).height()); +} + void RenderMeter::layout() { ASSERT(needsLayout()); @@ -59,4 +73,5 @@ void RenderMeter::updateFromElement() } } // namespace WebCore + #endif diff --git a/WebCore/rendering/RenderMeter.h b/WebCore/rendering/RenderMeter.h index 2fc7844..fd95adb 100644 --- a/WebCore/rendering/RenderMeter.h +++ b/WebCore/rendering/RenderMeter.h @@ -38,6 +38,8 @@ private: virtual bool isMeter() const { return true; } virtual void layout(); virtual void updateFromElement(); + virtual void calcWidth(); + virtual void calcHeight(); }; inline RenderMeter* toRenderMeter(RenderObject* object) diff --git a/WebCore/rendering/RenderObject.cpp b/WebCore/rendering/RenderObject.cpp index 2893d67..e9e9ffc 100644 --- a/WebCore/rendering/RenderObject.cpp +++ b/WebCore/rendering/RenderObject.cpp @@ -42,6 +42,7 @@ #include "RenderFlexibleBox.h" #include "RenderImageGeneratedContent.h" #include "RenderInline.h" +#include "RenderLayer.h" #include "RenderListItem.h" #include "RenderRuby.h" #include "RenderRubyText.h" @@ -222,7 +223,7 @@ RenderObject::RenderObject(Node* node) RenderObject::~RenderObject() { - ASSERT(!node() || documentBeingDestroyed() || !document()->frame()->view() || document()->frame()->view()->layoutRoot() != this); + ASSERT(!node() || documentBeingDestroyed() || !frame()->view() || frame()->view()->layoutRoot() != this); #ifndef NDEBUG ASSERT(!m_hasAXObject); renderObjectCounter.decrement(); @@ -1389,7 +1390,7 @@ Color RenderObject::selectionBackgroundColor() const if (pseudoStyle && pseudoStyle->visitedDependentColor(CSSPropertyBackgroundColor).isValid()) color = pseudoStyle->visitedDependentColor(CSSPropertyBackgroundColor).blendWithWhite(); else - color = document()->frame()->selection()->isFocusedAndActive() ? + color = frame()->selection()->isFocusedAndActive() ? theme()->activeSelectionBackgroundColor() : theme()->inactiveSelectionBackgroundColor(); } @@ -1408,7 +1409,7 @@ Color RenderObject::selectionForegroundColor() const if (!color.isValid()) color = pseudoStyle->visitedDependentColor(CSSPropertyColor); } else - color = document()->frame()->selection()->isFocusedAndActive() ? + color = frame()->selection()->isFocusedAndActive() ? theme()->activeSelectionForegroundColor() : theme()->inactiveSelectionForegroundColor(); @@ -1948,9 +1949,9 @@ void RenderObject::destroy() // FIXME: RenderObject::destroy should not get called with a renderer whose document // has a null frame, so we assert this. However, we don't want release builds to crash which is why we // check that the frame is not null. - ASSERT(document()->frame()); - if (document()->frame() && document()->frame()->eventHandler()->autoscrollRenderer() == this) - document()->frame()->eventHandler()->stopAutoscrollTimer(true); + ASSERT(frame()); + if (frame() && frame()->eventHandler()->autoscrollRenderer() == this) + frame()->eventHandler()->stopAutoscrollTimer(true); if (m_hasCounterNodeMap) RenderCounter::destroyCounterNodes(this); @@ -2276,8 +2277,8 @@ void RenderObject::addDashboardRegions(Vector<DashboardRegionValue>& regions) region.bounds.setX(absPos.x() + styleRegion.offset.left().value()); region.bounds.setY(absPos.y() + styleRegion.offset.top().value()); - if (document()->frame()) { - float pageScaleFactor = document()->frame()->page()->chrome()->scaleFactor(); + if (frame()) { + float pageScaleFactor = frame()->page()->chrome()->scaleFactor(); if (pageScaleFactor != 1.0f) { region.bounds.scale(pageScaleFactor); region.clip.scale(pageScaleFactor); @@ -2382,7 +2383,7 @@ void RenderObject::adjustRectForOutlineAndShadow(IntRect& rect) const AnimationController* RenderObject::animation() const { - return document()->frame()->animation(); + return frame()->animation(); } void RenderObject::imageChanged(CachedImage* image, const IntRect* rect) diff --git a/WebCore/rendering/RenderObject.h b/WebCore/rendering/RenderObject.h index 3ff38ab..9f1e8dd 100644 --- a/WebCore/rendering/RenderObject.h +++ b/WebCore/rendering/RenderObject.h @@ -66,6 +66,7 @@ class RenderSVGResourceContainer; * three phases invoked on them during this phase. */ +// FIXME: These enums should move to their own header since they're used by other headers. enum PaintPhase { PaintPhaseBlockBackground, PaintPhaseChildBlockBackground, @@ -450,9 +451,11 @@ public: bool isRooted(RenderView** = 0); Node* node() const { return m_isAnonymous ? 0 : m_node; } - Document* document() const { return m_node->document(); } void setNode(Node* node) { m_node = node; } + Document* document() const { return m_node->document(); } + Frame* frame() const { return document()->frame(); } + bool hasOutlineAnnotation() const; bool hasOutline() const { return style()->hasOutline() || hasOutlineAnnotation(); } diff --git a/WebCore/rendering/RenderPath.cpp b/WebCore/rendering/RenderPath.cpp index ccb9562..238a4e6 100644 --- a/WebCore/rendering/RenderPath.cpp +++ b/WebCore/rendering/RenderPath.cpp @@ -5,6 +5,7 @@ 2009 Google, Inc. 2009 Dirk Schulze <krit@webkit.org> Copyright (C) Research In Motion Limited 2010. All rights reserved. + 2009 Jeff Schiller <codedread@gmail.com> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -30,6 +31,7 @@ #include "FloatPoint.h" #include "FloatQuad.h" #include "GraphicsContext.h" +#include "HitTestRequest.h" #include "PointerEventsHitRules.h" #include "RenderSVGContainer.h" #include "RenderSVGResourceFilter.h" @@ -71,7 +73,7 @@ RenderPath::RenderPath(SVGStyledTransformableElement* node) { } -bool RenderPath::fillContains(const FloatPoint& point, bool requiresFill) const +bool RenderPath::fillContains(const FloatPoint& point, bool requiresFill, WindRule fillRule) const { if (!m_fillBoundingBox.contains(point)) return false; @@ -79,7 +81,7 @@ bool RenderPath::fillContains(const FloatPoint& point, bool requiresFill) const if (requiresFill && !RenderSVGResource::fillPaintingResource(this, style())) return false; - return m_path.contains(point, style()->svgStyle()->fillRule()); + return m_path.contains(point, fillRule); } bool RenderPath::strokeContains(const FloatPoint& point, bool requiresStroke) const @@ -130,16 +132,28 @@ void RenderPath::layout() static inline void fillAndStrokePath(const Path& path, GraphicsContext* context, RenderPath* object) { context->beginPath(); + RenderStyle* style = object->style(); - if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(object, object->style())) { + if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(object, style)) { context->addPath(path); - if (fillPaintingResource->applyResource(object, object->style(), context, ApplyToFillMode)) + if (fillPaintingResource->applyResource(object, style, context, ApplyToFillMode)) fillPaintingResource->postApplyResource(object, context, ApplyToFillMode); } - if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(object, object->style())) { - context->addPath(path); - if (strokePaintingResource->applyResource(object, object->style(), context, ApplyToStrokeMode)) + if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(object, style)) { + if (style->svgStyle()->vectorEffect() == VE_NON_SCALING_STROKE) { + SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(object->node()); + AffineTransform transform = element->getScreenCTM(); + if (!transform.isInvertible()) + return; + + Path transformedPath = path; + context->concatCTM(transform.inverse()); + transformedPath.transform(transform); + context->addPath(transformedPath); + } else + context->addPath(path); + if (strokePaintingResource->applyResource(object, style, context, ApplyToStrokeMode)) strokePaintingResource->postApplyResource(object, context, ApplyToStrokeMode); } } @@ -195,7 +209,7 @@ void RenderPath::addFocusRingRects(Vector<IntRect>& rects, int, int) rects.append(rect); } -bool RenderPath::nodeAtFloatPoint(const HitTestRequest&, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) +bool RenderPath::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) { // We only draw in the forground phase, so we only hit-test then. if (hitTestAction != HitTestForeground) @@ -203,17 +217,22 @@ bool RenderPath::nodeAtFloatPoint(const HitTestRequest&, HitTestResult& result, FloatPoint localPoint = m_localTransform.inverse().mapPoint(pointInParent); - PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_PATH_HITTESTING, style()->pointerEvents()); + if (!pointInClippingArea(this, localPoint)) + return false; + PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_PATH_HITTESTING, request, style()->pointerEvents()); bool isVisible = (style()->visibility() == VISIBLE); if (isVisible || !hitRules.requireVisible) { - if ((hitRules.canHitStroke && (style()->svgStyle()->hasStroke() || !hitRules.requireStroke) && strokeContains(localPoint, hitRules.requireStroke)) - || (hitRules.canHitFill && (style()->svgStyle()->hasFill() || !hitRules.requireFill) && fillContains(localPoint, hitRules.requireFill))) { + const SVGRenderStyle* svgStyle = style()->svgStyle(); + WindRule fillRule = svgStyle->fillRule(); + if (request.svgClipContent()) + fillRule = svgStyle->clipRule(); + if ((hitRules.canHitStroke && (svgStyle->hasStroke() || !hitRules.requireStroke) && strokeContains(localPoint, hitRules.requireStroke)) + || (hitRules.canHitFill && (svgStyle->hasFill() || !hitRules.requireFill) && fillContains(localPoint, hitRules.requireFill, fillRule))) { updateHitTestResult(result, roundedIntPoint(localPoint)); return true; } } - return false; } @@ -297,23 +316,8 @@ void RenderPath::updateCachedBoundaries() } // Cache smallest possible repaint rectangle - - // FIXME: We need to be careful here. We assume that there is no resource, if the rect is empty. - FloatRect rect = filterBoundingBoxForRenderer(this); - if (rect.isEmpty()) - m_repaintBoundingBox = m_strokeAndMarkerBoundingBox; - else - m_repaintBoundingBox = rect; - - rect = clipperBoundingBoxForRenderer(this); - if (!rect.isEmpty()) - m_repaintBoundingBox.intersect(rect); - - rect = maskerBoundingBoxForRenderer(this); - if (!rect.isEmpty()) - m_repaintBoundingBox.intersect(rect); - - svgStyle->inflateForShadow(m_repaintBoundingBox); + m_repaintBoundingBox = m_strokeAndMarkerBoundingBox; + intersectRepaintRectWithResources(this, m_repaintBoundingBox); } } diff --git a/WebCore/rendering/RenderPath.h b/WebCore/rendering/RenderPath.h index 5509057..3748f39 100644 --- a/WebCore/rendering/RenderPath.h +++ b/WebCore/rendering/RenderPath.h @@ -47,7 +47,7 @@ public: private: // Hit-detection seperated for the fill and the stroke - bool fillContains(const FloatPoint&, bool requiresFill = true) const; + bool fillContains(const FloatPoint&, bool requiresFill = true, WindRule fillRule = RULE_NONZERO) const; bool strokeContains(const FloatPoint&, bool requiresStroke = true) const; virtual FloatRect objectBoundingBox() const { return m_fillBoundingBox; } diff --git a/WebCore/rendering/RenderProgress.cpp b/WebCore/rendering/RenderProgress.cpp index ac3fb15..e4e045d 100644 --- a/WebCore/rendering/RenderProgress.cpp +++ b/WebCore/rendering/RenderProgress.cpp @@ -23,8 +23,8 @@ #if ENABLE(PROGRESS_TAG) #include "RenderProgress.h" - -#include "HTMLDivElement.h" +#include "ShadowElement.h" +#include "HTMLNames.h" #include "HTMLProgressElement.h" #include "RenderTheme.h" #include "RenderView.h" @@ -35,32 +35,6 @@ using namespace std; namespace WebCore { -using namespace HTMLNames; - -class ProgressValueElement : public HTMLDivElement { -public: - static PassRefPtr<ProgressValueElement> create(Node* shadowParent); - -private: - ProgressValueElement(Node* shadowParent); - - virtual bool isShadowNode() const { return true; } - virtual Node* shadowParentNode() { return m_shadowParent; } - - Node* m_shadowParent; -}; - -inline ProgressValueElement::ProgressValueElement(Node* shadowParent) - : HTMLDivElement(divTag, shadowParent->document()) - , m_shadowParent(shadowParent) -{ -} - -inline PassRefPtr<ProgressValueElement> ProgressValueElement::create(Node* shadowParent) -{ - return new ProgressValueElement(shadowParent); -} - RenderProgress::RenderProgress(HTMLProgressElement* element) : RenderBlock(element) , m_position(-1) @@ -144,7 +118,7 @@ void RenderProgress::updateValuePartState() { bool needLayout = !style()->hasAppearance() || m_valuePart; if (!style()->hasAppearance() && !m_valuePart) { - m_valuePart = ProgressValueElement::create(node()); + m_valuePart = ShadowBlockElement::create(node()); RefPtr<RenderStyle> styleForValuePart = createStyleForValuePart(style()); m_valuePart->setRenderer(m_valuePart->createRenderer(renderArena(), styleForValuePart.get())); m_valuePart->renderer()->setStyle(styleForValuePart.release()); diff --git a/WebCore/rendering/RenderProgress.h b/WebCore/rendering/RenderProgress.h index 1137e99..4d1a88f 100644 --- a/WebCore/rendering/RenderProgress.h +++ b/WebCore/rendering/RenderProgress.h @@ -27,7 +27,7 @@ namespace WebCore { class HTMLProgressElement; -class ProgressValueElement; +class ShadowBlockElement; class RenderProgress : public RenderBlock { public: @@ -63,7 +63,7 @@ private: double m_animationDuration; bool m_animating; Timer<RenderProgress> m_animationTimer; - RefPtr<ProgressValueElement> m_valuePart; + RefPtr<ShadowBlockElement> m_valuePart; }; inline RenderProgress* toRenderProgress(RenderObject* object) diff --git a/WebCore/rendering/RenderSVGContainer.cpp b/WebCore/rendering/RenderSVGContainer.cpp index 56846a9..66889ac 100644 --- a/WebCore/rendering/RenderSVGContainer.cpp +++ b/WebCore/rendering/RenderSVGContainer.cpp @@ -146,20 +146,7 @@ FloatRect RenderSVGContainer::strokeBoundingBox() const FloatRect RenderSVGContainer::repaintRectInLocalCoordinates() const { FloatRect repaintRect = computeContainerBoundingBox(this, true); - - FloatRect rect = filterBoundingBoxForRenderer(this); - if (!rect.isEmpty()) - repaintRect = rect; - - rect = clipperBoundingBoxForRenderer(this); - if (!rect.isEmpty()) - repaintRect.intersect(rect); - - rect = maskerBoundingBoxForRenderer(this); - if (!rect.isEmpty()) - repaintRect.intersect(rect); - - style()->svgStyle()->inflateForShadow(repaintRect); + intersectRepaintRectWithResources(this, repaintRect); return repaintRect; } @@ -172,6 +159,9 @@ bool RenderSVGContainer::nodeAtFloatPoint(const HitTestRequest& request, HitTest FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent); + if (!pointInClippingArea(this, localPoint)) + return false; + for (RenderObject* child = lastChild(); child; child = child->previousSibling()) { if (child->nodeAtFloatPoint(request, result, localPoint, hitTestAction)) { updateHitTestResult(result, roundedIntPoint(localPoint)); diff --git a/WebCore/rendering/RenderSVGImage.cpp b/WebCore/rendering/RenderSVGImage.cpp index 006142c..d1a3037 100644 --- a/WebCore/rendering/RenderSVGImage.cpp +++ b/WebCore/rendering/RenderSVGImage.cpp @@ -112,17 +112,19 @@ void RenderSVGImage::destroy() RenderImage::destroy(); } -bool RenderSVGImage::nodeAtFloatPoint(const HitTestRequest&, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) +bool RenderSVGImage::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) { // We only draw in the forground phase, so we only hit-test then. if (hitTestAction != HitTestForeground) return false; - PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_IMAGE_HITTESTING, style()->pointerEvents()); - + PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_IMAGE_HITTESTING, request, style()->pointerEvents()); bool isVisible = (style()->visibility() == VISIBLE); if (isVisible || !hitRules.requireVisible) { FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent); + + if (!pointInClippingArea(this, localPoint)) + return false; if (hitRules.canHitFill) { if (m_localBounds.contains(localPoint)) { @@ -153,22 +155,7 @@ FloatRect RenderSVGImage::repaintRectInLocalCoordinates() const return m_cachedLocalRepaintRect; m_cachedLocalRepaintRect = m_localBounds; - - // FIXME: We need to be careful here. We assume that there is no filter, - // clipper or masker if the rects are empty. - FloatRect rect = filterBoundingBoxForRenderer(this); - if (!rect.isEmpty()) - m_cachedLocalRepaintRect = rect; - - rect = clipperBoundingBoxForRenderer(this); - if (!rect.isEmpty()) - m_cachedLocalRepaintRect.intersect(rect); - - rect = maskerBoundingBoxForRenderer(this); - if (!rect.isEmpty()) - m_cachedLocalRepaintRect.intersect(rect); - - style()->svgStyle()->inflateForShadow(m_cachedLocalRepaintRect); + intersectRepaintRectWithResources(this, m_cachedLocalRepaintRect); return m_cachedLocalRepaintRect; } diff --git a/WebCore/rendering/RenderSVGResource.h b/WebCore/rendering/RenderSVGResource.h index 5334025..a14a972 100644 --- a/WebCore/rendering/RenderSVGResource.h +++ b/WebCore/rendering/RenderSVGResource.h @@ -61,7 +61,7 @@ public: virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode) = 0; virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short) { } - virtual FloatRect resourceBoundingBox(const FloatRect&) = 0; + virtual FloatRect resourceBoundingBox(RenderObject*) = 0; virtual RenderSVGResourceType resourceType() const = 0; diff --git a/WebCore/rendering/RenderSVGResourceClipper.cpp b/WebCore/rendering/RenderSVGResourceClipper.cpp index 7957df4..450c5d6 100644 --- a/WebCore/rendering/RenderSVGResourceClipper.cpp +++ b/WebCore/rendering/RenderSVGResourceClipper.cpp @@ -27,6 +27,8 @@ #include "AffineTransform.h" #include "FloatRect.h" #include "GraphicsContext.h" +#include "HitTestRequest.h" +#include "HitTestResult.h" #include "ImageBuffer.h" #include "IntRect.h" #include "RenderObject.h" @@ -266,12 +268,49 @@ void RenderSVGResourceClipper::calculateClipContentRepaintRect() } } -FloatRect RenderSVGResourceClipper::resourceBoundingBox(const FloatRect& objectBoundingBox) +bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundingBox, const FloatPoint& nodeAtPoint) { + FloatPoint point = nodeAtPoint; + if (!pointInClippingArea(this, point)) + return false; + + if (static_cast<SVGClipPathElement*>(node())->clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { + AffineTransform transform; + transform.translate(objectBoundingBox.x(), objectBoundingBox.y()); + transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); + point = transform.inverse().mapPoint(point); + } + + for (Node* childNode = node()->firstChild(); childNode; childNode = childNode->nextSibling()) { + RenderObject* renderer = childNode->renderer(); + if (!childNode->isSVGElement() || !static_cast<SVGElement*>(childNode)->isStyled() || !renderer) + continue; + if (!renderer->isRenderPath() && !renderer->isSVGText() && !renderer->isSVGShadowTreeRootContainer()) + continue; + IntPoint hitPoint; + HitTestResult result(hitPoint); + if (renderer->nodeAtFloatPoint(HitTestRequest(HitTestRequest::SVGClipContent), result, point, HitTestForeground)) + return true; + } + + return false; +} + +FloatRect RenderSVGResourceClipper::resourceBoundingBox(RenderObject* object) +{ + // Save the reference to the calling object for relayouting it on changing resource properties. + if (!m_clipper.contains(object)) + m_clipper.set(object, new ClipperData); + + // Resource was not layouted yet. Give back the boundingBox of the object. + if (selfNeedsLayout()) + return object->objectBoundingBox(); + if (m_clipBoundaries.isEmpty()) calculateClipContentRepaintRect(); if (static_cast<SVGClipPathElement*>(node())->clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { + FloatRect objectBoundingBox = object->objectBoundingBox(); AffineTransform transform; transform.translate(objectBoundingBox.x(), objectBoundingBox.y()); transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); diff --git a/WebCore/rendering/RenderSVGResourceClipper.h b/WebCore/rendering/RenderSVGResourceClipper.h index d8e2eed..78ec75b 100644 --- a/WebCore/rendering/RenderSVGResourceClipper.h +++ b/WebCore/rendering/RenderSVGResourceClipper.h @@ -51,9 +51,11 @@ public: virtual void invalidateClient(RenderObject*); virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); - virtual FloatRect resourceBoundingBox(const FloatRect&); + virtual FloatRect resourceBoundingBox(RenderObject*); virtual RenderSVGResourceType resourceType() const { return ClipperResourceType; } + + bool hitTestClipContent(const FloatRect&, const FloatPoint&); SVGUnitTypes::SVGUnitType clipPathUnits() const { return toUnitType(static_cast<SVGClipPathElement*>(node())->clipPathUnits()); } diff --git a/WebCore/rendering/RenderSVGResourceContainer.h b/WebCore/rendering/RenderSVGResourceContainer.h index b63575d..54617bb 100644 --- a/WebCore/rendering/RenderSVGResourceContainer.h +++ b/WebCore/rendering/RenderSVGResourceContainer.h @@ -23,6 +23,8 @@ #if ENABLE(SVG) #include "RenderSVGHiddenContainer.h" + +#include "SVGStyledTransformableElement.h" #include "RenderSVGResource.h" namespace WebCore { @@ -33,7 +35,8 @@ public: RenderSVGResourceContainer(SVGStyledElement* node) : RenderSVGHiddenContainer(node) , RenderSVGResource() - , m_id(node->getIDAttribute()) + // FIXME: Should probably be using getIdAttribute rather than idForStyleResolution. + , m_id(node->hasID() ? node->idForStyleResolution() : nullAtom) { ASSERT(node->document()); node->document()->accessSVGExtensions()->addResource(m_id, this); @@ -55,7 +58,8 @@ public: // Remove old id, that is guaranteed to be present in cache extensions->removeResource(m_id); - m_id = static_cast<Element*>(node())->getIDAttribute(); + // FIXME: Should probably be using getIdAttribute rather than idForStyleResolution. + m_id = node()->hasID() ? static_cast<Element*>(node())->idForStyleResolution() : nullAtom; // It's possible that an element is referencing us with the new id, and has to be notified that we're existing now if (extensions->isPendingResource(m_id)) { @@ -80,6 +84,17 @@ public: virtual bool drawsContents() { return false; } virtual RenderSVGResourceContainer* toRenderSVGResourceContainer() { return this; } + + static AffineTransform transformOnNonScalingStroke(RenderObject* object, const AffineTransform resourceTransform) + { + if (!object->isRenderPath()) + return resourceTransform; + + SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(object->node()); + AffineTransform transform = resourceTransform; + transform.multiply(element->getScreenCTM()); + return transform; + } private: AtomicString m_id; diff --git a/WebCore/rendering/RenderSVGResourceFilter.cpp b/WebCore/rendering/RenderSVGResourceFilter.cpp index e197d5b..b0220a9 100644 --- a/WebCore/rendering/RenderSVGResourceFilter.cpp +++ b/WebCore/rendering/RenderSVGResourceFilter.cpp @@ -279,10 +279,10 @@ void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo filterData->sourceGraphicBuffer.clear(); } -FloatRect RenderSVGResourceFilter::resourceBoundingBox(const FloatRect& objectBoundingBox) +FloatRect RenderSVGResourceFilter::resourceBoundingBox(RenderObject* object) { if (SVGFilterElement* element = static_cast<SVGFilterElement*>(node())) - return element->filterBoundingBox(objectBoundingBox); + return element->filterBoundingBox(object->objectBoundingBox()); return FloatRect(); } diff --git a/WebCore/rendering/RenderSVGResourceFilter.h b/WebCore/rendering/RenderSVGResourceFilter.h index 4d875c0..105b256 100644 --- a/WebCore/rendering/RenderSVGResourceFilter.h +++ b/WebCore/rendering/RenderSVGResourceFilter.h @@ -70,7 +70,7 @@ public: virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode); - virtual FloatRect resourceBoundingBox(const FloatRect&); + virtual FloatRect resourceBoundingBox(RenderObject*); PassOwnPtr<SVGFilterBuilder> buildPrimitives(); diff --git a/WebCore/rendering/RenderSVGResourceGradient.cpp b/WebCore/rendering/RenderSVGResourceGradient.cpp index 6c9d784..e715f6f 100644 --- a/WebCore/rendering/RenderSVGResourceGradient.cpp +++ b/WebCore/rendering/RenderSVGResourceGradient.cpp @@ -159,17 +159,35 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle* GradientData* gradientData = m_gradient.get(object); + bool isPaintingText = resourceMode & ApplyToTextMode; + // Create gradient object - if (!gradientData->gradient) + if (!gradientData->gradient) { buildGradient(gradientData, gradientElement); + // CG platforms will handle the gradient space transform for text after applying the + // resource, so don't apply it here. For non-CG platforms, we want the text bounding + // box applied to the gradient space transform now, so the gradient shader can use it. +#if PLATFORM(CG) + if (gradientData->boundingBoxMode && !isPaintingText) { +#else + if (gradientData->boundingBoxMode) { +#endif + FloatRect objectBoundingBox = object->objectBoundingBox(); + gradientData->userspaceTransform.translate(objectBoundingBox.x(), objectBoundingBox.y()); + gradientData->userspaceTransform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); + } + + gradientData->userspaceTransform.multiply(gradientData->transform); + gradientData->gradient->setGradientSpaceTransform(gradientData->userspaceTransform); + } + if (!gradientData->gradient) return false; // Draw gradient context->save(); - bool isPaintingText = resourceMode & ApplyToTextMode; if (isPaintingText) { #if PLATFORM(CG) if (!createMaskAndSwapContextForTextGradient(context, m_savedContext, m_imageBuffer, object)) { @@ -181,24 +199,6 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle* context->setTextDrawingMode(resourceMode & ApplyToFillMode ? cTextFill : cTextStroke); } - AffineTransform transform; - - // CG platforms will handle the gradient space transform for text after applying the - // resource, so don't apply it here. For non-CG platforms, we want the text bounding - // box applied to the gradient space transform now, so the gradient shader can use it. -#if PLATFORM(CG) - if (gradientData->boundingBoxMode && !isPaintingText) { -#else - if (gradientData->boundingBoxMode) { -#endif - FloatRect objectBoundingBox = object->objectBoundingBox(); - transform.translate(objectBoundingBox.x(), objectBoundingBox.y()); - transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); - } - - transform.multiply(gradientData->transform); - gradientData->gradient->setGradientSpaceTransform(transform); - const SVGRenderStyle* svgStyle = style->svgStyle(); ASSERT(svgStyle); @@ -207,6 +207,8 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle* context->setFillGradient(gradientData->gradient); context->setFillRule(svgStyle->fillRule()); } else if (resourceMode & ApplyToStrokeMode) { + if (svgStyle->vectorEffect() == VE_NON_SCALING_STROKE) + gradientData->gradient->setGradientSpaceTransform(transformOnNonScalingStroke(object, gradientData->userspaceTransform)); context->setAlpha(svgStyle->strokeOpacity()); context->setStrokeGradient(gradientData->gradient); applyStrokeStyleToContext(context, style, object); diff --git a/WebCore/rendering/RenderSVGResourceGradient.h b/WebCore/rendering/RenderSVGResourceGradient.h index 4d848af..b01af6d 100644 --- a/WebCore/rendering/RenderSVGResourceGradient.h +++ b/WebCore/rendering/RenderSVGResourceGradient.h @@ -39,6 +39,7 @@ struct GradientData { RefPtr<Gradient> gradient; bool boundingBoxMode; + AffineTransform userspaceTransform; AffineTransform transform; }; @@ -54,7 +55,7 @@ public: virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode); - virtual FloatRect resourceBoundingBox(const FloatRect&) { return FloatRect(); } + virtual FloatRect resourceBoundingBox(RenderObject*) { return FloatRect(); } protected: void addStops(GradientData*, const Vector<Gradient::ColorStop>&) const; diff --git a/WebCore/rendering/RenderSVGResourceMarker.h b/WebCore/rendering/RenderSVGResourceMarker.h index fe848a9..533a03b 100644 --- a/WebCore/rendering/RenderSVGResourceMarker.h +++ b/WebCore/rendering/RenderSVGResourceMarker.h @@ -58,7 +58,7 @@ public: AffineTransform markerTransformation(const FloatPoint& origin, float angle, float strokeWidth) const; virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short) { return false; } - virtual FloatRect resourceBoundingBox(const FloatRect&) { return FloatRect(); } + virtual FloatRect resourceBoundingBox(RenderObject*) { return FloatRect(); } FloatPoint referencePoint() const; float angle() const; diff --git a/WebCore/rendering/RenderSVGResourceMasker.cpp b/WebCore/rendering/RenderSVGResourceMasker.cpp index 2bfb283..ea79439 100644 --- a/WebCore/rendering/RenderSVGResourceMasker.cpp +++ b/WebCore/rendering/RenderSVGResourceMasker.cpp @@ -210,12 +210,22 @@ void RenderSVGResourceMasker::calculateMaskContentRepaintRect() } } -FloatRect RenderSVGResourceMasker::resourceBoundingBox(const FloatRect& objectBoundingBox) +FloatRect RenderSVGResourceMasker::resourceBoundingBox(RenderObject* object) { + // Save the reference to the calling object for relayouting it on changing resource properties. + if (!m_masker.contains(object)) + m_masker.set(object, new MaskerData); + + // Resource was not layouted yet. Give back clipping rect of the mask. + SVGMaskElement* maskElement = static_cast<SVGMaskElement*>(node()); + FloatRect objectBoundingBox = object->objectBoundingBox(); + FloatRect maskBoundaries = maskElement->maskBoundingBox(objectBoundingBox); + if (selfNeedsLayout()) + return maskBoundaries; + if (m_maskBoundaries.isEmpty()) calculateMaskContentRepaintRect(); - SVGMaskElement* maskElement = static_cast<SVGMaskElement*>(node()); if (!maskElement) return FloatRect(); @@ -227,7 +237,7 @@ FloatRect RenderSVGResourceMasker::resourceBoundingBox(const FloatRect& objectBo maskRect = transform.mapRect(maskRect); } - maskRect.intersect(maskElement->maskBoundingBox(objectBoundingBox)); + maskRect.intersect(maskBoundaries); return maskRect; } diff --git a/WebCore/rendering/RenderSVGResourceMasker.h b/WebCore/rendering/RenderSVGResourceMasker.h index 2de5f3f..f6301cb 100644 --- a/WebCore/rendering/RenderSVGResourceMasker.h +++ b/WebCore/rendering/RenderSVGResourceMasker.h @@ -57,7 +57,7 @@ public: virtual void invalidateClient(RenderObject*); virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); - virtual FloatRect resourceBoundingBox(const FloatRect&); + virtual FloatRect resourceBoundingBox(RenderObject*); SVGUnitTypes::SVGUnitType maskUnits() const { return toUnitType(static_cast<SVGMaskElement*>(node())->maskUnits()); } SVGUnitTypes::SVGUnitType maskContentUnits() const { return toUnitType(static_cast<SVGMaskElement*>(node())->maskContentUnits()); } diff --git a/WebCore/rendering/RenderSVGResourcePattern.cpp b/WebCore/rendering/RenderSVGResourcePattern.cpp index 8302030..040b2e2 100644 --- a/WebCore/rendering/RenderSVGResourcePattern.cpp +++ b/WebCore/rendering/RenderSVGResourcePattern.cpp @@ -90,25 +90,19 @@ bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle* PatternData* patternData = m_pattern.get(object); if (!patternData->pattern) { - FloatRect patternBoundaries; - AffineTransform patternTransform; // Create tile image - OwnPtr<ImageBuffer> tileImage = createTileImage(patternBoundaries, patternTransform, patternElement, object); + OwnPtr<ImageBuffer> tileImage = createTileImage(patternData, patternElement, object); if (!tileImage) return false; // Create pattern object - buildPattern(patternData, patternBoundaries, tileImage.release()); + buildPattern(patternData, tileImage.release()); if (!patternData->pattern) return false; - // Compute pattern transformation - AffineTransform transform; - transform.translate(patternBoundaries.x(), patternBoundaries.y()); - transform.multiply(patternTransform); - patternData->pattern->setPatternSpaceTransform(transform); + patternData->pattern->setPatternSpaceTransform(patternData->transform); } // Draw pattern @@ -122,6 +116,8 @@ bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle* context->setFillPattern(patternData->pattern); context->setFillRule(svgStyle->fillRule()); } else if (resourceMode & ApplyToStrokeMode) { + if (svgStyle->vectorEffect() == VE_NON_SCALING_STROKE) + patternData->pattern->setPatternSpaceTransform(transformOnNonScalingStroke(object, patternData->transform)); context->setAlpha(svgStyle->strokeOpacity()); context->setStrokePattern(patternData->pattern); applyStrokeStyleToContext(context, style, object); @@ -212,8 +208,7 @@ FloatRect RenderSVGResourcePattern::calculatePatternBoundariesIncludingOverflow( return patternBoundariesIncludingOverflow; } -PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(FloatRect& patternBoundaries, - AffineTransform& patternTransform, +PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(PatternData* patternData, const SVGPatternElement* patternElement, RenderObject* object) const { @@ -224,8 +219,8 @@ PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(FloatRect& pat return 0; FloatRect objectBoundingBox = object->objectBoundingBox(); - patternBoundaries = calculatePatternBoundaries(attributes, objectBoundingBox, patternElement); - patternTransform = attributes.patternTransform(); + FloatRect patternBoundaries = calculatePatternBoundaries(attributes, objectBoundingBox, patternElement); + AffineTransform patternTransform = attributes.patternTransform(); AffineTransform viewBoxCTM = patternElement->viewBoxToViewTransform(patternElement->viewBox(), patternElement->preserveAspectRatio(), @@ -276,11 +271,17 @@ PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(FloatRect& pat renderSubtreeToImage(tileImage.get(), node->renderer()); } + patternData->boundaries = patternBoundaries; + + // Compute pattern transformation + patternData->transform.translate(patternBoundaries.x(), patternBoundaries.y()); + patternData->transform.multiply(patternTransform); + context->restore(); return tileImage.release(); } -void RenderSVGResourcePattern::buildPattern(PatternData* patternData, const FloatRect& patternBoundaries, PassOwnPtr<ImageBuffer> tileImage) const +void RenderSVGResourcePattern::buildPattern(PatternData* patternData, PassOwnPtr<ImageBuffer> tileImage) const { if (!tileImage->image()) { patternData->pattern = 0; @@ -288,14 +289,14 @@ void RenderSVGResourcePattern::buildPattern(PatternData* patternData, const Floa } IntRect tileRect = tileImage->image()->rect(); - if (tileRect.width() <= patternBoundaries.width() && tileRect.height() <= patternBoundaries.height()) { + if (tileRect.width() <= patternData->boundaries.width() && tileRect.height() <= patternData->boundaries.height()) { patternData->pattern = Pattern::create(tileImage->image(), true, true); return; } // Draw the first cell of the pattern manually to support overflow="visible" on all platforms. - int tileWidth = static_cast<int>(patternBoundaries.width() + 0.5f); - int tileHeight = static_cast<int>(patternBoundaries.height() + 0.5f); + int tileWidth = static_cast<int>(patternData->boundaries.width() + 0.5f); + int tileHeight = static_cast<int>(patternData->boundaries.height() + 0.5f); // Don't create ImageBuffers with image size of 0 if (!tileWidth || !tileHeight) { @@ -310,14 +311,14 @@ void RenderSVGResourcePattern::buildPattern(PatternData* patternData, const Floa int numX = static_cast<int>(ceilf(tileRect.width() / tileWidth)) + 1; newTileImageContext->save(); - newTileImageContext->translate(-patternBoundaries.width() * numX, -patternBoundaries.height() * numY); + newTileImageContext->translate(-patternData->boundaries.width() * numX, -patternData->boundaries.height() * numY); for (int i = numY; i > 0; --i) { - newTileImageContext->translate(0, patternBoundaries.height()); + newTileImageContext->translate(0, patternData->boundaries.height()); for (int j = numX; j > 0; --j) { - newTileImageContext->translate(patternBoundaries.width(), 0); + newTileImageContext->translate(patternData->boundaries.width(), 0); newTileImageContext->drawImage(tileImage->image(), style()->colorSpace(), tileRect, tileRect); } - newTileImageContext->translate(-patternBoundaries.width() * numX, 0); + newTileImageContext->translate(-patternData->boundaries.width() * numX, 0); } newTileImageContext->restore(); diff --git a/WebCore/rendering/RenderSVGResourcePattern.h b/WebCore/rendering/RenderSVGResourcePattern.h index 4129934..690b0de 100644 --- a/WebCore/rendering/RenderSVGResourcePattern.h +++ b/WebCore/rendering/RenderSVGResourcePattern.h @@ -38,6 +38,8 @@ namespace WebCore { struct PatternData { RefPtr<Pattern> pattern; + FloatRect boundaries; + AffineTransform transform; }; struct PatternAttributes; @@ -54,14 +56,14 @@ public: virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode); - virtual FloatRect resourceBoundingBox(const FloatRect&) { return FloatRect(); } + virtual FloatRect resourceBoundingBox(RenderObject*) { return FloatRect(); } virtual RenderSVGResourceType resourceType() const { return s_resourceType; } static RenderSVGResourceType s_resourceType; private: - PassOwnPtr<ImageBuffer> createTileImage(FloatRect& patternBoundaries, AffineTransform& patternTransform, const SVGPatternElement*, RenderObject*) const; - void buildPattern(PatternData*, const FloatRect& patternBoundaries, PassOwnPtr<ImageBuffer> tileImage) const; + PassOwnPtr<ImageBuffer> createTileImage(PatternData*, const SVGPatternElement*, RenderObject*) const; + void buildPattern(PatternData*, PassOwnPtr<ImageBuffer> tileImage) const; FloatRect calculatePatternBoundariesIncludingOverflow(PatternAttributes&, const FloatRect& objectBoundingBox, const AffineTransform& viewBoxCTM, const FloatRect& patternBoundaries) const; diff --git a/WebCore/rendering/RenderSVGResourceSolidColor.h b/WebCore/rendering/RenderSVGResourceSolidColor.h index a4de62d..ad7fd27 100644 --- a/WebCore/rendering/RenderSVGResourceSolidColor.h +++ b/WebCore/rendering/RenderSVGResourceSolidColor.h @@ -38,7 +38,7 @@ public: virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode); - virtual FloatRect resourceBoundingBox(const FloatRect&) { return FloatRect(); } + virtual FloatRect resourceBoundingBox(RenderObject*) { return FloatRect(); } virtual RenderSVGResourceType resourceType() const { return s_resourceType; } static RenderSVGResourceType s_resourceType; diff --git a/WebCore/rendering/RenderSVGText.cpp b/WebCore/rendering/RenderSVGText.cpp index 966196b..072b6d1 100644 --- a/WebCore/rendering/RenderSVGText.cpp +++ b/WebCore/rendering/RenderSVGText.cpp @@ -33,6 +33,7 @@ #include "FloatConversion.h" #include "FloatQuad.h" #include "GraphicsContext.h" +#include "HitTestRequest.h" #include "PointerEventsHitRules.h" #include "RenderLayer.h" #include "RenderSVGRoot.h" @@ -98,12 +99,16 @@ RootInlineBox* RenderSVGText::createRootInlineBox() bool RenderSVGText::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) { - PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, style()->pointerEvents()); + PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, request, style()->pointerEvents()); bool isVisible = (style()->visibility() == VISIBLE); if (isVisible || !hitRules.requireVisible) { if ((hitRules.canHitStroke && (style()->svgStyle()->hasStroke() || !hitRules.requireStroke)) || (hitRules.canHitFill && (style()->svgStyle()->hasFill() || !hitRules.requireFill))) { FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent); + + if (!pointInClippingArea(this, localPoint)) + return false; + return RenderBlock::nodeAtPoint(request, result, (int)localPoint.x(), (int)localPoint.y(), 0, 0, hitTestAction); } } @@ -186,7 +191,7 @@ FloatRect RenderSVGText::objectBoundingBox() const FloatRect RenderSVGText::strokeBoundingBox() const { - FloatRect repaintRect = objectBoundingBox(); + FloatRect strokeRect = objectBoundingBox(); // SVG needs to include the strokeWidth(), not the textStrokeWidth(). if (style()->svgStyle()->hasStroke()) { @@ -202,33 +207,31 @@ FloatRect RenderSVGText::strokeBoundingBox() const } #endif - repaintRect.inflate(strokeWidth); + strokeRect.inflate(strokeWidth); } - return repaintRect; + return strokeRect; } FloatRect RenderSVGText::repaintRectInLocalCoordinates() const { FloatRect repaintRect = strokeBoundingBox(); + intersectRepaintRectWithResources(this, repaintRect); - // FIXME: We need to be careful here. We assume that there is no filter, - // clipper or masker if the rects are empty. - FloatRect rect = filterBoundingBoxForRenderer(this); - if (!rect.isEmpty()) - repaintRect = rect; - - rect = clipperBoundingBoxForRenderer(this); - if (!rect.isEmpty()) - repaintRect.intersect(rect); - - rect = maskerBoundingBoxForRenderer(this); - if (!rect.isEmpty()) - repaintRect.intersect(rect); + return repaintRect; +} - style()->svgStyle()->inflateForShadow(repaintRect); +// Fix for <rdar://problem/8048875>. We should not render :first-line CSS Style +// in a SVG text element context. +RenderBlock* RenderSVGText::firstLineBlock() const +{ + return 0; +} - return repaintRect; +// Fix for <rdar://problem/8048875>. We should not render :first-letter CSS Style +// in a SVG text element context. +void RenderSVGText::updateFirstLetter() +{ } } diff --git a/WebCore/rendering/RenderSVGText.h b/WebCore/rendering/RenderSVGText.h index 66f7eb3..162c958 100644 --- a/WebCore/rendering/RenderSVGText.h +++ b/WebCore/rendering/RenderSVGText.h @@ -71,6 +71,9 @@ private: virtual RootInlineBox* createRootInlineBox(); + virtual RenderBlock* firstLineBlock() const; + virtual void updateFirstLetter(); + bool m_needsTransformUpdate : 1; AffineTransform m_localTransform; }; diff --git a/WebCore/rendering/RenderSlider.cpp b/WebCore/rendering/RenderSlider.cpp index aed8a8c..60b2369 100644 --- a/WebCore/rendering/RenderSlider.cpp +++ b/WebCore/rendering/RenderSlider.cpp @@ -28,14 +28,14 @@ #include "EventNames.h" #include "Frame.h" #include "HTMLInputElement.h" -#include "HTMLDivElement.h" #include "HTMLNames.h" -#include "HTMLParser.h" +#include "LegacyHTMLTreeConstructor.h" #include "MediaControlElements.h" #include "MouseEvent.h" #include "RenderLayer.h" #include "RenderTheme.h" #include "RenderView.h" +#include "ShadowElement.h" #include "StepRange.h" #include <wtf/MathExtras.h> @@ -47,8 +47,6 @@ using std::min; namespace WebCore { -using namespace HTMLNames; - static const int defaultTrackLength = 129; // Returns a value between 0 and 1. @@ -59,7 +57,7 @@ static double sliderPosition(HTMLInputElement* element) } // FIXME: Could share code with the SliderDivElement class in RenderProgress. -class SliderThumbElement : public HTMLDivElement { +class SliderThumbElement : public ShadowBlockElement { public: static PassRefPtr<SliderThumbElement> create(Node* shadowParent); @@ -71,17 +69,12 @@ public: private: SliderThumbElement(Node* shadowParent); - virtual bool isShadowNode() const { return true; } - virtual Node* shadowParentNode() { return m_shadowParent; } - FloatPoint m_offsetToThumb; - Node* m_shadowParent; bool m_inDragMode; }; inline SliderThumbElement::SliderThumbElement(Node* shadowParent) - : HTMLDivElement(divTag, shadowParent->document()) - , m_shadowParent(shadowParent) + : ShadowBlockElement(shadowParent) , m_inDragMode(false) { } @@ -94,7 +87,7 @@ inline PassRefPtr<SliderThumbElement> SliderThumbElement::create(Node* shadowPar void SliderThumbElement::defaultEventHandler(Event* event) { if (!event->isMouseEvent()) { - HTMLDivElement::defaultEventHandler(event); + ShadowBlockElement::defaultEventHandler(event); return; } @@ -118,7 +111,7 @@ void SliderThumbElement::defaultEventHandler(Event* event) } m_inDragMode = true; - document()->frame()->eventHandler()->setCapturingMouseEventsNode(m_shadowParent); + document()->frame()->eventHandler()->setCapturingMouseEventsNode(shadowParentNode()); event->setDefaultHandled(); return; } @@ -144,7 +137,7 @@ void SliderThumbElement::defaultEventHandler(Event* event) } } - HTMLDivElement::defaultEventHandler(event); + ShadowBlockElement::defaultEventHandler(event); } void SliderThumbElement::detach() @@ -153,7 +146,7 @@ void SliderThumbElement::detach() if (Frame* frame = document()->frame()) frame->eventHandler()->setCapturingMouseEventsNode(0); } - HTMLDivElement::detach(); + ShadowBlockElement::detach(); } RenderSlider::RenderSlider(HTMLInputElement* element) diff --git a/WebCore/rendering/RenderTextControl.cpp b/WebCore/rendering/RenderTextControl.cpp index 7724619..d1c8039 100644 --- a/WebCore/rendering/RenderTextControl.cpp +++ b/WebCore/rendering/RenderTextControl.cpp @@ -169,7 +169,7 @@ void RenderTextControl::setInnerTextValue(const String& innerTextValue) String value = innerTextValue; if (value != text() || !m_innerText->hasChildNodes()) { if (value != text()) { - if (Frame* frame = document()->frame()) { + if (Frame* frame = this->frame()) { frame->editor()->clearUndoRedoOperations(); if (AXObjectCache::accessibilityEnabled()) @@ -201,7 +201,7 @@ void RenderTextControl::setLastChangeWasUserEdit(bool lastChangeWasUserEdit) int RenderTextControl::selectionStart() { - Frame* frame = document()->frame(); + Frame* frame = this->frame(); if (!frame) return 0; return indexForVisiblePosition(frame->selection()->start()); @@ -209,7 +209,7 @@ int RenderTextControl::selectionStart() int RenderTextControl::selectionEnd() { - Frame* frame = document()->frame(); + Frame* frame = this->frame(); if (!frame) return 0; return indexForVisiblePosition(frame->selection()->end()); @@ -255,7 +255,7 @@ void RenderTextControl::setSelectionRange(int start, int end) } VisibleSelection newSelection = VisibleSelection(startPosition, endPosition); - if (Frame* frame = document()->frame()) + if (Frame* frame = this->frame()) frame->selection()->setSelection(newSelection); } @@ -545,7 +545,7 @@ void RenderTextControl::selectionChanged(bool userTriggered) { cacheSelection(selectionStart(), selectionEnd()); - if (Frame* frame = document()->frame()) { + if (Frame* frame = this->frame()) { if (frame->selection()->isRange() && userTriggered) node()->dispatchEvent(Event::create(eventNames().selectEvent, true, false)); } diff --git a/WebCore/rendering/RenderTextControlMultiLine.cpp b/WebCore/rendering/RenderTextControlMultiLine.cpp index 76bf612..976d1ac 100644 --- a/WebCore/rendering/RenderTextControlMultiLine.cpp +++ b/WebCore/rendering/RenderTextControlMultiLine.cpp @@ -57,7 +57,7 @@ void RenderTextControlMultiLine::subtreeHasChanged() node()->dispatchEvent(Event::create(eventNames().inputEvent, true, false)); - if (Frame* frame = document()->frame()) + if (Frame* frame = this->frame()) frame->textDidChangeInTextArea(textArea); } diff --git a/WebCore/rendering/RenderTextControlSingleLine.cpp b/WebCore/rendering/RenderTextControlSingleLine.cpp index 20f33c3..d3892e9 100644 --- a/WebCore/rendering/RenderTextControlSingleLine.cpp +++ b/WebCore/rendering/RenderTextControlSingleLine.cpp @@ -27,13 +27,14 @@ #include "EventNames.h" #include "Frame.h" #include "FrameView.h" -#include "HitTestResult.h" #include "HTMLInputElement.h" #include "HTMLNames.h" +#include "HitTestResult.h" #include "InputElement.h" #include "LocalizedStrings.h" #include "MouseEvent.h" #include "PlatformKeyboardEvent.h" +#include "RenderLayer.h" #include "RenderScrollbar.h" #include "RenderTheme.h" #include "SearchPopupMenu.h" @@ -171,7 +172,7 @@ void RenderTextControlSingleLine::subtreeHasChanged() startSearchEventTimer(); if (!wasChanged && node()->focused()) { - if (Frame* frame = document()->frame()) + if (Frame* frame = this->frame()) frame->textFieldDidBeginEditing(static_cast<Element*>(node())); } diff --git a/WebCore/rendering/RenderTextControlSingleLine.h b/WebCore/rendering/RenderTextControlSingleLine.h index b093954..dff9e5f 100644 --- a/WebCore/rendering/RenderTextControlSingleLine.h +++ b/WebCore/rendering/RenderTextControlSingleLine.h @@ -108,6 +108,8 @@ private: // PopupMenuClient methods virtual void valueChanged(unsigned listIndex, bool fireEvents = true); + virtual void selectionChanged(unsigned, bool) {} + virtual void selectionCleared() {} virtual String itemText(unsigned listIndex) const; virtual String itemToolTip(unsigned) const { return String(); } virtual String itemAccessibilityText(unsigned) const { return String(); } diff --git a/WebCore/rendering/RenderTheme.cpp b/WebCore/rendering/RenderTheme.cpp index c37de8d..2b5efc9 100644 --- a/WebCore/rendering/RenderTheme.cpp +++ b/WebCore/rendering/RenderTheme.cpp @@ -226,6 +226,10 @@ void RenderTheme::adjustStyle(CSSStyleSelector* selector, RenderStyle* style, El #endif #if ENABLE(METER_TAG) case MeterPart: + case RelevancyLevelIndicatorPart: + case ContinuousCapacityLevelIndicatorPart: + case DiscreteCapacityLevelIndicatorPart: + case RatingLevelIndicatorPart: return adjustMeterStyle(selector, style, e); #endif default: @@ -288,6 +292,10 @@ bool RenderTheme::paint(RenderObject* o, const RenderObject::PaintInfo& paintInf return paintMenuList(o, paintInfo, r); #if ENABLE(METER_TAG) case MeterPart: + case RelevancyLevelIndicatorPart: + case ContinuousCapacityLevelIndicatorPart: + case DiscreteCapacityLevelIndicatorPart: + case RatingLevelIndicatorPart: return paintMeter(o, paintInfo, r); #endif #if ENABLE(PROGRESS_TAG) @@ -386,6 +394,10 @@ bool RenderTheme::paintBorderOnly(RenderObject* o, const RenderObject::PaintInfo case MenulistPart: #if ENABLE(METER_TAG) case MeterPart: + case RelevancyLevelIndicatorPart: + case ContinuousCapacityLevelIndicatorPart: + case DiscreteCapacityLevelIndicatorPart: + case RatingLevelIndicatorPart: #endif #if ENABLE(PROGRESS_TAG) case ProgressBarPart: @@ -427,6 +439,10 @@ bool RenderTheme::paintDecorations(RenderObject* o, const RenderObject::PaintInf case MenulistPart: #if ENABLE(METER_TAG) case MeterPart: + case RelevancyLevelIndicatorPart: + case ContinuousCapacityLevelIndicatorPart: + case DiscreteCapacityLevelIndicatorPart: + case RatingLevelIndicatorPart: #endif #if ENABLE(PROGRESS_TAG) case ProgressBarPart: @@ -897,8 +913,16 @@ void RenderTheme::adjustMeterStyle(CSSStyleSelector*, RenderStyle* style, Elemen style->setBoxShadow(0); } +IntSize RenderTheme::meterSizeForBounds(const RenderMeter*, const IntRect& bounds) const +{ + return bounds.size(); +} + bool RenderTheme::paintMeter(RenderObject* renderObject, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) { + if (!renderObject->isMeter()) + return true; + // Some platforms do not have a native gauge widget, so we draw here a default implementation. RenderMeter* renderMeter = toRenderMeter(renderObject); RenderStyle* style = renderObject->style(); diff --git a/WebCore/rendering/RenderTheme.h b/WebCore/rendering/RenderTheme.h index a4514a5..2d196c7 100644 --- a/WebCore/rendering/RenderTheme.h +++ b/WebCore/rendering/RenderTheme.h @@ -39,6 +39,9 @@ namespace WebCore { class Element; class PopupMenu; class RenderMenuList; +#if ENABLE(METER_TAG) +class RenderMeter; +#endif #if ENABLE(PROGRESS_TAG) class RenderProgress; #endif @@ -190,6 +193,10 @@ public: virtual String formatMediaControlsRemainingTime(float currentTime, float duration) const; #endif +#if ENABLE(METER_TAG) + virtual IntSize meterSizeForBounds(const RenderMeter*, const IntRect&) const; +#endif + protected: // The platform selection color. virtual Color platformActiveSelectionBackgroundColor() const; diff --git a/WebCore/rendering/RenderThemeChromiumSkia.cpp b/WebCore/rendering/RenderThemeChromiumSkia.cpp index 0956e38..e3afd1f 100644 --- a/WebCore/rendering/RenderThemeChromiumSkia.cpp +++ b/WebCore/rendering/RenderThemeChromiumSkia.cpp @@ -26,6 +26,7 @@ #include "ChromiumBridge.h" #include "CSSValueKeywords.h" +#include "CurrentTime.h" #include "GraphicsContext.h" #include "HTMLMediaElement.h" #include "HTMLNames.h" @@ -35,6 +36,7 @@ #include "RenderBox.h" #include "RenderMediaControlsChromium.h" #include "RenderObject.h" +#include "RenderProgress.h" #include "RenderSlider.h" #include "ScrollbarTheme.h" #include "TimeRanges.h" @@ -768,4 +770,113 @@ int RenderThemeChromiumSkia::menuListInternalPadding(RenderStyle* style, int pad return padding; } +#if ENABLE(PROGRESS_TAG) + +// +// Following values are come from default of GTK+ +// +static const int progressDeltaPixelsPerSecond = 100; +static const int progressActivityBlocks = 5; +static const int progressAnimationFrmaes = 10; +static const double progressAnimationInterval = 0.125; + +IntRect RenderThemeChromiumSkia::determinateProgressValueRectFor(RenderProgress* renderProgress, const IntRect& rect) const +{ + int dx = rect.width() * renderProgress->position(); + if (renderProgress->style()->direction() == RTL) + return IntRect(rect.x() + rect.width() - dx, rect.y(), dx, rect.height()); + return IntRect(rect.x(), rect.y(), dx, rect.height()); +} + +IntRect RenderThemeChromiumSkia::indeterminateProgressValueRectFor(RenderProgress* renderProgress, const IntRect& rect) const +{ + + int valueWidth = rect.width() / progressActivityBlocks; + int movableWidth = rect.width() - valueWidth; + if (movableWidth <= 0) + return IntRect(); + + double progress = renderProgress->animationProgress(); + if (progress < 0.5) + return IntRect(rect.x() + progress * 2 * movableWidth, rect.y(), valueWidth, rect.height()); + return IntRect(rect.x() + (1.0 - progress) * 2 * movableWidth, rect.y(), valueWidth, rect.height()); +} + +double RenderThemeChromiumSkia::animationRepeatIntervalForProgressBar(RenderProgress*) const +{ + return progressAnimationInterval; +} + +double RenderThemeChromiumSkia::animationDurationForProgressBar(RenderProgress* renderProgress) const +{ + return progressAnimationInterval * progressAnimationFrmaes * 2; // "2" for back and forth +} + +bool RenderThemeChromiumSkia::paintProgressBar(RenderObject* renderObject, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) +{ + static Image* barImage = Image::loadPlatformResource("linuxProgressBar").releaseRef(); + static Image* valueImage = Image::loadPlatformResource("linuxProgressValue").releaseRef(); + static Image* leftBorderImage = Image::loadPlatformResource("linuxProgressBorderLeft").releaseRef(); + static Image* rightBorderImage = Image::loadPlatformResource("linuxProgressBorderRight").releaseRef(); + ASSERT(barImage->height() == valueImage->height()); + + if (!renderObject->isProgress()) + return true; + + paintInfo.context->platformContext()->setImageResamplingHint(barImage->size(), rect.size()); + + RenderProgress* renderProgress = toRenderProgress(renderObject); + double tileScale = static_cast<double>(rect.height()) / barImage->height(); + IntSize barTileSize(static_cast<int>(barImage->width() * tileScale), rect.height()); + ColorSpace colorSpace = renderObject->style()->colorSpace(); + + paintInfo.context->drawTiledImage(barImage, colorSpace, rect, IntPoint(0, 0), barTileSize); + + IntRect valueRect = progressValueRectFor(renderProgress, rect); + if (valueRect.width()) { + + IntSize valueTileSize(static_cast<int>(valueImage->width() * tileScale), valueRect.height()); + int leftOffset = valueRect.x() - rect.x(); + int roundedLeftOffset= (leftOffset / valueTileSize.width()) * valueTileSize.width(); + int dstLeftValueWidth = roundedLeftOffset - leftOffset + (leftOffset % valueImage->width()) ? valueTileSize.width() : 0; + + IntRect dstLeftValueRect(valueRect.x(), valueRect.y(), dstLeftValueWidth, valueRect.height()); + int srcLeftValueWidth = dstLeftValueWidth / tileScale; + IntRect srcLeftValueRect(valueImage->width() - srcLeftValueWidth, 0, srcLeftValueWidth, valueImage->height()); + paintInfo.context->drawImage(valueImage, colorSpace, dstLeftValueRect, srcLeftValueRect); + + int rightOffset = valueRect.right() - rect.x(); + int roundedRightOffset = (rightOffset / valueTileSize.width()) * valueTileSize.width(); + int dstRightValueWidth = rightOffset - roundedRightOffset; + IntRect dstRightValueRect(rect.x() + roundedRightOffset, valueRect.y(), dstRightValueWidth, valueTileSize.height()); + int srcRightValueWidth = dstRightValueWidth / tileScale; + IntRect srcRightValueRect(0, 0, srcRightValueWidth, valueImage->height()); + paintInfo.context->drawImage(valueImage, colorSpace, dstRightValueRect, srcRightValueRect); + + IntRect alignedValueRect(dstLeftValueRect.right(), dstLeftValueRect.y(), + dstRightValueRect.x() - dstLeftValueRect.right(), dstLeftValueRect.height()); + paintInfo.context->drawTiledImage(valueImage, colorSpace, alignedValueRect, IntPoint(0, 0), valueTileSize); + } + + int dstLeftBorderWidth = leftBorderImage->width() * tileScale; + IntRect dstLeftBorderRect(rect.x(), rect.y(), dstLeftBorderWidth, rect.height()); + paintInfo.context->drawImage(leftBorderImage, colorSpace, dstLeftBorderRect, leftBorderImage->rect()); + + int dstRightBorderWidth = rightBorderImage->width() * tileScale; + IntRect dstRightBorderRect(rect.right() - dstRightBorderWidth, rect.y(), dstRightBorderWidth, rect.height()); + paintInfo.context->drawImage(rightBorderImage, colorSpace, dstRightBorderRect, rightBorderImage->rect()); + + paintInfo.context->platformContext()->clearImageResamplingHint(); + + return false; +} + + +IntRect RenderThemeChromiumSkia::progressValueRectFor(RenderProgress* renderProgress, const IntRect& rect) const +{ + return renderProgress->isDeterminate() ? determinateProgressValueRectFor(renderProgress, rect) : indeterminateProgressValueRectFor(renderProgress, rect); +} + +#endif + } // namespace WebCore diff --git a/WebCore/rendering/RenderThemeChromiumSkia.h b/WebCore/rendering/RenderThemeChromiumSkia.h index dc920b1cf..56c315e 100644 --- a/WebCore/rendering/RenderThemeChromiumSkia.h +++ b/WebCore/rendering/RenderThemeChromiumSkia.h @@ -32,6 +32,8 @@ namespace WebCore { +class RenderProgress; + class RenderThemeChromiumSkia : public RenderTheme { public: RenderThemeChromiumSkia(); @@ -117,6 +119,12 @@ namespace WebCore { virtual bool paintSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual bool paintSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); +#if ENABLE(PROGRESS_TAG) + virtual double animationRepeatIntervalForProgressBar(RenderProgress*) const; + virtual double animationDurationForProgressBar(RenderProgress*) const; + virtual bool paintProgressBar(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); +#endif + // These methods define the padding for the MenuList's inner block. virtual int popupInternalPaddingLeft(RenderStyle*) const; virtual int popupInternalPaddingRight(RenderStyle*) const; @@ -145,6 +153,12 @@ namespace WebCore { virtual double caretBlinkIntervalInternal() const; +#if ENABLE(PROGRESS_TAG) + IntRect determinateProgressValueRectFor(RenderProgress*, const IntRect&) const; + IntRect indeterminateProgressValueRectFor(RenderProgress*, const IntRect&) const; + IntRect progressValueRectFor(RenderProgress*, const IntRect&) const; +#endif + private: int menuListInternalPadding(RenderStyle*, int paddingType) const; bool paintMediaButtonInternal(GraphicsContext*, const IntRect&, Image*); diff --git a/WebCore/rendering/RenderThemeChromiumWin.cpp b/WebCore/rendering/RenderThemeChromiumWin.cpp index cc7570c..d82fddc 100644 --- a/WebCore/rendering/RenderThemeChromiumWin.cpp +++ b/WebCore/rendering/RenderThemeChromiumWin.cpp @@ -679,21 +679,13 @@ void RenderThemeChromiumWin::adjustProgressBarStyle(CSSStyleSelector*, RenderSty bool RenderThemeChromiumWin::paintProgressBar(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) { - RenderProgress* renderProgress = toRenderProgress(o); - - IntRect valueRect; - if (renderProgress->isDeterminate()) { - 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 { - // 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); - } + if (!o->isProgress()) + return true; + RenderProgress* renderProgress = toRenderProgress(o); + // 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. + IntRect valueRect = renderProgress->isDeterminate() ? determinateProgressValueRectFor(renderProgress, r) : IntRect(0, 0, 0, 0); double animatedSeconds = renderProgress->animationStartTime() ? WTF::currentTime() - renderProgress->animationStartTime() : 0; ThemePainter painter(i.context, r); ChromiumBridge::paintProgressBar(painter.context(), r, valueRect, renderProgress->isDeterminate(), animatedSeconds); diff --git a/WebCore/rendering/RenderThemeMac.h b/WebCore/rendering/RenderThemeMac.h index cb604b9..7cb4e3b 100644 --- a/WebCore/rendering/RenderThemeMac.h +++ b/WebCore/rendering/RenderThemeMac.h @@ -80,6 +80,11 @@ public: virtual bool paintCapsLockIndicator(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); +#if ENABLE(METER_TAG) + virtual IntSize meterSizeForBounds(const RenderMeter*, const IntRect&) const; + virtual bool paintMeter(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); +#endif + #if ENABLE(PROGRESS_TAG) // Returns the repeat interval of the animation for the progress bar. virtual double animationRepeatIntervalForProgressBar(RenderProgress*) const; @@ -201,12 +206,18 @@ private: NSSliderCell* sliderThumbHorizontal() const; NSSliderCell* sliderThumbVertical() const; +#if ENABLE(METER_TAG) + NSLevelIndicatorStyle levelIndicatorStyleFor(ControlPart) const; + NSLevelIndicatorCell* levelIndicatorFor(const RenderMeter*) const; +#endif + private: mutable RetainPtr<NSPopUpButtonCell> m_popupButton; mutable RetainPtr<NSSearchFieldCell> m_search; mutable RetainPtr<NSMenu> m_searchMenuTemplate; mutable RetainPtr<NSSliderCell> m_sliderThumbHorizontal; mutable RetainPtr<NSSliderCell> m_sliderThumbVertical; + mutable RetainPtr<NSLevelIndicatorCell> m_levelIndicator; bool m_isSliderThumbHorizontalPressed; bool m_isSliderThumbVerticalPressed; diff --git a/WebCore/rendering/RenderThemeMac.mm b/WebCore/rendering/RenderThemeMac.mm index f1de775..d0289de 100644 --- a/WebCore/rendering/RenderThemeMac.mm +++ b/WebCore/rendering/RenderThemeMac.mm @@ -51,6 +51,11 @@ #import "RenderProgress.h" +#if ENABLE(METER_TAG) +#include "RenderMeter.h" +#include "HTMLMeterElement.h" +#endif + #ifdef BUILDING_ON_TIGER typedef int NSInteger; typedef unsigned NSUInteger; @@ -801,7 +806,100 @@ bool RenderThemeMac::paintMenuList(RenderObject* o, const RenderObject::PaintInf return false; } - + +#if ENABLE(METER_TAG) + +IntSize RenderThemeMac::meterSizeForBounds(const RenderMeter* renderMeter, const IntRect& bounds) const +{ + if (NoControlPart == renderMeter->style()->appearance()) + return bounds.size(); + + NSLevelIndicatorCell* cell = levelIndicatorFor(renderMeter); + // Makes enough room for cell's intrinsic size. + NSSize cellSize = [cell cellSizeForBounds:IntRect(IntPoint(), bounds.size())]; + return IntSize(bounds.width() < cellSize.width ? cellSize.width : bounds.width(), + bounds.height() < cellSize.height ? cellSize.height : bounds.height()); +} + +bool RenderThemeMac::paintMeter(RenderObject* renderObject, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) +{ + if (!renderObject->isMeter()) + return true; + + // Becaue NSLevelIndicatorCell doesn't support vertical gauge, we use a portable version + if (rect.width() < rect.height()) + return RenderTheme::paintMeter(renderObject, paintInfo, rect); + + NSLevelIndicatorCell* cell = levelIndicatorFor(toRenderMeter(renderObject)); + paintInfo.context->save(); + [cell drawWithFrame:rect inView:documentViewFor(renderObject)]; + [cell setControlView:nil]; + paintInfo.context->restore(); + + return false; +} + +NSLevelIndicatorStyle RenderThemeMac::levelIndicatorStyleFor(ControlPart part) const +{ + switch (part) { + case RelevancyLevelIndicatorPart: + return NSRelevancyLevelIndicatorStyle; + case DiscreteCapacityLevelIndicatorPart: + return NSDiscreteCapacityLevelIndicatorStyle; + case RatingLevelIndicatorPart: + return NSRatingLevelIndicatorStyle; + case MeterPart: + case ContinuousCapacityLevelIndicatorPart: + default: + return NSContinuousCapacityLevelIndicatorStyle; + } + +} + +NSLevelIndicatorCell* RenderThemeMac::levelIndicatorFor(const RenderMeter* renderMeter) const +{ + RenderStyle* style = renderMeter->style(); + ASSERT(style->appearance() != NoControlPart); + + if (!m_levelIndicator) + m_levelIndicator.adoptNS([[NSLevelIndicatorCell alloc] initWithLevelIndicatorStyle:NSContinuousCapacityLevelIndicatorStyle]); + NSLevelIndicatorCell* cell = m_levelIndicator.get(); + + HTMLMeterElement* element = static_cast<HTMLMeterElement*>(renderMeter->node()); + double value = element->value(); + + // Because NSLevelIndicatorCell does not support optimum-in-the-middle type coloring, + // we explicitly control the color instead giving low and high value to NSLevelIndicatorCell as is. + switch (element->gaugeRegion()) { + case HTMLMeterElement::GaugeRegionOptimum: + // Make meter the green + [cell setWarningValue:value + 1]; + [cell setCriticalValue:value + 2]; + break; + case HTMLMeterElement::GaugeRegionSuboptimal: + // Make the meter yellow + [cell setWarningValue:value - 1]; + [cell setCriticalValue:value + 1]; + break; + case HTMLMeterElement::GaugeRegionEvenLessGood: + // Make the meter red + [cell setWarningValue:value - 2]; + [cell setCriticalValue:value - 1]; + break; + } + + [cell setLevelIndicatorStyle:levelIndicatorStyleFor(style->appearance())]; + [cell setBaseWritingDirection:style->direction() == LTR ? NSWritingDirectionLeftToRight : NSWritingDirectionRightToLeft]; + [cell setMinValue:element->min()]; + [cell setMaxValue:element->max()]; + RetainPtr<NSNumber> valueObject = [NSNumber numberWithDouble:value]; + [cell setObjectValue:valueObject.get()]; + + return cell; +} + +#endif + #if ENABLE(PROGRESS_TAG) double RenderThemeMac::animationRepeatIntervalForProgressBar(RenderProgress*) const @@ -820,6 +918,9 @@ void RenderThemeMac::adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Ele bool RenderThemeMac::paintProgressBar(RenderObject* renderObject, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) { + if (!renderObject->isProgress()) + return true; + RenderProgress* renderProgress = toRenderProgress(renderObject); HIThemeTrackDrawInfo trackInfo; trackInfo.version = 0; diff --git a/WebCore/rendering/RenderTreeAsText.cpp b/WebCore/rendering/RenderTreeAsText.cpp index cf76f0b..b05d97a 100644 --- a/WebCore/rendering/RenderTreeAsText.cpp +++ b/WebCore/rendering/RenderTreeAsText.cpp @@ -38,6 +38,7 @@ #include "RenderBR.h" #include "RenderFileUploadControl.h" #include "RenderInline.h" +#include "RenderLayer.h" #include "RenderListItem.h" #include "RenderListMarker.h" #include "RenderPart.h" diff --git a/WebCore/rendering/RenderWidget.cpp b/WebCore/rendering/RenderWidget.cpp index e477676..2556bbb 100644 --- a/WebCore/rendering/RenderWidget.cpp +++ b/WebCore/rendering/RenderWidget.cpp @@ -27,6 +27,7 @@ #include "AnimationController.h" #include "GraphicsContext.h" #include "HitTestResult.h" +#include "RenderLayer.h" #include "RenderView.h" #include "RenderWidgetProtector.h" @@ -333,7 +334,7 @@ void RenderWidget::updateWidgetPosition() #ifndef ANDROID_FLATTEN_IFRAME // if the frame bounds got changed, or if view needs layout (possibly indicating // content size is wrong) we have to do a layout to set the right widget size - if (m_widget->isFrameView()) { + if (m_widget && m_widget->isFrameView()) { FrameView* frameView = static_cast<FrameView*>(m_widget.get()); if (boundsChanged || frameView->needsLayout()) frameView->layout(); diff --git a/WebCore/rendering/RootInlineBox.cpp b/WebCore/rendering/RootInlineBox.cpp index 691179d..24e49c6 100644 --- a/WebCore/rendering/RootInlineBox.cpp +++ b/WebCore/rendering/RootInlineBox.cpp @@ -126,7 +126,7 @@ void RootInlineBox::paintEllipsisBox(RenderObject::PaintInfo& paintInfo, int tx, void RootInlineBox::addHighlightOverflow() { - Frame* frame = renderer()->document()->frame(); + Frame* frame = renderer()->frame(); if (!frame) return; Page* page = frame->page(); @@ -145,7 +145,7 @@ void RootInlineBox::paintCustomHighlight(RenderObject::PaintInfo& paintInfo, int if (!renderer()->shouldPaintWithinRoot(paintInfo) || renderer()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseForeground) return; - Frame* frame = renderer()->document()->frame(); + Frame* frame = renderer()->frame(); if (!frame) return; Page* page = frame->page(); diff --git a/WebCore/rendering/SVGRenderSupport.cpp b/WebCore/rendering/SVGRenderSupport.cpp index 2600512..2ae90de 100644 --- a/WebCore/rendering/SVGRenderSupport.cpp +++ b/WebCore/rendering/SVGRenderSupport.cpp @@ -32,6 +32,7 @@ #include "Document.h" #include "ImageBuffer.h" #include "NodeRenderStyle.h" +#include "RenderLayer.h" #include "RenderObject.h" #include "RenderSVGContainer.h" #include "RenderSVGResource.h" @@ -81,7 +82,7 @@ void SVGRenderBase::mapLocalToContainer(const RenderObject* object, RenderBoxMod object->parent()->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState); } -bool SVGRenderBase::prepareToRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, const FloatRect& repaintRect, RenderSVGResourceFilter*& filter, RenderSVGResourceFilter* rootFilter) +bool SVGRenderBase::prepareToRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, const FloatRect& repaintRect, RenderSVGResourceFilter*& filter) { #if !ENABLE(FILTERS) UNUSED_PARAM(filter); @@ -99,7 +100,7 @@ bool SVGRenderBase::prepareToRenderSVGContent(RenderObject* object, RenderObject const SVGRenderStyle* svgStyle = style->svgStyle(); ASSERT(svgStyle); - // Setup transparency layers before setting up filters! + // Setup transparency layers before setting up SVG resources! float opacity = style->opacity(); if (opacity < 1.0f) { paintInfo.context->clip(repaintRect); @@ -112,43 +113,35 @@ bool SVGRenderBase::prepareToRenderSVGContent(RenderObject* object, RenderObject paintInfo.context->beginTransparencyLayer(1.0f); } -#if ENABLE(FILTERS) - AtomicString filterId(svgStyle->filterResource()); -#endif - - AtomicString clipperId(svgStyle->clipperResource()); - AtomicString maskerId(svgStyle->maskerResource()); - Document* document = object->document(); -#if ENABLE(FILTERS) - RenderSVGResourceFilter* newFilter = getRenderSVGResourceById<RenderSVGResourceFilter>(document, filterId); - if (newFilter == rootFilter) { - // Catch <text filter="url(#foo)">Test<tspan filter="url(#foo)">123</tspan></text>. - // The filter is NOT meant to be applied twice in that case! - filter = 0; - filterId = String(); - } else - filter = newFilter; -#endif - - if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(document, maskerId)) { - if (!masker->applyResource(object, style, paintInfo.context, ApplyToDefaultMode)) - return false; - } else if (!maskerId.isEmpty()) - svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement); + if (svgStyle->hasMasker()) { + AtomicString maskerId(svgStyle->maskerResource()); + if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(document, maskerId)) { + if (!masker->applyResource(object, style, paintInfo.context, ApplyToDefaultMode)) + return false; + } else + svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement); + } - if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(document, clipperId)) - clipper->applyResource(object, style, paintInfo.context, ApplyToDefaultMode); - else if (!clipperId.isEmpty()) - svgElement->document()->accessSVGExtensions()->addPendingResource(clipperId, styledElement); + if (svgStyle->hasClipper()) { + AtomicString clipperId(svgStyle->clipperResource()); + if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(document, clipperId)) + clipper->applyResource(object, style, paintInfo.context, ApplyToDefaultMode); + else + svgElement->document()->accessSVGExtensions()->addPendingResource(clipperId, styledElement); + } #if ENABLE(FILTERS) - if (filter) { - if (!filter->applyResource(object, style, paintInfo.context, ApplyToDefaultMode)) - return false; - } else if (!filterId.isEmpty()) - svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement); + if (svgStyle->hasFilter()) { + AtomicString filterId(svgStyle->filterResource()); + filter = getRenderSVGResourceById<RenderSVGResourceFilter>(document, filterId); + if (filter) { + if (!filter->applyResource(object, style, paintInfo.context, ApplyToDefaultMode)) + return false; + } else + svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement); + } #endif return true; @@ -280,31 +273,33 @@ bool SVGRenderBase::isOverflowHidden(const RenderObject* object) return object->style()->overflowX() == OHIDDEN; } -FloatRect SVGRenderBase::filterBoundingBoxForRenderer(const RenderObject* object) const +void SVGRenderBase::intersectRepaintRectWithResources(const RenderObject* object, FloatRect& repaintRect) const { + ASSERT(object); + ASSERT(object->style()); + const SVGRenderStyle* svgStyle = object->style()->svgStyle(); + if (!svgStyle) + return; + + RenderObject* renderer = const_cast<RenderObject*>(object); #if ENABLE(FILTERS) - if (RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(object->document(), object->style()->svgStyle()->filterResource())) - return filter->resourceBoundingBox(object->objectBoundingBox()); -#else - UNUSED_PARAM(object); + if (svgStyle->hasFilter()) { + if (RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(object->document(), svgStyle->filterResource())) + repaintRect = filter->resourceBoundingBox(renderer); + } #endif - return FloatRect(); -} - -FloatRect SVGRenderBase::clipperBoundingBoxForRenderer(const RenderObject* object) const -{ - if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(object->document(), object->style()->svgStyle()->clipperResource())) - return clipper->resourceBoundingBox(object->objectBoundingBox()); - - return FloatRect(); -} -FloatRect SVGRenderBase::maskerBoundingBoxForRenderer(const RenderObject* object) const -{ - if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(object->document(), object->style()->svgStyle()->maskerResource())) - return masker->resourceBoundingBox(object->objectBoundingBox()); - - return FloatRect(); + if (svgStyle->hasClipper()) { + if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(object->document(), svgStyle->clipperResource())) + repaintRect.intersect(clipper->resourceBoundingBox(renderer)); + } + + if (svgStyle->hasMasker()) { + if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(object->document(), svgStyle->maskerResource())) + repaintRect.intersect(masker->resourceBoundingBox(renderer)); + } + + svgStyle->inflateForShadow(repaintRect); } static inline void invalidatePaintingResource(SVGPaint* paint, RenderObject* object) @@ -320,6 +315,27 @@ static inline void invalidatePaintingResource(SVGPaint* paint, RenderObject* obj paintingResource->invalidateClient(object); } +bool pointInClippingArea(const RenderObject* object, const FloatPoint& point) +{ + ASSERT(object); + ASSERT(object->style()); + + Document* document = object->document(); + ASSERT(document); + + const SVGRenderStyle* svgStyle = object->style()->svgStyle(); + ASSERT(svgStyle); + + // We just take clippers into account to determine if a point is on the node. The Specification may + // change later and we also need to check maskers. + if (svgStyle->hasClipper()) { + if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(document, svgStyle->clipperResource())) + return clipper->hitTestClipContent(object->objectBoundingBox(), point); + } + + return true; +} + void deregisterFromResources(RenderObject* object) { ASSERT(object); diff --git a/WebCore/rendering/SVGRenderSupport.h b/WebCore/rendering/SVGRenderSupport.h index b8a014a..e961c73 100644 --- a/WebCore/rendering/SVGRenderSupport.h +++ b/WebCore/rendering/SVGRenderSupport.h @@ -46,7 +46,7 @@ public: // FIXME: These are only public for SVGRootInlineBox. // It's unclear if these should be exposed or not. SVGRootInlineBox may // pass the wrong RenderObject* and boundingBox to these functions. - static bool prepareToRenderSVGContent(RenderObject*, RenderObject::PaintInfo&, const FloatRect& boundingBox, RenderSVGResourceFilter*&, RenderSVGResourceFilter* rootFilter = 0); + static bool prepareToRenderSVGContent(RenderObject*, RenderObject::PaintInfo&, const FloatRect& boundingBox, RenderSVGResourceFilter*&); static void finishRenderSVGContent(RenderObject*, RenderObject::PaintInfo&, RenderSVGResourceFilter*&, GraphicsContext* savedContext); // Layout all children of the passed render object @@ -58,10 +58,8 @@ public: // strokeBoundingBox() includes the marker boundaries for a RenderPath object virtual FloatRect strokeBoundingBox() const { return FloatRect(); } - // returns the bounding box of filter, clipper, marker and masker (or the empty rect if no filter) in local coordinates - FloatRect filterBoundingBoxForRenderer(const RenderObject*) const; - FloatRect clipperBoundingBoxForRenderer(const RenderObject*) const; - FloatRect maskerBoundingBoxForRenderer(const RenderObject*) const; + // Calculates the repaintRect in combination with filter, clipper and masker in local coordinates. + void intersectRepaintRectWithResources(const RenderObject*, FloatRect&) const; protected: static IntRect clippedOverflowRectForRepaint(RenderObject*, RenderBoxModelObject* repaintContainer); @@ -81,6 +79,8 @@ void applyTransformToPaintInfo(RenderObject::PaintInfo&, const AffineTransform& // This offers a way to render parts of a WebKit rendering tree into a ImageBuffer. void renderSubtreeToImage(ImageBuffer*, RenderObject*); +bool pointInClippingArea(const RenderObject*, const FloatPoint&); + void deregisterFromResources(RenderObject*); void clampImageBufferSizeToViewport(FrameView*, IntSize& imageBufferSize); diff --git a/WebCore/rendering/SVGRenderTreeAsText.cpp b/WebCore/rendering/SVGRenderTreeAsText.cpp index 8668780..2a71dee 100644 --- a/WebCore/rendering/SVGRenderTreeAsText.cpp +++ b/WebCore/rendering/SVGRenderTreeAsText.cpp @@ -351,7 +351,7 @@ static void writeSVGPaintingResource(TextStream& ts, RenderSVGResource* resource else if (resource->resourceType() == RadialGradientResourceType) ts << "[type=RADIAL-GRADIENT]"; - ts << " [id=\"" << static_cast<SVGElement*>(node)->getIDAttribute() << "\"]"; + ts << " [id=\"" << static_cast<SVGElement*>(node)->getIdAttribute() << "\"]"; } static void writeStyle(TextStream& ts, const RenderObject& object) @@ -581,7 +581,7 @@ void writeSVGResourceContainer(TextStream& ts, const RenderObject& object, int i writeStandardPrefix(ts, object, indent); Element* element = static_cast<Element*>(object.node()); - const AtomicString& id = element->getIDAttribute(); + const AtomicString& id = element->getIdAttribute(); writeNameAndQuotedValue(ts, "id", id); RenderSVGResourceContainer* resource = const_cast<RenderObject&>(object).toRenderSVGResourceContainer(); @@ -734,6 +734,7 @@ void writeResources(TextStream& ts, const RenderObject& object, int indent) const RenderStyle* style = object.style(); const SVGRenderStyle* svgStyle = style->svgStyle(); + RenderObject& renderer = const_cast<RenderObject&>(object); if (!svgStyle->maskerResource().isEmpty()) { if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(object.document(), svgStyle->maskerResource())) { writeIndent(ts, indent); @@ -741,7 +742,7 @@ void writeResources(TextStream& ts, const RenderObject& object, int indent) writeNameAndQuotedValue(ts, "masker", svgStyle->maskerResource()); ts << " "; writeStandardPrefix(ts, *masker, 0); - ts << " " << masker->resourceBoundingBox(object.objectBoundingBox()) << "\n"; + ts << " " << masker->resourceBoundingBox(&renderer) << "\n"; } } if (!svgStyle->clipperResource().isEmpty()) { @@ -751,7 +752,7 @@ void writeResources(TextStream& ts, const RenderObject& object, int indent) writeNameAndQuotedValue(ts, "clipPath", svgStyle->clipperResource()); ts << " "; writeStandardPrefix(ts, *clipper, 0); - ts << " " << clipper->resourceBoundingBox(object.objectBoundingBox()) << "\n"; + ts << " " << clipper->resourceBoundingBox(&renderer) << "\n"; } } #if ENABLE(FILTERS) @@ -762,7 +763,7 @@ void writeResources(TextStream& ts, const RenderObject& object, int indent) writeNameAndQuotedValue(ts, "filter", svgStyle->filterResource()); ts << " "; writeStandardPrefix(ts, *filter, 0); - ts << " " << filter->resourceBoundingBox(object.objectBoundingBox()) << "\n"; + ts << " " << filter->resourceBoundingBox(&renderer) << "\n"; } } #endif diff --git a/WebCore/rendering/SVGRootInlineBox.cpp b/WebCore/rendering/SVGRootInlineBox.cpp index 8760fe5..6b750be 100644 --- a/WebCore/rendering/SVGRootInlineBox.cpp +++ b/WebCore/rendering/SVGRootInlineBox.cpp @@ -73,14 +73,13 @@ RenderSVGRoot* findSVGRootObject(RenderObject* start) // Helper class for paint() struct SVGRootInlineBoxPaintWalker { - SVGRootInlineBoxPaintWalker(SVGRootInlineBox* rootBox, RenderSVGResourceFilter* rootFilter, RenderObject::PaintInfo paintInfo, int tx, int ty) + SVGRootInlineBoxPaintWalker(SVGRootInlineBox* rootBox, RenderObject::PaintInfo paintInfo, int tx, int ty) : m_rootBox(rootBox) , m_chunkStarted(false) , m_paintInfo(paintInfo) , m_savedInfo(paintInfo) , m_boundingBox(tx + rootBox->x(), ty + rootBox->y(), rootBox->width(), rootBox->height()) , m_filter(0) - , m_rootFilter(rootFilter) , m_fillPaintingResource(0) , m_strokePaintingResource(0) , m_fillPaintingResourceObject(0) @@ -143,7 +142,7 @@ struct SVGRootInlineBoxPaintWalker { // FIXME: Why is this done here instead of in RenderSVGText? if (!flowBox->isRootInlineBox()) - SVGRenderBase::prepareToRenderSVGContent(object, m_paintInfo, m_boundingBox, m_filter, m_rootFilter); + SVGRenderBase::prepareToRenderSVGContent(object, m_paintInfo, m_boundingBox, m_filter); } void chunkEndCallback(InlineBox* box) @@ -403,7 +402,6 @@ private: FloatRect m_boundingBox; RenderSVGResourceFilter* m_filter; - RenderSVGResourceFilter* m_rootFilter; RenderSVGResource* m_fillPaintingResource; RenderSVGResource* m_strokePaintingResource; @@ -431,7 +429,7 @@ void SVGRootInlineBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) // Initialize text rendering if (SVGRenderBase::prepareToRenderSVGContent(renderer(), paintInfo, boundingBox, filter)) { // Render text, chunk-by-chunk - SVGRootInlineBoxPaintWalker walkerCallback(this, filter, paintInfo, tx, ty); + SVGRootInlineBoxPaintWalker walkerCallback(this, paintInfo, tx, ty); SVGTextChunkWalker<SVGRootInlineBoxPaintWalker> walker(&walkerCallback, &SVGRootInlineBoxPaintWalker::chunkPortionCallback, &SVGRootInlineBoxPaintWalker::chunkStartCallback, diff --git a/WebCore/rendering/ShadowElement.cpp b/WebCore/rendering/ShadowElement.cpp new file mode 100644 index 0000000..dea9233 --- /dev/null +++ b/WebCore/rendering/ShadowElement.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "ShadowElement.h" + +#include "HTMLNames.h" + +namespace WebCore { + +PassRefPtr<ShadowBlockElement> ShadowBlockElement::create(Node* shadowParent) +{ + return new ShadowBlockElement(shadowParent); +} + +ShadowBlockElement::ShadowBlockElement(Node* shadowParent) + : ShadowElement<HTMLDivElement>(HTMLNames::divTag, shadowParent) +{ +} + +PassRefPtr<ShadowInputElement> ShadowInputElement::create(Node* shadowParent) +{ + return new ShadowInputElement(shadowParent); +} + +ShadowInputElement::ShadowInputElement(Node* shadowParent) + : ShadowElement<HTMLInputElement>(HTMLNames::inputTag, shadowParent) +{ +} + +} // namespace WebCore diff --git a/WebCore/rendering/ShadowElement.h b/WebCore/rendering/ShadowElement.h new file mode 100644 index 0000000..90030ee --- /dev/null +++ b/WebCore/rendering/ShadowElement.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2008, 2009, 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ShadowElement_h +#define ShadowElement_h + +#include "HTMLDivElement.h" +#include "HTMLInputElement.h" + +namespace WebCore { + +template<class BaseElement> +class ShadowElement : public BaseElement { +protected: + ShadowElement(const QualifiedName& name, Node* shadowParent) + : BaseElement(name, shadowParent->document()) + , m_shadowParent(shadowParent) + {} + + virtual bool isShadowNode() const { return true; } + virtual Node* shadowParentNode() { return m_shadowParent; } + +private: + Node* m_shadowParent; +}; + +class ShadowBlockElement : public ShadowElement<HTMLDivElement> { +public: + static PassRefPtr<ShadowBlockElement> create(Node*); +protected: + ShadowBlockElement(Node*); +}; + +class ShadowInputElement : public ShadowElement<HTMLInputElement> { +public: + static PassRefPtr<ShadowInputElement> create(Node*); +protected: + ShadowInputElement(Node*); +}; + +} // namespace WebCore + +#endif // ShadowElement_h diff --git a/WebCore/rendering/style/RenderStyle.cpp b/WebCore/rendering/style/RenderStyle.cpp index 220e657..af4e055 100644 --- a/WebCore/rendering/style/RenderStyle.cpp +++ b/WebCore/rendering/style/RenderStyle.cpp @@ -916,11 +916,12 @@ const Animation* RenderStyle::transitionForProperty(int property) const void RenderStyle::setBlendedFontSize(int size) { + FontSelector* currentFontSelector = font().fontSelector(); FontDescription desc(fontDescription()); desc.setSpecifiedSize(size); desc.setComputedSize(size); setFontDescription(desc); - font().update(font().fontSelector()); + font().update(currentFontSelector); } void RenderStyle::getBoxShadowExtent(int &top, int &right, int &bottom, int &left) const diff --git a/WebCore/rendering/style/SVGRenderStyle.cpp b/WebCore/rendering/style/SVGRenderStyle.cpp index 042b8f7..f4e6cb5 100644 --- a/WebCore/rendering/style/SVGRenderStyle.cpp +++ b/WebCore/rendering/style/SVGRenderStyle.cpp @@ -1,6 +1,6 @@ /* Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org> - 2004, 2005 Rob Buis <buis@kde.org> + 2004, 2005, 2010 Rob Buis <buis@kde.org> Copyright (C) Research In Motion Limited 2010. All rights reserved. Based on khtml code by: @@ -146,14 +146,14 @@ float SVGRenderStyle::cssPrimitiveToLength(const RenderObject* item, CSSValue* v return primitive->computeLengthFloat(const_cast<RenderStyle*>(item->style()), item->document()->documentElement()->renderStyle()); } -static void getSVGShadowExtent(ShadowData* shadow, int& top, int& right, int& bottom, int& left) +static void getSVGShadowExtent(ShadowData* shadow, float& top, float& right, float& bottom, float& left) { - top = 0; - right = 0; - bottom = 0; - left = 0; + top = 0.0f; + right = 0.0f; + bottom = 0.0f; + left = 0.0f; - int blurAndSpread = shadow->blur() + shadow->spread(); + float blurAndSpread = shadow->blur() + shadow->spread(); top = min(top, shadow->y() - blurAndSpread); right = max(right, shadow->x() + blurAndSpread); @@ -178,21 +178,14 @@ void SVGRenderStyle::inflateForShadow(FloatRect& repaintRect) const if (!svgShadow) return; - int shadowTop; - int shadowRight; - int shadowBottom; - int shadowLeft; + float shadowTop; + float shadowRight; + float shadowBottom; + float shadowLeft; getSVGShadowExtent(svgShadow, shadowTop, shadowRight, shadowBottom, shadowLeft); - int overflowLeft = repaintRect.x() + shadowLeft; - int overflowRight = repaintRect.right() + shadowRight; - int overflowTop = repaintRect.y() + shadowTop; - int overflowBottom = repaintRect.bottom() + shadowBottom; - - repaintRect.setX(overflowLeft); - repaintRect.setY(overflowTop); - repaintRect.setWidth(overflowRight - overflowLeft); - repaintRect.setHeight(overflowBottom - overflowTop); + repaintRect.move(shadowLeft, shadowTop); + repaintRect.setSize(repaintRect.size() + FloatSize(shadowRight - shadowLeft, shadowBottom - shadowTop)); } } diff --git a/WebCore/rendering/style/SVGRenderStyle.h b/WebCore/rendering/style/SVGRenderStyle.h index 3d6a7da..b0bef61 100644 --- a/WebCore/rendering/style/SVGRenderStyle.h +++ b/WebCore/rendering/style/SVGRenderStyle.h @@ -58,6 +58,7 @@ public: SVG_RS_DEFINE_ATTRIBUTE(EAlignmentBaseline, AlignmentBaseline, alignmentBaseline, AB_AUTO) SVG_RS_DEFINE_ATTRIBUTE(EDominantBaseline, DominantBaseline, dominantBaseline, DB_AUTO) SVG_RS_DEFINE_ATTRIBUTE(EBaselineShift, BaselineShift, baselineShift, BS_BASELINE) + SVG_RS_DEFINE_ATTRIBUTE(EVectorEffect, VectorEffect, vectorEffect, VE_NONE) SVG_RS_DEFINE_ATTRIBUTE_INHERITED(LineCap, CapStyle, capStyle, ButtCap) SVG_RS_DEFINE_ATTRIBUTE_INHERITED(WindRule, ClipRule, clipRule, RULE_NONZERO) @@ -108,6 +109,9 @@ public: SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, inheritedResources, markerEnd, MarkerEndResource, markerEndResource, String()) // convenience + bool hasClipper() const { return !clipperResource().isEmpty(); } + bool hasMasker() const { return !maskerResource().isEmpty(); } + bool hasFilter() const { return !filterResource().isEmpty(); } bool hasMarkers() const { return !markerStartResource().isEmpty() || !markerMidResource().isEmpty() || !markerEndResource().isEmpty(); } bool hasStroke() const { return strokePaint()->paintType() != SVGPaint::SVG_PAINTTYPE_NONE; } bool hasFill() const { return fillPaint()->paintType() != SVGPaint::SVG_PAINTTYPE_NONE; } @@ -165,7 +169,8 @@ protected: unsigned _alignmentBaseline : 4; // EAlignmentBaseline unsigned _dominantBaseline : 4; // EDominantBaseline unsigned _baselineShift : 2; // EBaselineShift - // 22 bits unused + unsigned _vectorEffect: 1; // EVectorEffect + // 21 bits unused } f; uint32_t _niflags; }; @@ -210,6 +215,7 @@ private: svg_noninherited_flags.f._alignmentBaseline = initialAlignmentBaseline(); svg_noninherited_flags.f._dominantBaseline = initialDominantBaseline(); svg_noninherited_flags.f._baselineShift = initialBaselineShift(); + svg_noninherited_flags.f._vectorEffect = initialVectorEffect(); } }; diff --git a/WebCore/rendering/style/SVGRenderStyleDefs.h b/WebCore/rendering/style/SVGRenderStyleDefs.h index e0354e6..207cefa 100644 --- a/WebCore/rendering/style/SVGRenderStyleDefs.h +++ b/WebCore/rendering/style/SVGRenderStyleDefs.h @@ -121,6 +121,11 @@ namespace WebCore { DB_IDEOGRAPHIC, DB_ALPHABETIC, DB_HANGING, DB_MATHEMATICAL, DB_CENTRAL, DB_MIDDLE, DB_TEXT_AFTER_EDGE, DB_TEXT_BEFORE_EDGE }; + + enum EVectorEffect { + VE_NONE, + VE_NON_SCALING_STROKE + }; class CSSValue; class CSSValueList; |