diff options
Diffstat (limited to 'WebCore/rendering')
90 files changed, 1388 insertions, 984 deletions
diff --git a/WebCore/rendering/AutoTableLayout.cpp b/WebCore/rendering/AutoTableLayout.cpp index ea8b416..d9233a2 100644 --- a/WebCore/rendering/AutoTableLayout.cpp +++ b/WebCore/rendering/AutoTableLayout.cpp @@ -140,7 +140,7 @@ void AutoTableLayout::recalcColumn(int effCol) // Nav/IE weirdness if (l.width.isFixed()) { - if (m_table->style()->htmlHacks() && l.maxWidth > l.width.value() && fixedContributor != maxContributor) { + if (m_table->document()->inQuirksMode() && l.maxWidth > l.width.value() && fixedContributor != maxContributor) { l.width = Length(); fixedContributor = 0; } diff --git a/WebCore/rendering/FixedTableLayout.cpp b/WebCore/rendering/FixedTableLayout.cpp index 4d6b88c..b5ff971 100644 --- a/WebCore/rendering/FixedTableLayout.cpp +++ b/WebCore/rendering/FixedTableLayout.cpp @@ -223,7 +223,7 @@ void FixedTableLayout::calcPrefWidths(int& minWidth, int& maxWidth) // In this example, the two inner tables should be as large as the outer table. // We can achieve this effect by making the maxwidth of fixed tables with percentage // widths be infinite. - if (m_table->style()->htmlHacks() && m_table->style()->width().isPercent() + if (m_table->document()->inQuirksMode() && m_table->style()->width().isPercent() && maxWidth < TABLE_MAX_WIDTH) maxWidth = TABLE_MAX_WIDTH; } diff --git a/WebCore/rendering/InlineFlowBox.cpp b/WebCore/rendering/InlineFlowBox.cpp index dfe7561..a71b796 100644 --- a/WebCore/rendering/InlineFlowBox.cpp +++ b/WebCore/rendering/InlineFlowBox.cpp @@ -761,8 +761,8 @@ void InlineFlowBox::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty) int h = height(); // Constrain our background/border painting to the line top and bottom if necessary. - bool strictMode = renderer()->document()->inStrictMode(); - if (!hasTextChildren() && !strictMode) { + bool noQuirksMode = renderer()->document()->inNoQuirksMode(); + if (!hasTextChildren() && !noQuirksMode) { RootInlineBox* rootBox = root(); int bottom = min(rootBox->lineBottom(), y + h); y = max(rootBox->lineTop(), y); @@ -837,8 +837,8 @@ void InlineFlowBox::paintMask(PaintInfo& paintInfo, int tx, int ty) int h = height(); // Constrain our background/border painting to the line top and bottom if necessary. - bool strictMode = renderer()->document()->inStrictMode(); - if (!hasTextChildren() && !strictMode) { + bool noQuirksMode = renderer()->document()->inNoQuirksMode(); + if (!hasTextChildren() && !noQuirksMode) { RootInlineBox* rootBox = root(); int bottom = min(rootBox->lineBottom(), y + h); y = max(rootBox->lineTop(), y); @@ -922,7 +922,7 @@ void InlineFlowBox::paintTextDecorations(PaintInfo& paintInfo, int tx, int ty, b { // Paint text decorations like underlines/overlines. We only do this if we aren't in quirks mode (i.e., in // almost-strict mode or strict mode). - if (renderer()->style()->htmlHacks() || !paintInfo.shouldPaintWithinRoot(renderer()) || + if (renderer()->document()->inQuirksMode() || !paintInfo.shouldPaintWithinRoot(renderer()) || renderer()->style()->visibility() != VISIBLE) return; diff --git a/WebCore/rendering/InlineTextBox.cpp b/WebCore/rendering/InlineTextBox.cpp index cb4fdb8..c74fe1e 100644 --- a/WebCore/rendering/InlineTextBox.cpp +++ b/WebCore/rendering/InlineTextBox.cpp @@ -547,7 +547,7 @@ void InlineTextBox::paint(PaintInfo& paintInfo, int tx, int ty) } // Paint decorations - if (d != TDNONE && paintInfo.phase != PaintPhaseSelection && styleToUse->htmlHacks()) { + if (d != TDNONE && paintInfo.phase != PaintPhaseSelection && renderer()->document()->inQuirksMode()) { context->setStrokeColor(styleToUse->visitedDependentColor(CSSPropertyColor), styleToUse->colorSpace()); paintDecoration(context, tx, ty, d, textShadow); } @@ -768,6 +768,21 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, int tx, int ty, in context->clearShadow(); } +static GraphicsContext::TextCheckingLineStyle textCheckingLineStyleForMarkerType(DocumentMarker::MarkerType markerType) +{ + switch (markerType) { + case DocumentMarker::Spelling: + return GraphicsContext::TextCheckingSpellingLineStyle; + case DocumentMarker::Grammar: + return GraphicsContext::TextCheckingGrammarLineStyle; + case DocumentMarker::Replacement: + return GraphicsContext::TextCheckingReplacementLineStyle; + default: + ASSERT_NOT_REACHED(); + return GraphicsContext::TextCheckingSpellingLineStyle; + } +} + void InlineTextBox::paintSpellingOrGrammarMarker(GraphicsContext* pt, int tx, int ty, const DocumentMarker& marker, RenderStyle* style, const Font& font, bool grammar) { // Never print spelling/grammar markers (5327887) @@ -831,7 +846,7 @@ void InlineTextBox::paintSpellingOrGrammarMarker(GraphicsContext* pt, int tx, in // In larger fonts, though, place the underline up near the baseline to prevent a big gap. underlineOffset = baseline + 2; } - pt->drawLineForMisspellingOrBadGrammar(IntPoint(tx + m_x + start, ty + m_y + underlineOffset), width, grammar); + pt->drawLineForTextChecking(IntPoint(tx + m_x + start, ty + m_y + underlineOffset), width, textCheckingLineStyleForMarkerType(marker.type)); } void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, int tx, int ty, const DocumentMarker& marker, RenderStyle* style, const Font& font) @@ -898,10 +913,10 @@ void InlineTextBox::paintDocumentMarkers(GraphicsContext* pt, int tx, int ty, Re case DocumentMarker::Grammar: case DocumentMarker::Spelling: case DocumentMarker::Replacement: + case DocumentMarker::RejectedCorrection: if (background) continue; break; - case DocumentMarker::TextMatch: if (!background) continue; @@ -933,6 +948,9 @@ void InlineTextBox::paintDocumentMarkers(GraphicsContext* pt, int tx, int ty, Re break; case DocumentMarker::Replacement: computeRectForReplacementMarker(tx, ty, marker, style, font); + paintSpellingOrGrammarMarker(pt, tx, ty, marker, style, font, false); + break; + case DocumentMarker::RejectedCorrection: break; default: ASSERT_NOT_REACHED(); diff --git a/WebCore/rendering/MediaControlElements.cpp b/WebCore/rendering/MediaControlElements.cpp index 3fb712f..aaeb3e2 100644 --- a/WebCore/rendering/MediaControlElements.cpp +++ b/WebCore/rendering/MediaControlElements.cpp @@ -42,6 +42,7 @@ #include "RenderMedia.h" #include "RenderSlider.h" #include "RenderTheme.h" +#include "Settings.h" namespace WebCore { @@ -780,7 +781,20 @@ PassRefPtr<MediaControlFullscreenButtonElement> MediaControlFullscreenButtonElem void MediaControlFullscreenButtonElement::defaultEventHandler(Event* event) { if (event->type() == eventNames().clickEvent) { - mediaElement()->enterFullscreen(); +#if ENABLE(FULLSCREEN_API) + // Only use the new full screen API if the fullScreenEnabled setting has + // been explicitly enabled. Otherwise, use the old fullscreen API. This + // allows apps which embed a WebView to retain the existing full screen + // video implementation without requiring them to implement their own full + // screen behavior. + if (document()->settings() && document()->settings()->fullScreenEnabled()) { + if (document()->webkitFullScreen() && document()->webkitCurrentFullScreenElement() == mediaElement()) + document()->webkitCancelFullScreen(); + else + mediaElement()->webkitRequestFullScreen(0); + } else +#endif + mediaElement()->enterFullscreen(); event->setDefaultHandled(); } HTMLInputElement::defaultEventHandler(event); diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp index 28d7914..d66336d 100644 --- a/WebCore/rendering/RenderBlock.cpp +++ b/WebCore/rendering/RenderBlock.cpp @@ -1042,7 +1042,7 @@ bool RenderBlock::isSelfCollapsingBlock() const return false; bool hasAutoHeight = style()->height().isAuto(); - if (style()->height().isPercent() && !style()->htmlHacks()) { + if (style()->height().isPercent() && !document()->inQuirksMode()) { hasAutoHeight = true; for (RenderBlock* cb = containingBlock(); !cb->isRenderView(); cb = cb->containingBlock()) { if (cb->style()->height().isFixed() || cb->isTableCell()) @@ -1478,7 +1478,7 @@ int RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo) // This child is collapsing with the top of the // block. If it has larger margin values, then we need to update // our own maximal values. - if (!style()->htmlHacks() || !marginInfo.quirkContainer() || !topQuirk) + if (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !topQuirk) setMaxTopMargins(max(posTop, maxTopPosMargin()), max(negTop, maxTopNegMargin())); // The minute any of the margins involved isn't a quirk, don't @@ -1530,7 +1530,7 @@ int RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo) } else if (!marginInfo.atTopOfBlock() || (!marginInfo.canCollapseTopWithChildren() - && (!style()->htmlHacks() || !marginInfo.quirkContainer() || !marginInfo.topQuirk()))) { + && (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !marginInfo.topQuirk()))) { // We're collapsing with a previous sibling's margins and not // with the top of the block. setHeight(height() + max(marginInfo.posMargin(), posTop) - max(marginInfo.negMargin(), negTop)); @@ -1683,7 +1683,7 @@ void RenderBlock::handleBottomOfBlock(int top, int bottom, MarginInfo& marginInf // If we can't collapse with children then go ahead and add in the bottom margin. if (!marginInfo.canCollapseWithBottom() && !marginInfo.canCollapseWithTop() - && (!style()->htmlHacks() || !marginInfo.quirkContainer() || !marginInfo.bottomQuirk())) + && (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !marginInfo.bottomQuirk())) setHeight(height() + marginInfo.margin()); // Now add in our bottom border/padding. @@ -2120,8 +2120,12 @@ void RenderBlock::paintChildren(PaintInfo& paintInfo, int tx, int ty) PaintInfo info(paintInfo); info.phase = newPhase; info.updatePaintingRootForChildren(this); + + RenderView* renderView = view(); + bool usePrintRect = !renderView->printRect().isEmpty() && !document()->settings()->paginateDuringLayoutEnabled(); + bool checkPageBreaks = document()->paginated() && !document()->settings()->paginateDuringLayoutEnabled(); - bool checkColumnBreaks = !checkPageBreaks && !view()->printRect().isEmpty() && !document()->settings()->paginateDuringLayoutEnabled(); + bool checkColumnBreaks = !checkPageBreaks && usePrintRect; for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) { // Check for page-break-before: always, and if it's set, break and bail. @@ -2133,6 +2137,17 @@ void RenderBlock::paintChildren(PaintInfo& paintInfo, int tx, int ty) return; } + if (!child->isFloating() && child->isReplaced() && usePrintRect && child->height() <= renderView->printRect().height()) { + // Paginate block-level replaced elements. + if (ty + child->y() + child->height() > renderView->printRect().bottom()) { + if (ty + child->y() < renderView->truncatedAt()) + renderView->setBestTruncatedAt(ty + child->y(), child); + // If we were able to truncate, don't paint. + if (ty + child->y() >= renderView->truncatedAt()) + break; + } + } + if (!child->hasSelfPaintingLayer() && !child->isFloating()) child->paint(info, tx, ty); @@ -3529,7 +3544,7 @@ void RenderBlock::clearFloats() int RenderBlock::addOverhangingFloats(RenderBlock* child, int xoff, int yoff, bool makeChildPaintOtherFloats) { // Prevent floats from being added to the canvas by the root element, e.g., <html>. - if (child->hasOverflowClip() || !child->containsFloats() || child->isRoot()) + if (child->hasOverflowClip() || !child->containsFloats() || child->isRoot() || child->hasColumns()) return 0; int lowestFloatBottom = 0; @@ -4593,7 +4608,7 @@ void RenderBlock::calcInlinePrefWidths() // Firefox and Opera will allow a table cell to grow to fit an image inside it under // very specific cirucumstances (in order to match common WinIE renderings). // Not supporting the quirk has caused us to mis-render some real sites. (See Bugzilla 10517.) - bool allowImagesToBreak = !style()->htmlHacks() || !isTableCell() || !style()->width().isIntrinsicOrAuto(); + bool allowImagesToBreak = !document()->inQuirksMode() || !isTableCell() || !style()->width().isIntrinsicOrAuto(); bool autoWrap, oldAutoWrap; autoWrap = oldAutoWrap = style()->autoWrap(); @@ -4922,7 +4937,7 @@ void RenderBlock::calcBlockPrefWidths() // of 100px because of the table. // We can achieve this effect by making the maxwidth of blocks that contain tables // with percentage widths be infinite (as long as they are not inside a table cell). - if (style()->htmlHacks() && child->style()->width().isPercent() && + if (document()->inQuirksMode() && child->style()->width().isPercent() && !isTableCell() && child->isTable() && m_maxPrefWidth < BLOCK_MAX_WIDTH) { RenderBlock* cb = containingBlock(); while (!cb->isRenderView() && !cb->isTableCell()) diff --git a/WebCore/rendering/RenderBlockLineLayout.cpp b/WebCore/rendering/RenderBlockLineLayout.cpp index 7cb1597..d703fb2 100644 --- a/WebCore/rendering/RenderBlockLineLayout.cpp +++ b/WebCore/rendering/RenderBlockLineLayout.cpp @@ -194,7 +194,7 @@ static inline InlineBox* createInlineBoxForRenderer(RenderObject* obj, bool isRo // We only treat a box as text for a <br> if we are on a line by ourself or in strict mode // (Note the use of strict mode. In "almost strict" mode, we don't treat the box for <br> as text.) if (obj->isBR()) - textBox->setIsText(isOnlyRun || obj->document()->inStrictMode()); + textBox->setIsText(isOnlyRun || obj->document()->inNoQuirksMode()); return textBox; } @@ -1518,7 +1518,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool // Firefox and Opera will allow a table cell to grow to fit an image inside it under // very specific circumstances (in order to match common WinIE renderings). // Not supporting the quirk has caused us to mis-render some real sites. (See Bugzilla 10517.) - bool allowImagesToBreak = !style()->htmlHacks() || !isTableCell() || !style()->width().isIntrinsicOrAuto(); + bool allowImagesToBreak = !document()->inQuirksMode() || !isTableCell() || !style()->width().isIntrinsicOrAuto(); EWhiteSpace currWS = style()->whiteSpace(); EWhiteSpace lastWS = currWS; diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp index d614081..e107c4f 100644 --- a/WebCore/rendering/RenderBox.cpp +++ b/WebCore/rendering/RenderBox.cpp @@ -1619,7 +1619,7 @@ int RenderBox::calcPercentageHeight(const Length& height) int result = -1; bool skippedAutoHeightContainingBlock = false; RenderBlock* cb = containingBlock(); - if (style()->htmlHacks()) { + if (document()->inQuirksMode()) { // In quirks mode, blocks with auto height are skipped, and we keep looking for an enclosing // block that may have a specified height and then use it. In strict mode, this violates the // specification, which states that percentage heights just revert to auto if the containing @@ -1668,7 +1668,7 @@ int RenderBox::calcPercentageHeight(const Length& height) result = cb->calcPercentageHeight(cb->style()->height()); if (result != -1) result = cb->calcContentBoxHeight(result); - } else if (cb->isRenderView() || (cb->isBody() && style()->htmlHacks()) || isPositionedWithSpecifiedHeight) { + } else if (cb->isRenderView() || (cb->isBody() && document()->inQuirksMode()) || isPositionedWithSpecifiedHeight) { // Don't allow this to affect the block' height() member variable, since this // can get called while the block is still laying out its kids. int oldHeight = cb->height(); @@ -1901,7 +1901,7 @@ void RenderBox::calcAbsoluteHorizontal() // To match WinIE, in quirks mode use the parent's 'direction' property // instead of the the container block's. - TextDirection containerDirection = (style()->htmlHacks()) ? parent()->style()->direction() : containerBlock->style()->direction(); + TextDirection containerDirection = (document()->inQuirksMode()) ? parent()->style()->direction() : containerBlock->style()->direction(); const int bordersPlusPadding = borderAndPaddingWidth(); const Length marginLeft = style()->marginLeft(); @@ -2437,7 +2437,7 @@ void RenderBox::calcAbsoluteHorizontalReplaced() // To match WinIE, in quirks mode use the parent's 'direction' property // instead of the the container block's. - TextDirection containerDirection = (style()->htmlHacks()) ? parent()->style()->direction() : containerBlock->style()->direction(); + TextDirection containerDirection = (document()->inQuirksMode()) ? parent()->style()->direction() : containerBlock->style()->direction(); // Variables to solve. Length left = style()->left(); diff --git a/WebCore/rendering/RenderBox.h b/WebCore/rendering/RenderBox.h index e02f77a..8f1e9c3 100644 --- a/WebCore/rendering/RenderBox.h +++ b/WebCore/rendering/RenderBox.h @@ -217,7 +217,7 @@ public: bool stretchesToViewHeight() const { - return style()->htmlHacks() && style()->height().isAuto() && !isFloatingOrPositioned() && (isRoot() || isBody()); + return document()->inQuirksMode() && style()->height().isAuto() && !isFloatingOrPositioned() && (isRoot() || isBody()); } virtual IntSize intrinsicSize() const { return IntSize(); } @@ -246,7 +246,7 @@ public: virtual int verticalScrollbarWidth() const; int horizontalScrollbarHeight() const; - virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1.0f, Node** stopNode = 0); + virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1, Node** stopNode = 0); bool canBeScrolledAndHasScrollableArea() const; virtual bool canBeProgramaticallyScrolled(bool) const; virtual void autoscroll(); diff --git a/WebCore/rendering/RenderBoxModelObject.cpp b/WebCore/rendering/RenderBoxModelObject.cpp index 78618d1..0fbc9f2 100644 --- a/WebCore/rendering/RenderBoxModelObject.cpp +++ b/WebCore/rendering/RenderBoxModelObject.cpp @@ -337,10 +337,25 @@ int RenderBoxModelObject::relativePositionOffsetX() const int RenderBoxModelObject::relativePositionOffsetY() const { - if (!style()->top().isAuto()) - return style()->top().calcValue(containingBlock()->availableHeight()); - else if (!style()->bottom().isAuto()) - return -style()->bottom().calcValue(containingBlock()->availableHeight()); + RenderBlock* containingBlock = this->containingBlock(); + + // If the containing block of a relatively positioned element does not + // specify a height, a percentage top or bottom offset should be resolved as + // auto. An exception to this is if the containing block has the WinIE quirk + // where <html> and <body> assume the size of the viewport. In this case, + // calculate the percent offset based on this height. + // See <https://bugs.webkit.org/show_bug.cgi?id=26396>. + if (!style()->top().isAuto() + && (!containingBlock->style()->height().isAuto() + || !style()->top().isPercent() + || containingBlock->stretchesToViewHeight())) + return style()->top().calcValue(containingBlock->availableHeight()); + + if (!style()->bottom().isAuto() + && (!containingBlock->style()->height().isAuto() + || !style()->bottom().isPercent() + || containingBlock->stretchesToViewHeight())) + return -style()->bottom().calcValue(containingBlock->availableHeight()); return 0; } diff --git a/WebCore/rendering/RenderEmbeddedObject.cpp b/WebCore/rendering/RenderEmbeddedObject.cpp index 55b230b..b1b253a 100644 --- a/WebCore/rendering/RenderEmbeddedObject.cpp +++ b/WebCore/rendering/RenderEmbeddedObject.cpp @@ -102,6 +102,7 @@ bool RenderEmbeddedObject::allowsAcceleratedCompositing() const } #endif +// FIXME: This belongs in HTMLPluginElement.cpp to be shared by HTMLObjectElement and HTMLEmbedElement. static bool isURLAllowed(Document* doc, const String& url) { if (doc->frame()->page()->frameCount() >= Page::maxNumberOfFrames) @@ -123,6 +124,7 @@ static bool isURLAllowed(Document* doc, const String& url) typedef HashMap<String, String, CaseFoldingHash> ClassIdToTypeMap; +// FIXME: This belongs in HTMLObjectElement.cpp static ClassIdToTypeMap* createClassIdToTypeMap() { ClassIdToTypeMap* map = new ClassIdToTypeMap; @@ -135,6 +137,7 @@ static ClassIdToTypeMap* createClassIdToTypeMap() return map; } +// FIXME: This belongs in HTMLObjectElement.cpp static String serviceTypeForClassId(const String& classId) { // Return early if classId is empty (since we won't do anything below). @@ -146,6 +149,7 @@ static String serviceTypeForClassId(const String& classId) return map->get(classId); } +// FIXME: This belongs in HTMLObjectElement.cpp static void mapDataParamToSrc(Vector<String>* paramNames, Vector<String>* paramValues) { // Some plugins don't understand the "data" attribute of the OBJECT tag (i.e. Real and WMP @@ -164,190 +168,205 @@ static void mapDataParamToSrc(Vector<String>* paramNames, Vector<String>* paramV } } -void RenderEmbeddedObject::updateWidget(bool onlyCreateNonNetscapePlugins) +// FIXME: This belongs in some loader header? +static bool isNetscapePlugin(Frame* frame, const String& url, const String& serviceType) { - if (!m_replacementText.isNull() || !node()) // Check the node in case destroy() has been called. - return; - - String url; - String serviceType; - Vector<String> paramNames; - Vector<String> paramValues; - Frame* frame = frameView()->frame(); - - // The calls to SubframeLoader::requestObject within this function can result in a plug-in being initialized. - // This can run cause arbitrary JavaScript to run and may result in this RenderObject being detached from - // the render tree and destroyed, causing a crash like <rdar://problem/6954546>. By extending our lifetime - // artifically to ensure that we remain alive for the duration of plug-in initialization. - RenderWidgetProtector protector(this); + KURL completedURL; + if (!url.isEmpty()) + completedURL = frame->loader()->completeURL(url); - if (node()->hasTagName(objectTag)) { - HTMLObjectElement* objectElement = static_cast<HTMLObjectElement*>(node()); + if (frame->loader()->client()->objectContentType(completedURL, serviceType) == ObjectContentNetscapePlugin) + return true; + return false; +} - objectElement->setNeedWidgetUpdate(false); - if (!objectElement->isFinishedParsingChildren()) - return; +// FIXME: This belongs on HTMLObjectElement. +static bool hasFallbackContent(HTMLObjectElement* objectElement) +{ + for (Node* child = objectElement->firstChild(); child; child = child->nextSibling()) { + if ((!child->isTextNode() && !child->hasTagName(paramTag)) // Discount <param> + || (child->isTextNode() && !static_cast<Text*>(child)->containsOnlyWhitespace())) + return true; + } + return false; +} - // Check for a child EMBED tag. - HTMLEmbedElement* embed = 0; - for (Node* child = objectElement->firstChild(); child; ) { - if (child->hasTagName(embedTag)) { - embed = static_cast<HTMLEmbedElement*>(child); - break; +// FIXME: This belongs on HTMLObjectElement. +static void parametersFromObject(HTMLObjectElement* objectElement, Vector<String>& paramNames, Vector<String>& paramValues, String& url, String& serviceType) +{ + HashSet<StringImpl*, CaseFoldingHash> uniqueParamNames; + + // Scan the PARAM children and store their name/value pairs. + // Get the URL and type from the params if we don't already have them. + Node* child = objectElement->firstChild(); + while (child) { + if (child->hasTagName(paramTag)) { + HTMLParamElement* p = static_cast<HTMLParamElement*>(child); + String name = p->name(); + if (url.isEmpty() && (equalIgnoringCase(name, "src") || equalIgnoringCase(name, "movie") || equalIgnoringCase(name, "code") || equalIgnoringCase(name, "url"))) + url = deprecatedParseURL(p->value()); + // FIXME: serviceType calculation does not belong in this function. + if (serviceType.isEmpty() && equalIgnoringCase(name, "type")) { + serviceType = p->value(); + size_t pos = serviceType.find(";"); + if (pos != notFound) + serviceType = serviceType.left(pos); } - - if (child->hasTagName(objectTag)) - child = child->nextSibling(); // Don't descend into nested OBJECT tags - else - child = child->traverseNextNode(objectElement); // Otherwise descend (EMBEDs may be inside COMMENT tags) - } - - // Use the attributes from the EMBED tag instead of the OBJECT tag including WIDTH and HEIGHT. - HTMLElement* embedOrObject; - if (embed) { - embedOrObject = embed; - url = embed->url(); - serviceType = embed->serviceType(); - } else - embedOrObject = objectElement; - - // If there was no URL or type defined in EMBED, try the OBJECT tag. - if (url.isEmpty()) - url = objectElement->url(); - if (serviceType.isEmpty()) - serviceType = objectElement->serviceType(); - - HashSet<StringImpl*, CaseFoldingHash> uniqueParamNames; - - // Scan the PARAM children. - // Get the URL and type from the params if we don't already have them. - // Get the attributes from the params if there is no EMBED tag. - Node* child = objectElement->firstChild(); - while (child && (url.isEmpty() || serviceType.isEmpty() || !embed)) { - if (child->hasTagName(paramTag)) { - HTMLParamElement* p = static_cast<HTMLParamElement*>(child); - String name = p->name(); - if (url.isEmpty() && (equalIgnoringCase(name, "src") || equalIgnoringCase(name, "movie") || equalIgnoringCase(name, "code") || equalIgnoringCase(name, "url"))) - url = p->value(); - if (serviceType.isEmpty() && equalIgnoringCase(name, "type")) { - serviceType = p->value(); - size_t pos = serviceType.find(";"); - if (pos != notFound) - serviceType = serviceType.left(pos); - } - if (!embed && !name.isEmpty()) { - uniqueParamNames.add(name.impl()); - paramNames.append(p->name()); - paramValues.append(p->value()); - } + if (!name.isEmpty()) { + uniqueParamNames.add(name.impl()); + paramNames.append(p->name()); + paramValues.append(p->value()); } - child = child->nextSibling(); } + child = child->nextSibling(); + } - // When OBJECT is used for an applet via Sun's Java plugin, the CODEBASE attribute in the tag - // points to the Java plugin itself (an ActiveX component) while the actual applet CODEBASE is - // in a PARAM tag. See <http://java.sun.com/products/plugin/1.2/docs/tags.html>. This means - // we have to explicitly suppress the tag's CODEBASE attribute if there is none in a PARAM, - // else our Java plugin will misinterpret it. [4004531] - String codebase; - if (!embed && MIMETypeRegistry::isJavaAppletMIMEType(serviceType)) { - codebase = "codebase"; - uniqueParamNames.add(codebase.impl()); // pretend we found it in a PARAM already - } - - // Turn the attributes of either the EMBED tag or OBJECT tag into arrays, but don't override PARAM values. - NamedNodeMap* attributes = embedOrObject->attributes(); - if (attributes) { - for (unsigned i = 0; i < attributes->length(); ++i) { - Attribute* it = attributes->attributeItem(i); - const AtomicString& name = it->name().localName(); - if (embed || !uniqueParamNames.contains(name.impl())) { - paramNames.append(name.string()); - paramValues.append(it->value().string()); - } + // When OBJECT is used for an applet via Sun's Java plugin, the CODEBASE attribute in the tag + // points to the Java plugin itself (an ActiveX component) while the actual applet CODEBASE is + // in a PARAM tag. See <http://java.sun.com/products/plugin/1.2/docs/tags.html>. This means + // we have to explicitly suppress the tag's CODEBASE attribute if there is none in a PARAM, + // else our Java plugin will misinterpret it. [4004531] + String codebase; + if (MIMETypeRegistry::isJavaAppletMIMEType(serviceType)) { + codebase = "codebase"; + uniqueParamNames.add(codebase.impl()); // pretend we found it in a PARAM already + } + + // Turn the attributes of the <object> element into arrays, but don't override <param> values. + NamedNodeMap* attributes = objectElement->attributes(); + if (attributes) { + for (unsigned i = 0; i < attributes->length(); ++i) { + Attribute* it = attributes->attributeItem(i); + const AtomicString& name = it->name().localName(); + if (!uniqueParamNames.contains(name.impl())) { + paramNames.append(name.string()); + paramValues.append(it->value().string()); } } + } - mapDataParamToSrc(¶mNames, ¶mValues); + mapDataParamToSrc(¶mNames, ¶mValues); - // If we still don't have a type, try to map from a specific CLASSID to a type. - if (serviceType.isEmpty()) - serviceType = serviceTypeForClassId(objectElement->classId()); + // If we still don't have a type, try to map from a specific CLASSID to a type. + if (serviceType.isEmpty()) + serviceType = serviceTypeForClassId(objectElement->classId()); +} - if (!isURLAllowed(document(), url)) - return; +// FIXME: This belongs on HTMLObjectElement, HTMLPluginElement or HTMLFrameOwnerElement. +static void updateWidgetForObjectElement(HTMLObjectElement* objectElement, bool onlyCreateNonNetscapePlugins) +{ + objectElement->setNeedsWidgetUpdate(false); + if (!objectElement->isFinishedParsingChildren()) + return; - // Find out if we support fallback content. - m_hasFallbackContent = false; - for (Node* child = objectElement->firstChild(); child && !m_hasFallbackContent; child = child->nextSibling()) { - if ((!child->isTextNode() && !child->hasTagName(embedTag) && !child->hasTagName(paramTag)) // Discount <embed> and <param> - || (child->isTextNode() && !static_cast<Text*>(child)->containsOnlyWhitespace())) - m_hasFallbackContent = true; - } + Frame* frame = objectElement->document()->frame(); + String url = objectElement->url(); + String serviceType = objectElement->serviceType(); - if (onlyCreateNonNetscapePlugins) { - KURL completedURL; - if (!url.isEmpty()) - completedURL = frame->loader()->completeURL(url); + Vector<String> paramNames; + Vector<String> paramValues; + parametersFromObject(objectElement, paramNames, paramValues, url, serviceType); - if (frame->loader()->client()->objectContentType(completedURL, serviceType) == ObjectContentNetscapePlugin) - return; - } + if (!isURLAllowed(objectElement->document(), url)) + return; - bool beforeLoadAllowedLoad = objectElement->dispatchBeforeLoadEvent(url); - - // beforeload events can modify the DOM, potentially causing - // RenderWidget::destroy() to be called. Ensure we haven't been - // destroyed before continuing. - if (!node()) - return; - - bool success = beforeLoadAllowedLoad && frame->loader()->subframeLoader()->requestObject(this, url, objectElement->getAttribute(nameAttr), serviceType, paramNames, paramValues); - - if (!success && m_hasFallbackContent) - objectElement->renderFallbackContent(); + bool fallbackContent = hasFallbackContent(objectElement); + objectElement->renderEmbeddedObject()->setHasFallbackContent(fallbackContent); - } else if (node()->hasTagName(embedTag)) { - HTMLEmbedElement* embedElement = static_cast<HTMLEmbedElement*>(node()); - embedElement->setNeedWidgetUpdate(false); - url = embedElement->url(); - serviceType = embedElement->serviceType(); + if (onlyCreateNonNetscapePlugins && isNetscapePlugin(frame, url, serviceType)) + return; - if (url.isEmpty() && serviceType.isEmpty()) - return; - if (!isURLAllowed(document(), url)) - return; + bool beforeLoadAllowedLoad = objectElement->dispatchBeforeLoadEvent(url); - // add all attributes set on the embed object - NamedNodeMap* attributes = embedElement->attributes(); - if (attributes) { - for (unsigned i = 0; i < attributes->length(); ++i) { - Attribute* it = attributes->attributeItem(i); - paramNames.append(it->name().localName().string()); - paramValues.append(it->value().string()); - } - } + // beforeload events can modify the DOM, potentially causing + // RenderWidget::destroy() to be called. Ensure we haven't been + // destroyed before continuing. + // FIXME: Should this render fallback content? + if (!objectElement->renderer()) + return; + + bool success = beforeLoadAllowedLoad && frame->loader()->subframeLoader()->requestObject(objectElement, url, objectElement->getAttribute(nameAttr), serviceType, paramNames, paramValues); - if (onlyCreateNonNetscapePlugins) { - KURL completedURL; - if (!url.isEmpty()) - completedURL = frame->loader()->completeURL(url); + if (!success && fallbackContent) + objectElement->renderFallbackContent(); +} - if (frame->loader()->client()->objectContentType(completedURL, serviceType) == ObjectContentNetscapePlugin) - return; +// FIXME: This belongs on HTMLEmbedElement. +static void parametersFromEmbed(HTMLEmbedElement* embedElement, Vector<String>& paramNames, Vector<String>& paramValues) +{ + NamedNodeMap* attributes = embedElement->attributes(); + if (attributes) { + for (unsigned i = 0; i < attributes->length(); ++i) { + Attribute* it = attributes->attributeItem(i); + paramNames.append(it->name().localName().string()); + paramValues.append(it->value().string()); } + } +} + +// FIXME: This belongs on HTMLEmbedElement, HTMLPluginElement or HTMLFrameOwnerElement. +static void updateWidgetForEmbedElement(HTMLEmbedElement* embedElement, bool onlyCreateNonNetscapePlugins) +{ + Frame* frame = embedElement->document()->frame(); + String url = embedElement->url(); + String serviceType = embedElement->serviceType(); - if (embedElement->dispatchBeforeLoadEvent(url)) - frame->loader()->subframeLoader()->requestObject(this, url, embedElement->getAttribute(nameAttr), serviceType, paramNames, paramValues); + embedElement->setNeedsWidgetUpdate(false); + + if (url.isEmpty() && serviceType.isEmpty()) + return; + if (!isURLAllowed(embedElement->document(), url)) + return; + + Vector<String> paramNames; + Vector<String> paramValues; + parametersFromEmbed(embedElement, paramNames, paramValues); + + if (onlyCreateNonNetscapePlugins && isNetscapePlugin(frame, url, serviceType)) + return; + + if (embedElement->dispatchBeforeLoadEvent(url)) { + // FIXME: beforeLoad could have detached the renderer! Just like in the <object> case above. + frame->loader()->subframeLoader()->requestObject(embedElement, url, embedElement->getAttribute(nameAttr), serviceType, paramNames, paramValues); + } +} + +#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) +// FIXME: This belongs on HTMLMediaElement. +static void updateWidgetForMediaElement(HTMLMediaElement* mediaElement, bool ignored) +{ + Vector<String> paramNames; + Vector<String> paramValues; + KURL kurl; + + mediaElement->getPluginProxyParams(kurl, paramNames, paramValues); + mediaElement->setNeedWidgetUpdate(false); + frame->loader()->subframeLoader()->loadMediaPlayerProxyPlugin(mediaElement, kurl, paramNames, paramValues); +} +#endif + +void RenderEmbeddedObject::updateWidget(bool onlyCreateNonNetscapePlugins) +{ + if (!m_replacementText.isNull() || !node()) // Check the node in case destroy() has been called. + return; + + // The calls to SubframeLoader::requestObject within this function can result in a plug-in being initialized. + // This can run cause arbitrary JavaScript to run and may result in this RenderObject being detached from + // the render tree and destroyed, causing a crash like <rdar://problem/6954546>. By extending our lifetime + // artifically to ensure that we remain alive for the duration of plug-in initialization. + RenderWidgetProtector protector(this); + + if (node()->hasTagName(objectTag)) { + HTMLObjectElement* objectElement = static_cast<HTMLObjectElement*>(node()); + updateWidgetForObjectElement(objectElement, onlyCreateNonNetscapePlugins); + } else if (node()->hasTagName(embedTag)) { + HTMLEmbedElement* embedElement = static_cast<HTMLEmbedElement*>(node()); + updateWidgetForEmbedElement(embedElement, onlyCreateNonNetscapePlugins); } #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) else if (node()->hasTagName(videoTag) || node()->hasTagName(audioTag)) { HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(node()); - KURL kurl; - - mediaElement->getPluginProxyParams(kurl, paramNames, paramValues); - mediaElement->setNeedWidgetUpdate(false); - frame->loader()->subframeLoader()->loadMediaPlayerProxyPlugin(node(), kurl, paramNames, paramValues); + updateWidgetForMediaElement(mediaElement, onlyCreateNonNetscapePlugins); } #endif } diff --git a/WebCore/rendering/RenderEmbeddedObject.h b/WebCore/rendering/RenderEmbeddedObject.h index 0944094..6376f93 100644 --- a/WebCore/rendering/RenderEmbeddedObject.h +++ b/WebCore/rendering/RenderEmbeddedObject.h @@ -41,7 +41,9 @@ public: void setShowsCrashedPluginIndicator(); bool showsMissingPluginIndicator() const { return m_showsMissingPluginIndicator; } + // FIXME: This belongs on HTMLObjectElement. bool hasFallbackContent() const { return m_hasFallbackContent; } + void setHasFallbackContent(bool hasFallbackContent) { m_hasFallbackContent = hasFallbackContent; } void handleMissingPluginIndicatorEvent(Event*); @@ -68,7 +70,7 @@ private: bool getReplacementTextGeometry(int tx, int ty, FloatRect& contentRect, Path&, FloatRect& replacementTextRect, Font&, TextRun&, float& textWidth); String m_replacementText; - bool m_hasFallbackContent; + bool m_hasFallbackContent; // FIXME: This belongs on HTMLObjectElement. bool m_showsMissingPluginIndicator; bool m_missingPluginIndicatorIsPressed; bool m_mouseDownWasInMissingPluginIndicator; diff --git a/WebCore/rendering/RenderForeignObject.cpp b/WebCore/rendering/RenderForeignObject.cpp index 50c1a42..bfcb940 100644 --- a/WebCore/rendering/RenderForeignObject.cpp +++ b/WebCore/rendering/RenderForeignObject.cpp @@ -102,14 +102,20 @@ void RenderForeignObject::layout() LayoutRepainter repainter(*this, m_everHadLayout && checkForRepaintDuringLayout()); SVGForeignObjectElement* foreign = static_cast<SVGForeignObjectElement*>(node()); + bool updateCachedBoundariesInParents = false; if (m_needsTransformUpdate) { m_localTransform = foreign->animatedLocalTransform(); m_needsTransformUpdate = false; + updateCachedBoundariesInParents = true; } + FloatRect oldViewport = m_viewport; + // Cache viewport boundaries FloatPoint viewportLocation(foreign->x().value(foreign), foreign->y().value(foreign)); m_viewport = FloatRect(viewportLocation, FloatSize(foreign->width().value(foreign), foreign->height().value(foreign))); + if (!updateCachedBoundariesInParents) + updateCachedBoundariesInParents = oldViewport != m_viewport; // Set box origin to the foreignObject x/y translation, so positioned objects in XHTML content get correct // positions. A regular RenderBoxModelObject would pull this information from RenderStyle - in SVG those @@ -122,6 +128,10 @@ void RenderForeignObject::layout() RenderBlock::layout(); ASSERT(!needsLayout()); + // If our bounds changed, notify the parents. + if (updateCachedBoundariesInParents) + RenderSVGBlock::setNeedsBoundariesUpdate(); + // Invalidate all resources of this client if our layout changed. if (layoutChanged) SVGResourcesCache::clientLayoutChanged(this); diff --git a/WebCore/rendering/RenderImage.cpp b/WebCore/rendering/RenderImage.cpp index f34b691..316b1cf 100644 --- a/WebCore/rendering/RenderImage.cpp +++ b/WebCore/rendering/RenderImage.cpp @@ -61,7 +61,6 @@ using namespace HTMLNames; RenderImage::RenderImage(Node* node) : RenderReplaced(node, IntSize(0, 0)) - , m_cachedImage(0) { updateAltText(); @@ -70,22 +69,15 @@ RenderImage::RenderImage(Node* node) RenderImage::~RenderImage() { - if (m_cachedImage) - m_cachedImage->removeClient(this); + ASSERT(m_imageResource); + m_imageResource->shutdown(); } -void RenderImage::setCachedImage(CachedImage* newImage) +void RenderImage::setImageResource(PassOwnPtr<RenderImageResource> imageResource) { - if (m_cachedImage == newImage) - return; - if (m_cachedImage) - m_cachedImage->removeClient(this); - m_cachedImage = newImage; - if (m_cachedImage) { - m_cachedImage->addClient(this); - if (m_cachedImage->errorOccurred()) - imageChanged(m_cachedImage.get()); - } + ASSERT(!m_imageResource); + m_imageResource = imageResource; + m_imageResource->initialize(this); } // If we'll be displaying either alt text or an image, add some padding. @@ -139,22 +131,22 @@ void RenderImage::imageChanged(WrappedImagePtr newImage, const IntRect* rect) if (hasBoxDecorations() || hasMask()) RenderReplaced::imageChanged(newImage, rect); - - if (newImage != imagePtr() || !newImage) + + if (newImage != m_imageResource->imagePtr() || !newImage) return; bool imageSizeChanged = false; // Set image dimensions, taking into account the size of the alt text. - if (errorOccurred()) - imageSizeChanged = setImageSizeForAltText(m_cachedImage.get()); - + if (m_imageResource->errorOccurred()) + imageSizeChanged = setImageSizeForAltText(m_imageResource->cachedImage()); + bool shouldRepaint = true; // Image dimensions have been changed, see what needs to be done - if (imageSize(style()->effectiveZoom()) != intrinsicSize() || imageSizeChanged) { - if (!errorOccurred()) - setIntrinsicSize(imageSize(style()->effectiveZoom())); + if (m_imageResource->imageSize(style()->effectiveZoom()) != intrinsicSize() || imageSizeChanged) { + if (!m_imageResource->errorOccurred()) + setIntrinsicSize(m_imageResource->imageSize(style()->effectiveZoom())); // In the case of generated image content using :before/:after, we might not be in the // render tree yet. In that case, we don't need to worry about check for layout, since we'll get a @@ -184,7 +176,7 @@ void RenderImage::imageChanged(WrappedImagePtr newImage, const IntRect* rect) if (rect) { // The image changed rect is in source image coordinates (pre-zooming), // so map from the bounds of the image to the contentsBox. - repaintRect = enclosingIntRect(mapRect(*rect, FloatRect(FloatPoint(), imageSize(1.0f)), contentBoxRect())); + repaintRect = enclosingIntRect(mapRect(*rect, FloatRect(FloatPoint(), m_imageResource->imageSize(1.0f)), contentBoxRect())); // Guard against too-large changed rects. repaintRect.intersect(contentBoxRect()); } else @@ -207,7 +199,7 @@ void RenderImage::notifyFinished(CachedResource* newImage) return; #if USE(ACCELERATED_COMPOSITING) - if ((newImage == m_cachedImage) && hasLayer()) { + if (newImage == m_imageResource->cachedImage() && hasLayer()) { // tell any potential compositing layers // that the image is done and they can reference it directly. layer()->rendererContentChanged(); @@ -216,15 +208,6 @@ void RenderImage::notifyFinished(CachedResource* newImage) UNUSED_PARAM(newImage); #endif } - -void RenderImage::resetAnimation() -{ - if (m_cachedImage) { - image()->resetAnimation(); - if (!needsLayout()) - repaint(); - } -} void RenderImage::paintReplaced(PaintInfo& paintInfo, int tx, int ty) { @@ -240,7 +223,7 @@ void RenderImage::paintReplaced(PaintInfo& paintInfo, int tx, int ty) GraphicsContext* context = paintInfo.context; - if (!hasImage() || errorOccurred()) { + if (!m_imageResource->hasImage() || m_imageResource->errorOccurred()) { if (paintInfo.phase == PaintPhaseSelection) return; @@ -265,17 +248,19 @@ void RenderImage::paintReplaced(PaintInfo& paintInfo, int tx, int ty) int usableWidth = cWidth - 2; int usableHeight = cHeight - 2; - if (errorOccurred() && !image()->isNull() && (usableWidth >= image()->width()) && (usableHeight >= image()->height())) { + Image* image = m_imageResource->image(); + + if (m_imageResource->errorOccurred() && !image->isNull() && usableWidth >= image->width() && usableHeight >= image->height()) { // Center the error image, accounting for border and padding. - int centerX = (usableWidth - image()->width()) / 2; + int centerX = (usableWidth - image->width()) / 2; if (centerX < 0) centerX = 0; - int centerY = (usableHeight - image()->height()) / 2; + int centerY = (usableHeight - image->height()) / 2; if (centerY < 0) centerY = 0; imageX = leftBorder + leftPad + centerX + 1; imageY = topBorder + topPad + centerY + 1; - context->drawImage(image(), style()->colorSpace(), IntPoint(tx + imageX, ty + imageY)); + context->drawImage(image, style()->colorSpace(), IntPoint(tx + imageX, ty + imageY)); errorPictureDrawn = true; } @@ -298,8 +283,8 @@ void RenderImage::paintReplaced(PaintInfo& paintInfo, int tx, int ty) context->drawText(style()->font(), textRun, IntPoint(ax, ay + ascent)); } } - } else if (hasImage() && cWidth > 0 && cHeight > 0) { - Image* img = image(cWidth, cHeight); + } else if (m_imageResource->hasImage() && cWidth > 0 && cHeight > 0) { + Image* img = m_imageResource->image(cWidth, cHeight); if (!img || img->isNull()) return; @@ -361,22 +346,22 @@ void RenderImage::paintFocusRings(PaintInfo& paintInfo, const RenderStyle* style void RenderImage::paintIntoRect(GraphicsContext* context, const IntRect& rect) { - if (!hasImage() || errorOccurred() || rect.width() <= 0 || rect.height() <= 0) + if (!m_imageResource->hasImage() || m_imageResource->errorOccurred() || rect.width() <= 0 || rect.height() <= 0) return; - Image* img = image(rect.width(), rect.height()); + Image* img = m_imageResource->image(rect.width(), rect.height()); if (!img || img->isNull()) return; HTMLImageElement* imageElt = (node() && node()->hasTagName(imgTag)) ? static_cast<HTMLImageElement*>(node()) : 0; CompositeOperator compositeOperator = imageElt ? imageElt->compositeOperator() : CompositeSourceOver; - bool useLowQualityScaling = shouldPaintAtLowQuality(context, this->image(), rect.size()); - context->drawImage(image(rect.width(), rect.height()), style()->colorSpace(), rect, compositeOperator, useLowQualityScaling); + bool useLowQualityScaling = shouldPaintAtLowQuality(context, m_imageResource->image(), rect.size()); + context->drawImage(m_imageResource->image(rect.width(), rect.height()), style()->colorSpace(), rect, compositeOperator, useLowQualityScaling); } int RenderImage::minimumReplacedHeight() const { - return errorOccurred() ? intrinsicSize().height() : 0; + return m_imageResource->errorOccurred() ? intrinsicSize().height() : 0; } HTMLMapElement* RenderImage::imageMap() const @@ -459,18 +444,18 @@ bool RenderImage::isHeightSpecified() const int RenderImage::calcReplacedWidth(bool includeMaxWidth) const { - if (imageHasRelativeWidth()) + if (m_imageResource->imageHasRelativeWidth()) if (RenderObject* cb = isPositioned() ? container() : containingBlock()) { if (cb->isBox()) - setImageContainerSize(IntSize(toRenderBox(cb)->availableWidth(), toRenderBox(cb)->availableHeight())); + m_imageResource->setImageContainerSize(IntSize(toRenderBox(cb)->availableWidth(), toRenderBox(cb)->availableHeight())); } int width; if (isWidthSpecified()) width = calcReplacedWidthUsing(style()->width()); - else if (usesImageContainerSize()) - width = imageSize(style()->effectiveZoom()).width(); - else if (imageHasRelativeWidth()) + else if (m_imageResource->usesImageContainerSize()) + width = m_imageResource->imageSize(style()->effectiveZoom()).width(); + else if (m_imageResource->imageHasRelativeWidth()) width = 0; // If the image is relatively-sized, set the width to 0 until there is a set container size. else width = calcAspectRatioWidth(); @@ -497,9 +482,9 @@ int RenderImage::calcReplacedHeight() const int height; if (isHeightSpecified()) height = calcReplacedHeightUsing(style()->height()); - else if (usesImageContainerSize()) - height = imageSize(style()->effectiveZoom()).height(); - else if (imageHasRelativeHeight()) + else if (m_imageResource->usesImageContainerSize()) + height = m_imageResource->imageSize(style()->effectiveZoom()).height(); + else if (m_imageResource->imageHasRelativeHeight()) height = 0; // If the image is relatively-sized, set the height to 0 until there is a set container size. else height = calcAspectRatioHeight(); @@ -536,7 +521,7 @@ int RenderImage::calcAspectRatioWidth() const IntSize size = intrinsicSize(); if (!size.height()) return 0; - if (!hasImage() || errorOccurred()) + if (!m_imageResource->hasImage() || m_imageResource->errorOccurred()) return size.width(); // Don't bother scaling. return RenderReplaced::calcReplacedHeight() * size.width() / size.height(); } @@ -546,7 +531,7 @@ int RenderImage::calcAspectRatioHeight() const IntSize size = intrinsicSize(); if (!size.width()) return 0; - if (!hasImage() || errorOccurred()) + if (!m_imageResource->hasImage() || m_imageResource->errorOccurred()) return size.height(); // Don't bother scaling. return RenderReplaced::calcReplacedWidth() * size.height() / size.width(); } @@ -571,9 +556,4 @@ void RenderImage::calcPrefWidths() setPrefWidthsDirty(false); } -Image* RenderImage::nullImage() -{ - return Image::nullImage(); -} - } // namespace WebCore diff --git a/WebCore/rendering/RenderImage.h b/WebCore/rendering/RenderImage.h index b89a652..2b88c32 100644 --- a/WebCore/rendering/RenderImage.h +++ b/WebCore/rendering/RenderImage.h @@ -25,6 +25,7 @@ #ifndef RenderImage_h #define RenderImage_h +#include "RenderImageResource.h" #include "RenderReplaced.h" namespace WebCore { @@ -36,25 +37,21 @@ public: RenderImage(Node*); virtual ~RenderImage(); + void setImageResource(PassOwnPtr<RenderImageResource>); + + RenderImageResource* imageResource() { return m_imageResource.get(); } + const RenderImageResource* imageResource() const { return m_imageResource.get(); } + CachedImage* cachedImage() const { return m_imageResource->cachedImage(); } + bool setImageSizeForAltText(CachedImage* newImage = 0); void updateAltText(); - void setCachedImage(CachedImage*); - CachedImage* cachedImage() const { return m_cachedImage.get(); } - HTMLMapElement* imageMap() const; - void resetAnimation(); - - virtual bool hasImage() const { return m_cachedImage; } - void highQualityRepaintTimerFired(Timer<RenderImage>*); protected: - virtual Image* image(int /* width */ = 0, int /* height */ = 0) { return m_cachedImage ? m_cachedImage->image() : nullImage(); } - virtual bool errorOccurred() const { return m_cachedImage && m_cachedImage->errorOccurred(); } - virtual void imageChanged(WrappedImagePtr, const IntRect* = 0); virtual void paintIntoRect(GraphicsContext*, const IntRect&); @@ -64,14 +61,14 @@ protected: bool isWidthSpecified() const; bool isHeightSpecified() const; - virtual void intrinsicSizeChanged() { imageChanged(imagePtr()); } + virtual void intrinsicSizeChanged() { imageChanged(m_imageResource->imagePtr()); } private: virtual const char* renderName() const { return "RenderImage"; } virtual bool isImage() const { return true; } virtual bool isRenderImage() const { return true; } - + virtual void paintReplaced(PaintInfo&, int tx, int ty); virtual int minimumReplacedHeight() const; @@ -84,37 +81,25 @@ private: virtual void calcPrefWidths(); - virtual bool usesImageContainerSize() const { return m_cachedImage ? m_cachedImage->usesImageContainerSize() : false; } - virtual void setImageContainerSize(const IntSize& size) const { if (m_cachedImage) m_cachedImage->setImageContainerSize(size); } - virtual bool imageHasRelativeWidth() const { return m_cachedImage ? m_cachedImage->imageHasRelativeWidth() : false; } - virtual bool imageHasRelativeHeight() const { return m_cachedImage ? m_cachedImage->imageHasRelativeHeight() : false; } - virtual IntSize imageSize(float multiplier) const { return m_cachedImage ? m_cachedImage->imageSize(multiplier) : IntSize(); } - virtual WrappedImagePtr imagePtr() const { return m_cachedImage.get(); } - int calcAspectRatioWidth() const; int calcAspectRatioHeight() const; -protected: - // The image we are rendering. - CachedResourceHandle<CachedImage> m_cachedImage; - private: // Text to display as long as the image isn't available. String m_altText; + OwnPtr<RenderImageResource> m_imageResource; - static Image* nullImage(); - friend class RenderImageScaleObserver; }; inline RenderImage* toRenderImage(RenderObject* object) -{ +{ ASSERT(!object || object->isRenderImage()); return static_cast<RenderImage*>(object); } inline const RenderImage* toRenderImage(const RenderObject* object) -{ +{ ASSERT(!object || object->isRenderImage()); return static_cast<const RenderImage*>(object); } diff --git a/WebCore/rendering/RenderImageGeneratedContent.cpp b/WebCore/rendering/RenderImageGeneratedContent.cpp deleted file mode 100644 index 29d0508..0000000 --- a/WebCore/rendering/RenderImageGeneratedContent.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2008 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "RenderImageGeneratedContent.h" - -#include "RenderBlock.h" -#include "RenderStyle.h" -#include "StyleCachedImage.h" - -namespace WebCore { - -RenderImageGeneratedContent::RenderImageGeneratedContent(Node* n) -: RenderImage(n) -{} - -RenderImageGeneratedContent::~RenderImageGeneratedContent() -{ - m_cachedImage = 0; - m_styleImage->removeClient(this); -} - -void RenderImageGeneratedContent::setStyleImage(StyleImage* image) -{ - if (image->isCachedImage()) - m_cachedImage = static_cast<StyleCachedImage*>(image)->cachedImage(); - m_styleImage = image; - m_styleImage->addClient(this); -} - -} diff --git a/WebCore/rendering/RenderImageGeneratedContent.h b/WebCore/rendering/RenderImageGeneratedContent.h deleted file mode 100644 index 9f8330d..0000000 --- a/WebCore/rendering/RenderImageGeneratedContent.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2008 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef RenderImageGeneratedContent_h -#define RenderImageGeneratedContent_h - -#include "RenderImage.h" -#include "StyleImage.h" -#include <wtf/RefPtr.h> - -namespace WebCore { - -class StyleImage; - -class RenderImageGeneratedContent : public RenderImage { -public: - RenderImageGeneratedContent(Node*); - virtual ~RenderImageGeneratedContent(); - - void setStyleImage(StyleImage*); - - virtual bool hasImage() const { return true; } - -protected: - virtual Image* image(int w = 0, int h = 0) { return m_styleImage->image(this, IntSize(w, h)); } - virtual bool errorOccurred() const { return m_styleImage->errorOccurred(); } - virtual bool usesImageContainerSize() const { return m_styleImage->usesImageContainerSize(); } - virtual void setImageContainerSize(const IntSize& size) const { m_styleImage->setImageContainerSize(size); } - virtual bool imageHasRelativeWidth() const { return m_styleImage->imageHasRelativeWidth(); } - virtual bool imageHasRelativeHeight() const { return m_styleImage->imageHasRelativeHeight(); } - virtual IntSize imageSize(float multiplier) const { return m_styleImage->imageSize(this, multiplier); } - - // |m_styleImage| can be 0 if we get a callback for a background image from RenderObject::setStyle. - virtual WrappedImagePtr imagePtr() const { return m_styleImage ? m_styleImage->data() : 0; } - -private: - RefPtr<StyleImage> m_styleImage; -}; - -} // namespace WebCore - -#endif // RenderImageGeneratedContent_h diff --git a/WebCore/rendering/RenderImageResource.cpp b/WebCore/rendering/RenderImageResource.cpp new file mode 100644 index 0000000..ea3ed2f --- /dev/null +++ b/WebCore/rendering/RenderImageResource.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (C) 1999 Lars Knoll <knoll@kde.org> + * Copyright (C) 1999 Antti Koivisto <koivisto@kde.org> + * Copyright (C) 2000 Dirk Mueller <mueller@kde.org> + * Copyright (C) 2006 Allan Sandfeld Jensen <kde@carewolf.com> + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> + * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com> + * + * 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 "RenderImageResource.h" + +#include "RenderImageResourceStyleImage.h" +#include "RenderObject.h" + +namespace WebCore { + +RenderImageResource::RenderImageResource() + : m_renderer(0) + , m_cachedImage(0) +{ +} + +RenderImageResource::~RenderImageResource() +{ +} + +void RenderImageResource::initialize(RenderObject* renderer) +{ + ASSERT(!m_renderer); + ASSERT(renderer); + m_renderer = renderer; +} + +void RenderImageResource::shutdown() +{ + ASSERT(m_renderer); + + if (m_cachedImage) + m_cachedImage->removeClient(m_renderer); +} + +void RenderImageResource::setCachedImage(CachedImage* newImage) +{ + ASSERT(m_renderer); + + if (m_cachedImage == newImage) + return; + + if (m_cachedImage) + m_cachedImage->removeClient(m_renderer); + m_cachedImage = newImage; + if (m_cachedImage) { + m_cachedImage->addClient(m_renderer); + if (m_cachedImage->errorOccurred()) + m_renderer->imageChanged(m_cachedImage.get()); + } +} + +void RenderImageResource::resetAnimation() +{ + ASSERT(m_renderer); + + if (!m_cachedImage) + return; + + image()->resetAnimation(); + + if (!m_renderer->needsLayout()) + m_renderer->repaint(); +} + +void RenderImageResource::setImageContainerSize(const IntSize& size) const +{ + ASSERT(m_renderer); + + if (!m_cachedImage) + return; + + m_cachedImage->setImageContainerSize(size); +} + +Image* RenderImageResource::nullImage() +{ + return Image::nullImage(); +} + +} // namespace WebCore diff --git a/WebCore/rendering/RenderImageResource.h b/WebCore/rendering/RenderImageResource.h new file mode 100644 index 0000000..2346712 --- /dev/null +++ b/WebCore/rendering/RenderImageResource.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 1999 Lars Knoll <knoll@kde.org> + * Copyright (C) 1999 Antti Koivisto <koivisto@kde.org> + * Copyright (C) 2006 Allan Sandfeld Jensen <kde@carewolf.com> + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> + * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef RenderImageResource_h +#define RenderImageResource_h + +#include "CachedImage.h" +#include "CachedResourceHandle.h" +#include "StyleImage.h" +#include <wtf/Noncopyable.h> + +namespace WebCore { + +class RenderObject; + +class RenderImageResource : public Noncopyable { +public: + virtual ~RenderImageResource(); + + static PassOwnPtr<RenderImageResource> create() + { + return adoptPtr(new RenderImageResource); + } + + virtual void initialize(RenderObject*); + virtual void shutdown(); + + void setCachedImage(CachedImage*); + CachedImage* cachedImage() const { return m_cachedImage.get(); } + virtual bool hasImage() const { return m_cachedImage; } + + void resetAnimation(); + + virtual Image* image(int /* width */ = 0, int /* height */ = 0) { return m_cachedImage ? m_cachedImage->image() : nullImage(); } + virtual bool errorOccurred() const { return m_cachedImage && m_cachedImage->errorOccurred(); } + + virtual void setImageContainerSize(const IntSize& size) const; + virtual bool usesImageContainerSize() const { return m_cachedImage ? m_cachedImage->usesImageContainerSize() : false; } + virtual bool imageHasRelativeWidth() const { return m_cachedImage ? m_cachedImage->imageHasRelativeWidth() : false; } + virtual bool imageHasRelativeHeight() const { return m_cachedImage ? m_cachedImage->imageHasRelativeHeight() : false; } + + virtual IntSize imageSize(float multiplier) const { return m_cachedImage ? m_cachedImage->imageSize(multiplier) : IntSize(); } + + virtual WrappedImagePtr imagePtr() const { return m_cachedImage.get(); } + +protected: + RenderImageResource(); + RenderObject* m_renderer; + CachedResourceHandle<CachedImage> m_cachedImage; + +private: + static Image* nullImage(); +}; + +} // namespace WebCore + +#endif // RenderImage_h diff --git a/WebCore/rendering/RenderImageResourceStyleImage.cpp b/WebCore/rendering/RenderImageResourceStyleImage.cpp new file mode 100644 index 0000000..7f41984 --- /dev/null +++ b/WebCore/rendering/RenderImageResourceStyleImage.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 1999 Lars Knoll <knoll@kde.org> + * Copyright (C) 1999 Antti Koivisto <koivisto@kde.org> + * Copyright (C) 2000 Dirk Mueller <mueller@kde.org> + * Copyright (C) 2006 Allan Sandfeld Jensen <kde@carewolf.com> + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> + * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com> + * + * 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 "RenderImageResourceStyleImage.h" + +#include "RenderObject.h" +#include "StyleCachedImage.h" + +namespace WebCore { + +RenderImageResourceStyleImage::RenderImageResourceStyleImage(StyleImage* styleImage) + : m_styleImage(styleImage) +{ + ASSERT(m_styleImage); +} + +RenderImageResourceStyleImage::~RenderImageResourceStyleImage() +{ +} + +void RenderImageResourceStyleImage::initialize(RenderObject* renderer) +{ + RenderImageResource::initialize(renderer); + + if (m_styleImage->isCachedImage()) + m_cachedImage = static_cast<StyleCachedImage*>(m_styleImage.get())->cachedImage(); + + m_styleImage->addClient(m_renderer); +} + +void RenderImageResourceStyleImage::shutdown() +{ + ASSERT(m_renderer); + m_styleImage->removeClient(m_renderer); + m_cachedImage = 0; +} + +} // namespace WebCore diff --git a/WebCore/rendering/RenderImageResourceStyleImage.h b/WebCore/rendering/RenderImageResourceStyleImage.h new file mode 100644 index 0000000..d91aaa8 --- /dev/null +++ b/WebCore/rendering/RenderImageResourceStyleImage.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 1999 Lars Knoll <knoll@kde.org> + * Copyright (C) 1999 Antti Koivisto <koivisto@kde.org> + * Copyright (C) 2006 Allan Sandfeld Jensen <kde@carewolf.com> + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> + * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef RenderImageResourceStyleImage_h +#define RenderImageResourceStyleImage_h + +#include "RenderImageResource.h" +#include "StyleImage.h" +#include <wtf/RefPtr.h> + +namespace WebCore { + +class RenderObject; + +class RenderImageResourceStyleImage : public RenderImageResource { +public: + virtual ~RenderImageResourceStyleImage(); + + static PassOwnPtr<RenderImageResource> create(StyleImage* styleImage) + { + return adoptPtr(new RenderImageResourceStyleImage(styleImage)); + } + virtual void initialize(RenderObject*); + virtual void shutdown(); + + virtual bool hasImage() const { return true; } + virtual Image* image(int width = 0, int height = 0) { return m_styleImage->image(m_renderer, IntSize(width, height)); } + virtual bool errorOccurred() const { return m_styleImage->errorOccurred(); } + + virtual void setImageContainerSize(const IntSize& size) const { m_styleImage->setImageContainerSize(size); } + virtual bool usesImageContainerSize() const { return m_styleImage->usesImageContainerSize(); } + virtual bool imageHasRelativeWidth() const { return m_styleImage->imageHasRelativeWidth(); } + virtual bool imageHasRelativeHeight() const { return m_styleImage->imageHasRelativeHeight(); } + + virtual IntSize imageSize(float multiplier) const { return m_styleImage->imageSize(m_renderer, multiplier); } + + virtual WrappedImagePtr imagePtr() const { return m_styleImage->data(); } + +private: + RenderImageResourceStyleImage(StyleImage*); + RefPtr<StyleImage> m_styleImage; +}; + +} // namespace WebCore + +#endif // RenderImageStyleImage_h diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp index 347fa32..331750c 100644 --- a/WebCore/rendering/RenderLayer.cpp +++ b/WebCore/rendering/RenderLayer.cpp @@ -2268,12 +2268,10 @@ bool RenderLayer::scroll(ScrollDirection direction, ScrollGranularity granularit bool didVerticalScroll = false; if (m_hBar) { - if (granularity == ScrollByDocument) { - // Special-case for the ScrollByDocument granularity. A document scroll can only be up - // or down and in both cases the horizontal bar goes all the way to the left. - didHorizontalScroll = m_hBar->scroll(ScrollLeft, ScrollByDocument, multiplier); - } else - didHorizontalScroll = m_hBar->scroll(direction, granularity, multiplier); + // Special-case for the ScrollByDocument granularity. A document scroll + // can only be up or down and in both cases the horizontal bar goes all + // the way to the left. + didHorizontalScroll = m_hBar->scroll((granularity == ScrollByDocument) ? ScrollLeft : direction, granularity, multiplier); } if (m_vBar) diff --git a/WebCore/rendering/RenderLayer.h b/WebCore/rendering/RenderLayer.h index 17521ad..3f0ac7c 100644 --- a/WebCore/rendering/RenderLayer.h +++ b/WebCore/rendering/RenderLayer.h @@ -277,7 +277,7 @@ public: void updateScrollInfoAfterLayout(); - bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1.0f); + bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1); void autoscroll(); void resize(const PlatformMouseEvent&, const IntSize&); diff --git a/WebCore/rendering/RenderLayerBacking.cpp b/WebCore/rendering/RenderLayerBacking.cpp index 23645d5..449466d 100644 --- a/WebCore/rendering/RenderLayerBacking.cpp +++ b/WebCore/rendering/RenderLayerBacking.cpp @@ -1163,9 +1163,11 @@ bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim KeyframeValueList transformVector(AnimatedPropertyWebkitTransform); KeyframeValueList opacityVector(AnimatedPropertyOpacity); - for (Vector<KeyframeValue>::const_iterator it = keyframes.beginKeyframes(); it != keyframes.endKeyframes(); ++it) { - const RenderStyle* keyframeStyle = it->style(); - float key = it->key(); + size_t numKeyframes = keyframes.size(); + for (size_t i = 0; i < numKeyframes; ++i) { + const KeyframeValue& currentKeyframe = keyframes[i]; + const RenderStyle* keyframeStyle = currentKeyframe.style(); + float key = currentKeyframe.key(); if (!keyframeStyle) continue; @@ -1173,10 +1175,10 @@ bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim // get timing function const TimingFunction* tf = keyframeStyle->hasAnimations() ? &((*keyframeStyle->animations()).animation(0)->timingFunction()) : 0; - if (hasTransform) + if (currentKeyframe.containsProperty(AnimatedPropertyWebkitTransform)) transformVector.insert(new TransformAnimationValue(key, &(keyframeStyle->transform()), tf)); - if (hasOpacity) + if (currentKeyframe.containsProperty(AnimatedPropertyOpacity)) opacityVector.insert(new FloatAnimationValue(key, keyframeStyle->opacity(), tf)); } diff --git a/WebCore/rendering/RenderLayerCompositor.h b/WebCore/rendering/RenderLayerCompositor.h index 917d610..86c061b 100644 --- a/WebCore/rendering/RenderLayerCompositor.h +++ b/WebCore/rendering/RenderLayerCompositor.h @@ -155,6 +155,7 @@ public: // their parent document. bool shouldPropagateCompositingToEnclosingIFrame() const; + // FIXME: This should be a RenderIFrame* HTMLFrameOwnerElement* enclosingIFrameElement() const; static RenderLayerCompositor* iframeContentsCompositor(RenderIFrame*); diff --git a/WebCore/rendering/RenderListBox.h b/WebCore/rendering/RenderListBox.h index aafb87e..36cb87a 100644 --- a/WebCore/rendering/RenderListBox.h +++ b/WebCore/rendering/RenderListBox.h @@ -68,7 +68,7 @@ private: virtual bool isPointInOverflowControl(HitTestResult&, int x, int y, int tx, int ty); - virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1.0f, Node** stopNode = 0); + virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1, Node** stopNode = 0); virtual void calcPrefWidths(); virtual int baselinePosition(bool firstLine, bool isRootLineBox) const; diff --git a/WebCore/rendering/RenderListItem.cpp b/WebCore/rendering/RenderListItem.cpp index f861467..2366a34 100644 --- a/WebCore/rendering/RenderListItem.cpp +++ b/WebCore/rendering/RenderListItem.cpp @@ -150,6 +150,7 @@ static RenderObject* getParentOfFirstLineBox(RenderBlock* curr, RenderObject* ma if (!firstChild) return 0; + bool inQuirksMode = curr->document()->inQuirksMode(); for (RenderObject* currChild = firstChild; currChild; currChild = currChild->nextSibling()) { if (currChild == marker) continue; @@ -163,7 +164,7 @@ static RenderObject* getParentOfFirstLineBox(RenderBlock* curr, RenderObject* ma if (currChild->isTable() || !currChild->isRenderBlock()) break; - if (curr->isListItem() && currChild->style()->htmlHacks() && currChild->node() && + if (curr->isListItem() && inQuirksMode && currChild->node() && (currChild->node()->hasTagName(ulTag)|| currChild->node()->hasTagName(olTag))) break; diff --git a/WebCore/rendering/RenderListMarker.cpp b/WebCore/rendering/RenderListMarker.cpp index 6ff1709..7b33c3d 100644 --- a/WebCore/rendering/RenderListMarker.cpp +++ b/WebCore/rendering/RenderListMarker.cpp @@ -79,7 +79,7 @@ static String toRoman(int number, bool upper) return String(&letters[lettersSize - length], length); } -static inline String toAlphabeticOrNumeric(int number, const UChar* sequence, int sequenceSize, SequenceType type) +static inline String toAlphabeticOrNumeric(int number, const UChar* sequence, unsigned sequenceSize, SequenceType type) { ASSERT(sequenceSize >= 2); @@ -115,12 +115,28 @@ static inline String toAlphabeticOrNumeric(int number, const UChar* sequence, in return String(&letters[lettersSize - length], length); } -static String toAlphabetic(int number, const UChar* alphabet, int alphabetSize) +static String toSymbolic(int number, const UChar* symbols, unsigned symbolsSize) +{ + ASSERT(number > 0); + ASSERT(symbolsSize >= 1); + unsigned numberShadow = number; + --numberShadow; + + // The asterisks list-style-type is the worst case; we show |numberShadow| asterisks. + Vector<UChar> letters; + letters.append(symbols[numberShadow % symbolsSize]); + unsigned numSymbols = numberShadow / symbolsSize; + while (numSymbols--) + letters.append(symbols[numberShadow % symbolsSize]); + return String::adopt(letters); +} + +static String toAlphabetic(int number, const UChar* alphabet, unsigned alphabetSize) { return toAlphabeticOrNumeric(number, alphabet, alphabetSize, AlphabeticSequence); } -static String toNumeric(int number, const UChar* numerals, int numeralsSize) +static String toNumeric(int number, const UChar* numerals, unsigned numeralsSize) { return toAlphabeticOrNumeric(number, numerals, numeralsSize, NumericSequence); } @@ -135,6 +151,11 @@ template <size_t size> static inline String toNumeric(int number, const UChar(&a return toNumeric(number, alphabet, size); } +template <size_t size> static inline String toSymbolic(int number, const UChar(&alphabet)[size]) +{ + return toSymbolic(number, alphabet, size); +} + static int toHebrewUnder1000(int number, UChar letters[5]) { // FIXME: CSS3 mentions various refinements not implemented here. @@ -419,6 +440,7 @@ static EListStyleType effectiveListMarkerType(EListStyleType type, int value) case Afar: case Amharic: case AmharicAbegede: + case Asterisks: case CjkEarthlyBranch: case CjkHeavenlyStem: case Ethiopic: @@ -437,6 +459,7 @@ static EListStyleType effectiveListMarkerType(EListStyleType type, int value) case EthiopicHalehameTiEr: case EthiopicHalehameTiEt: case EthiopicHalehameTig: + case Footnotes: case Hangul: case HangulConsonant: case Hiragana: @@ -475,9 +498,11 @@ static UChar listMarkerSuffix(EListStyleType type, int value) // Note, the following switch statement has been explicitly // grouped by list-style-type suffix. switch (effectiveType) { - case NoneListStyle: - case Disc: + case Asterisks: case Circle: + case Disc: + case Footnotes: + case NoneListStyle: case Square: ASSERT_NOT_REACHED(); return ' '; @@ -570,12 +595,24 @@ String listMarkerText(EListStyleType type, int value) case NoneListStyle: return ""; + case Asterisks: { + static const UChar asterisksSymbols[1] = { + 0x002A + }; + return toSymbolic(value, asterisksSymbols); + } // We use the same characters for text security. // See RenderText::setInternalString. case Circle: return String(&whiteBullet, 1); case Disc: return String(&bullet, 1); + case Footnotes: { + static const UChar footnotesSymbols[4] = { + 0x002A, 0x2051, 0x2020, 0x2021 + }; + return toSymbolic(value, footnotesSymbols); + } case Square: // The CSS 2.1 test suite uses U+25EE BLACK MEDIUM SMALL SQUARE // instead, but I think this looks better. @@ -1110,6 +1147,10 @@ void RenderListMarker::paint(PaintInfo& paintInfo, int tx, int ty) EListStyleType type = style()->listStyleType(); switch (type) { + case Asterisks: + case Footnotes: + context->drawText(style()->font(), TextRun(m_text), marker.location()); + return; case Disc: context->drawEllipse(marker); return; @@ -1291,6 +1332,11 @@ void RenderListMarker::calcPrefWidths() switch (type) { case NoneListStyle: break; + case Asterisks: + case Footnotes: + m_text = listMarkerText(type, m_listItem->value()); + width = font.width(m_text); // no suffix for these types + break; case Circle: case Disc: case Square: @@ -1489,6 +1535,11 @@ IntRect RenderListMarker::getRelativeMarkerRect() EListStyleType type = style()->listStyleType(); switch (type) { + case Asterisks: + case Footnotes: { + const Font& font = style()->font(); + return IntRect(x(), y() + font.ascent(), font.width(m_text), font.height()); + } case Disc: case Circle: case Square: { diff --git a/WebCore/rendering/RenderMedia.cpp b/WebCore/rendering/RenderMedia.cpp index d7b4a99..a589a2d 100644 --- a/WebCore/rendering/RenderMedia.cpp +++ b/WebCore/rendering/RenderMedia.cpp @@ -57,6 +57,7 @@ RenderMedia::RenderMedia(HTMLMediaElement* video) , m_opacityAnimationFrom(0) , m_opacityAnimationTo(1.0f) { + setImageResource(RenderImageResource::create()); } RenderMedia::RenderMedia(HTMLMediaElement* video, const IntSize& intrinsicSize) @@ -69,6 +70,7 @@ RenderMedia::RenderMedia(HTMLMediaElement* video, const IntSize& intrinsicSize) , m_opacityAnimationFrom(0) , m_opacityAnimationTo(1.0f) { + setImageResource(RenderImageResource::create()); setIntrinsicSize(intrinsicSize); } diff --git a/WebCore/rendering/RenderObject.cpp b/WebCore/rendering/RenderObject.cpp index 78da758..9ee97b4 100644 --- a/WebCore/rendering/RenderObject.cpp +++ b/WebCore/rendering/RenderObject.cpp @@ -41,7 +41,8 @@ #include "RenderArena.h" #include "RenderCounter.h" #include "RenderFlexibleBox.h" -#include "RenderImageGeneratedContent.h" +#include "RenderImage.h" +#include "RenderImageResourceStyleImage.h" #include "RenderInline.h" #include "RenderLayer.h" #include "RenderListItem.h" @@ -110,10 +111,12 @@ RenderObject* RenderObject::createObject(Node* node, RenderStyle* style) // Otherwise acts as if we didn't support this feature. const ContentData* contentData = style->contentData(); if (contentData && !contentData->next() && contentData->isImage() && doc != node) { - RenderImageGeneratedContent* image = new (arena) RenderImageGeneratedContent(node); + RenderImage* image = new (arena) RenderImage(node); image->setStyle(style); if (StyleImage* styleImage = contentData->image()) - image->setStyleImage(styleImage); + image->setImageResource(RenderImageResourceStyleImage::create(styleImage)); + else + image->setImageResource(RenderImageResource::create()); return image; } @@ -1425,7 +1428,8 @@ bool RenderObject::repaintAfterLayoutIfNeeded(RenderBoxModelObject* repaintConta style()->getBoxShadowHorizontalExtent(shadowLeft, shadowRight); int borderRight = isBox() ? toRenderBox(this)->borderRight() : 0; - int borderWidth = max(-outlineStyle->outlineOffset(), max(borderRight, max(style()->borderTopRightRadius().width(), style()->borderBottomRightRadius().width()))) + max(ow, shadowRight); + int boxWidth = isBox() ? toRenderBox(this)->width() : 0; + int borderWidth = max(-outlineStyle->outlineOffset(), max(borderRight, max(style()->borderTopRightRadius().width().calcValue(boxWidth), style()->borderBottomRightRadius().width().calcValue(boxWidth)))) + max(ow, shadowRight); IntRect rightRect(newOutlineBox.x() + min(newOutlineBox.width(), oldOutlineBox.width()) - borderWidth, newOutlineBox.y(), width + borderWidth, @@ -1443,7 +1447,8 @@ bool RenderObject::repaintAfterLayoutIfNeeded(RenderBoxModelObject* repaintConta style()->getBoxShadowVerticalExtent(shadowTop, shadowBottom); int borderBottom = isBox() ? toRenderBox(this)->borderBottom() : 0; - int borderHeight = max(-outlineStyle->outlineOffset(), max(borderBottom, max(style()->borderBottomLeftRadius().height(), style()->borderBottomRightRadius().height()))) + max(ow, shadowBottom); + int boxHeight = isBox() ? toRenderBox(this)->height() : 0; + int borderHeight = max(-outlineStyle->outlineOffset(), max(borderBottom, max(style()->borderBottomLeftRadius().height().calcValue(boxHeight), style()->borderBottomRightRadius().height().calcValue(boxHeight)))) + max(ow, shadowBottom); IntRect bottomRect(newOutlineBox.x(), min(newOutlineBox.bottom(), oldOutlineBox.bottom()) - borderHeight, max(newOutlineBox.width(), oldOutlineBox.width()), @@ -2556,27 +2561,11 @@ void RenderObject::adjustRectForOutlineAndShadow(IntRect& rect) const { int outlineSize = outlineStyleForRepaint()->outlineSize(); if (const ShadowData* boxShadow = style()->boxShadow()) { - int shadowLeft = 0; - int shadowRight = 0; - int shadowTop = 0; - int shadowBottom = 0; - - do { - if (boxShadow->style() == Normal) { - shadowLeft = min(boxShadow->x() - boxShadow->blur() - boxShadow->spread() - outlineSize, shadowLeft); - shadowRight = max(boxShadow->x() + boxShadow->blur() + boxShadow->spread() + outlineSize, shadowRight); - shadowTop = min(boxShadow->y() - boxShadow->blur() - boxShadow->spread() - outlineSize, shadowTop); - shadowBottom = max(boxShadow->y() + boxShadow->blur() + boxShadow->spread() + outlineSize, shadowBottom); - } - - boxShadow = boxShadow->next(); - } while (boxShadow); + boxShadow->adjustRectForShadow(rect, outlineSize); + return; + } - rect.move(shadowLeft, shadowTop); - rect.setWidth(rect.width() - shadowLeft + shadowRight); - rect.setHeight(rect.height() - shadowTop + shadowBottom); - } else - rect.inflate(outlineSize); + rect.inflate(outlineSize); } AnimationController* RenderObject::animation() const @@ -2708,6 +2697,12 @@ RenderSVGResourceContainer* RenderObject::toRenderSVGResourceContainer() return 0; } +void RenderObject::setNeedsBoundariesUpdate() +{ + if (RenderObject* renderer = parent()) + renderer->setNeedsBoundariesUpdate(); +} + FloatRect RenderObject::objectBoundingBox() const { ASSERT_NOT_REACHED(); diff --git a/WebCore/rendering/RenderObject.h b/WebCore/rendering/RenderObject.h index d2046cf..9fbaf91 100644 --- a/WebCore/rendering/RenderObject.h +++ b/WebCore/rendering/RenderObject.h @@ -327,7 +327,7 @@ public: // Unfortunately we don't have such a class yet, because it's not possible for all renderers // to inherit from RenderSVGObject -> RenderObject (some need RenderBlock inheritance for instance) virtual void setNeedsTransformUpdate() { } - virtual void setNeedsBoundariesUpdate() { } + virtual void setNeedsBoundariesUpdate(); // Per SVG 1.1 objectBoundingBox ignores clipping, masking, filter effects, opacity and stroke-width. // This is used for all computation of objectBoundingBox relative units and by SVGLocateable::getBBox(). @@ -383,14 +383,7 @@ public: bool hasBoxDecorations() const { return m_paintBackground; } bool mustRepaintBackgroundOrBorder() const; - bool hasBackground() const - { - Color color = style()->visitedDependentColor(CSSPropertyBackgroundColor); - if (color.isValid() && color.alpha() > 0) - return true; - return style()->hasBackgroundImage(); - } - + bool hasBackground() const { return style()->hasBackground(); } bool needsLayout() const { return m_needsLayout || m_normalChildNeedsLayout || m_posChildNeedsLayout || m_needsPositionedMovementLayout; } bool selfNeedsLayout() const { return m_needsLayout; } bool needsPositionedMovementLayout() const { return m_needsPositionedMovementLayout; } diff --git a/WebCore/rendering/RenderObjectChildList.cpp b/WebCore/rendering/RenderObjectChildList.cpp index 68e392c..96ec800 100644 --- a/WebCore/rendering/RenderObjectChildList.cpp +++ b/WebCore/rendering/RenderObjectChildList.cpp @@ -30,7 +30,8 @@ #include "AXObjectCache.h" #include "RenderBlock.h" #include "RenderCounter.h" -#include "RenderImageGeneratedContent.h" +#include "RenderImage.h" +#include "RenderImageResourceStyleImage.h" #include "RenderInline.h" #include "RenderLayer.h" #include "RenderListItem.h" @@ -97,6 +98,11 @@ RenderObject* RenderObjectChildList::removeChildNode(RenderObject* owner, Render if (oldChild->isPositioned() && owner->childrenInline()) owner->dirtyLinesFromChangedChild(oldChild); + +#if ENABLE(SVG) + // Update cached boundaries in SVG renderers, if a child is removed. + owner->setNeedsBoundariesUpdate(); +#endif } // If oldChild is the start or end of the selection, then clear the selection to @@ -430,12 +436,14 @@ void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, Pseudo renderer->setStyle(pseudoElementStyle); break; case CONTENT_OBJECT: { - RenderImageGeneratedContent* image = new (owner->renderArena()) RenderImageGeneratedContent(owner->document()); // anonymous object + RenderImage* image = new (owner->renderArena()) RenderImage(owner->document()); // anonymous object RefPtr<RenderStyle> style = RenderStyle::create(); style->inheritFrom(pseudoElementStyle); image->setStyle(style.release()); if (StyleImage* styleImage = content->image()) - image->setStyleImage(styleImage); + image->setImageResource(RenderImageResourceStyleImage::create(styleImage)); + else + image->setImageResource(RenderImageResource::create()); renderer = image; break; } diff --git a/WebCore/rendering/RenderPath.cpp b/WebCore/rendering/RenderPath.cpp index 86a12c8..0f31df1 100644 --- a/WebCore/rendering/RenderPath.cpp +++ b/WebCore/rendering/RenderPath.cpp @@ -101,28 +101,39 @@ void RenderPath::layout() LayoutRepainter repainter(*this, m_everHadLayout && checkForRepaintDuringLayout()); SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node()); + bool updateCachedBoundariesInParents = false; + bool needsPathUpdate = m_needsPathUpdate; if (needsPathUpdate) { m_path = element->toPathData(); m_needsPathUpdate = false; + updateCachedBoundariesInParents = true; } if (m_needsTransformUpdate) { m_localTransform = element->animatedLocalTransform(); m_needsTransformUpdate = false; + updateCachedBoundariesInParents = true; } + if (m_needsBoundariesUpdate) + updateCachedBoundariesInParents = true; + // Invalidate all resources of this client if our layout changed. if (m_everHadLayout && selfNeedsLayout()) SVGResourcesCache::clientLayoutChanged(this); // At this point LayoutRepainter already grabbed the old bounds, - // recalculate them now so repaintAfterLayout() uses the new bounds + // recalculate them now so repaintAfterLayout() uses the new bounds. if (needsPathUpdate || m_needsBoundariesUpdate) { updateCachedBoundaries(); m_needsBoundariesUpdate = false; } + // If our bounds changed, notify the parents. + if (updateCachedBoundariesInParents) + RenderSVGModelObject::setNeedsBoundariesUpdate(); + repainter.repaintAfterLayout(); setNeedsLayout(false); } @@ -172,8 +183,7 @@ void RenderPath::paint(PaintInfo& paintInfo, int, int) return; FloatRect boundingBox = repaintRectInLocalCoordinates(); - FloatRect nonLocalBoundingBox = m_localTransform.mapRect(boundingBox); - if (!nonLocalBoundingBox.intersects(paintInfo.rect)) + if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(boundingBox, m_localTransform, paintInfo)) return; PaintInfo childPaintInfo(paintInfo); @@ -270,13 +280,6 @@ FloatRect RenderPath::calculateMarkerBoundsIfNeeded() return m_markerLayoutInfo.calculateBoundaries(markerStart, markerMid, markerEnd, svgStyle->strokeWidth().value(svgElement), m_path); } -void RenderPath::styleWillChange(StyleDifference diff, const RenderStyle* newStyle) -{ - if (diff == StyleDifferenceLayout) - setNeedsBoundariesUpdate(); - RenderSVGModelObject::styleWillChange(diff, newStyle); -} - void RenderPath::updateCachedBoundaries() { if (m_path.isEmpty()) { diff --git a/WebCore/rendering/RenderPath.h b/WebCore/rendering/RenderPath.h index 1bdac07..1d35a01 100644 --- a/WebCore/rendering/RenderPath.h +++ b/WebCore/rendering/RenderPath.h @@ -41,8 +41,8 @@ public: RenderPath(SVGStyledTransformableElement*); const Path& path() const { return m_path; } - void setNeedsBoundariesUpdate() { m_needsBoundariesUpdate = true; } void setNeedsPathUpdate() { m_needsPathUpdate = true; } + virtual void setNeedsBoundariesUpdate() { m_needsBoundariesUpdate = true; } virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; } private: @@ -63,7 +63,6 @@ private: virtual void addFocusRingRects(Vector<IntRect>&, int tx, int ty); virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction); - virtual void styleWillChange(StyleDifference, const RenderStyle*); FloatRect calculateMarkerBoundsIfNeeded(); void updateCachedBoundaries(); diff --git a/WebCore/rendering/RenderRuby.cpp b/WebCore/rendering/RenderRuby.cpp index 4ab9d73..2f543d5 100644 --- a/WebCore/rendering/RenderRuby.cpp +++ b/WebCore/rendering/RenderRuby.cpp @@ -75,24 +75,19 @@ bool RenderRubyAsInline::isChildAllowed(RenderObject* child, RenderStyle*) const void RenderRubyAsInline::addChild(RenderObject* child, RenderObject* beforeChild) { - // Note: ':after' content is handled implicitely below + // Note: ':after' content is handled implicitly below - // if child is a ruby run, just add it normally if (child->isRubyRun()) { RenderInline::addChild(child, beforeChild); return; } - if (beforeChild && !isAfterContent(beforeChild)) { - // insert child into run - ASSERT(!beforeChild->isRubyRun()); - RenderRubyRun* run = findRubyRunParent(beforeChild); - ASSERT(run); // beforeChild should always have a run as parent - if (run) { + if (beforeChild && !isAfterContent(beforeChild) && !beforeChild->isRubyRun()) { + if (RenderRubyRun* run = findRubyRunParent(beforeChild)) { run->addChild(child, beforeChild); return; } - ASSERT(false); // beforeChild should always have a run as parent! + ASSERT_NOT_REACHED(); // beforeChild should always have a run as parent! // Emergency fallback: fall through and just append. } diff --git a/WebCore/rendering/RenderSVGBlock.cpp b/WebCore/rendering/RenderSVGBlock.cpp index d6022b5..b2d727a 100644 --- a/WebCore/rendering/RenderSVGBlock.cpp +++ b/WebCore/rendering/RenderSVGBlock.cpp @@ -81,6 +81,13 @@ void RenderSVGBlock::destroy() RenderBlock::destroy(); } +void RenderSVGBlock::styleWillChange(StyleDifference diff, const RenderStyle* newStyle) +{ + if (diff == StyleDifferenceLayout) + setNeedsBoundariesUpdate(); + RenderBlock::styleWillChange(diff, newStyle); +} + void RenderSVGBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { RenderBlock::styleDidChange(diff, oldStyle); diff --git a/WebCore/rendering/RenderSVGBlock.h b/WebCore/rendering/RenderSVGBlock.h index c4337cc..c1379da 100644 --- a/WebCore/rendering/RenderSVGBlock.h +++ b/WebCore/rendering/RenderSVGBlock.h @@ -40,6 +40,7 @@ private: virtual void absoluteRects(Vector<IntRect>&, int tx, int ty); virtual void destroy(); + virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle); virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); virtual void updateFromElement(); }; diff --git a/WebCore/rendering/RenderSVGContainer.cpp b/WebCore/rendering/RenderSVGContainer.cpp index bab07a4..8c99270 100644 --- a/WebCore/rendering/RenderSVGContainer.cpp +++ b/WebCore/rendering/RenderSVGContainer.cpp @@ -39,6 +39,7 @@ namespace WebCore { RenderSVGContainer::RenderSVGContainer(SVGStyledElement* node) : RenderSVGModelObject(node) , m_drawsContents(true) + , m_needsBoundariesUpdate(true) { } @@ -55,7 +56,7 @@ void RenderSVGContainer::layout() LayoutRepainter repainter(*this, m_everHadLayout && checkForRepaintDuringLayout()); // Allow RenderSVGTransformableContainer to update its transform. - calculateLocalTransform(); + bool updatedTransform = calculateLocalTransform(); SVGRenderSupport::layoutChildren(this, selfNeedsLayout()); @@ -63,6 +64,16 @@ void RenderSVGContainer::layout() if (m_everHadLayout && selfNeedsLayout()) SVGResourcesCache::clientLayoutChanged(this); + // At this point LayoutRepainter already grabbed the old bounds, + // recalculate them now so repaintAfterLayout() uses the new bounds. + if (m_needsBoundariesUpdate || updatedTransform) { + updateCachedBoundaries(); + m_needsBoundariesUpdate = false; + + // If our bounds changed, notify the parents. + RenderSVGModelObject::setNeedsBoundariesUpdate(); + } + repainter.repaintAfterLayout(); setNeedsLayout(false); } @@ -86,6 +97,10 @@ void RenderSVGContainer::paint(PaintInfo& paintInfo, int, int) if (!firstChild() && !selfWillPaint()) return; + FloatRect repaintRect = repaintRectInLocalCoordinates(); + if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(repaintRect, localToParentTransform(), paintInfo)) + return; + PaintInfo childPaintInfo(paintInfo); childPaintInfo.context->save(); @@ -115,7 +130,7 @@ void RenderSVGContainer::paint(PaintInfo& paintInfo, int, int) // FIXME: This means our focus ring won't share our rotation like it should. // We should instead disable our clip during PaintPhaseOutline if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE) { - IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRectInLocalCoordinates())); + IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRect)); paintOutline(paintInfo.context, paintRectInParent.x(), paintRectInParent.y(), paintRectInParent.width(), paintRectInParent.height()); } } @@ -128,21 +143,14 @@ void RenderSVGContainer::addFocusRingRects(Vector<IntRect>& rects, int, int) rects.append(paintRectInParent); } -FloatRect RenderSVGContainer::objectBoundingBox() const +void RenderSVGContainer::updateCachedBoundaries() { - return SVGRenderSupport::computeContainerBoundingBox(this, SVGRenderSupport::ObjectBoundingBox); -} + m_objectBoundingBox = FloatRect(); + m_strokeBoundingBox = FloatRect(); + m_repaintBoundingBox = FloatRect(); -FloatRect RenderSVGContainer::strokeBoundingBox() const -{ - return SVGRenderSupport::computeContainerBoundingBox(this, SVGRenderSupport::StrokeBoundingBox); -} - -FloatRect RenderSVGContainer::repaintRectInLocalCoordinates() const -{ - FloatRect repaintRect = SVGRenderSupport::computeContainerBoundingBox(this, SVGRenderSupport::RepaintBoundingBox); - SVGRenderSupport::intersectRepaintRectWithResources(this, repaintRect); - return repaintRect; + SVGRenderSupport::computeContainerBoundingBoxes(this, m_objectBoundingBox, m_strokeBoundingBox, m_repaintBoundingBox); + SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingBox); } bool RenderSVGContainer::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) diff --git a/WebCore/rendering/RenderSVGContainer.h b/WebCore/rendering/RenderSVGContainer.h index 0a122cd..b0c952f 100644 --- a/WebCore/rendering/RenderSVGContainer.h +++ b/WebCore/rendering/RenderSVGContainer.h @@ -43,6 +43,7 @@ public: bool drawsContents() const { return m_drawsContents; } virtual void paint(PaintInfo&, int parentX, int parentY); + virtual void setNeedsBoundariesUpdate() { m_needsBoundariesUpdate = true; } protected: virtual RenderObjectChildList* virtualChildren() { return children(); } @@ -55,14 +56,14 @@ protected: virtual void addFocusRingRects(Vector<IntRect>&, int tx, int ty); - virtual FloatRect objectBoundingBox() const; - virtual FloatRect strokeBoundingBox() const; - virtual FloatRect repaintRectInLocalCoordinates() const; + virtual FloatRect objectBoundingBox() const { return m_objectBoundingBox; } + virtual FloatRect strokeBoundingBox() const { return m_strokeBoundingBox; } + virtual FloatRect repaintRectInLocalCoordinates() const { return m_repaintBoundingBox; } virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction); // Allow RenderSVGTransformableContainer to hook in at the right time in layout() - virtual void calculateLocalTransform() { } + virtual bool calculateLocalTransform() { return false; } // Allow RenderSVGViewportContainer to hook in at the right times in layout(), paint() and nodeAtFloatPoint() virtual void calcViewport() { } @@ -70,10 +71,15 @@ protected: virtual bool pointIsInsideViewportClip(const FloatPoint& /*pointInParent*/) { return true; } bool selfWillPaint(); + void updateCachedBoundaries(); private: RenderObjectChildList m_children; + FloatRect m_objectBoundingBox; + FloatRect m_strokeBoundingBox; + FloatRect m_repaintBoundingBox; bool m_drawsContents : 1; + bool m_needsBoundariesUpdate : 1; }; inline RenderSVGContainer* toRenderSVGContainer(RenderObject* object) diff --git a/WebCore/rendering/RenderSVGGradientStop.h b/WebCore/rendering/RenderSVGGradientStop.h index 45da7b4..f06a9a5 100644 --- a/WebCore/rendering/RenderSVGGradientStop.h +++ b/WebCore/rendering/RenderSVGGradientStop.h @@ -46,6 +46,7 @@ public: // https://bugs.webkit.org/show_bug.cgi?id=20400 virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject*) { return IntRect(); } virtual FloatRect objectBoundingBox() const { return FloatRect(); } + virtual FloatRect strokeBoundingBox() const { return FloatRect(); } virtual FloatRect repaintRectInLocalCoordinates() const { return FloatRect(); } protected: diff --git a/WebCore/rendering/RenderSVGHiddenContainer.cpp b/WebCore/rendering/RenderSVGHiddenContainer.cpp index 0af4236..ee1d214 100644 --- a/WebCore/rendering/RenderSVGHiddenContainer.cpp +++ b/WebCore/rendering/RenderSVGHiddenContainer.cpp @@ -47,11 +47,6 @@ void RenderSVGHiddenContainer::paint(PaintInfo&, int, int) // This subtree does not paint. } -IntRect RenderSVGHiddenContainer::clippedOverflowRectForRepaint(RenderBoxModelObject* /*repaintContainer*/) -{ - return IntRect(); -} - void RenderSVGHiddenContainer::absoluteQuads(Vector<FloatQuad>&) { // This subtree does not take up space or paint @@ -62,16 +57,6 @@ bool RenderSVGHiddenContainer::nodeAtFloatPoint(const HitTestRequest&, HitTestRe return false; } -FloatRect RenderSVGHiddenContainer::objectBoundingBox() const -{ - return FloatRect(); -} - -FloatRect RenderSVGHiddenContainer::repaintRectInLocalCoordinates() const -{ - return FloatRect(); -} - } #endif // ENABLE(SVG) diff --git a/WebCore/rendering/RenderSVGHiddenContainer.h b/WebCore/rendering/RenderSVGHiddenContainer.h index e0daac1..97800d4 100644 --- a/WebCore/rendering/RenderSVGHiddenContainer.h +++ b/WebCore/rendering/RenderSVGHiddenContainer.h @@ -47,12 +47,9 @@ namespace WebCore { virtual void paint(PaintInfo&, int parentX, int parentY); - virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer); + virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject*) { return IntRect(); } virtual void absoluteQuads(Vector<FloatQuad>&); - virtual FloatRect objectBoundingBox() const; - virtual FloatRect repaintRectInLocalCoordinates() const; - virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction); }; } diff --git a/WebCore/rendering/RenderSVGImage.cpp b/WebCore/rendering/RenderSVGImage.cpp index 893a4ea..0056fa3 100644 --- a/WebCore/rendering/RenderSVGImage.cpp +++ b/WebCore/rendering/RenderSVGImage.cpp @@ -5,6 +5,7 @@ Copyright (C) 2007, 2008, 2009 Rob Buis <buis@kde.org> Copyright (C) 2009, Google, Inc. Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -32,6 +33,7 @@ #include "FloatQuad.h" #include "GraphicsContext.h" #include "PointerEventsHitRules.h" +#include "RenderImageResource.h" #include "RenderLayer.h" #include "RenderSVGResourceContainer.h" #include "RenderSVGResourceFilter.h" @@ -44,9 +46,16 @@ namespace WebCore { RenderSVGImage::RenderSVGImage(SVGImageElement* impl) - : RenderImage(impl) + : RenderSVGModelObject(impl) , m_needsTransformUpdate(true) + , m_imageResource(RenderImageResource::create()) { + m_imageResource->initialize(this); +} + +RenderSVGImage::~RenderSVGImage() +{ + m_imageResource->shutdown(); } void RenderSVGImage::layout() @@ -56,75 +65,72 @@ void RenderSVGImage::layout() LayoutRepainter repainter(*this, m_everHadLayout && checkForRepaintDuringLayout()); SVGImageElement* image = static_cast<SVGImageElement*>(node()); + bool updateCachedBoundariesInParents = false; if (m_needsTransformUpdate) { m_localTransform = image->animatedLocalTransform(); m_needsTransformUpdate = false; + updateCachedBoundariesInParents = true; } - // minimum height - setHeight(errorOccurred() ? intrinsicSize().height() : 0); - - calcWidth(); - calcHeight(); - // FIXME: Optimize caching the repaint rects. + FloatRect oldBoundaries = m_localBounds; m_localBounds = FloatRect(image->x().value(image), image->y().value(image), image->width().value(image), image->height().value(image)); m_cachedLocalRepaintRect = FloatRect(); + if (!updateCachedBoundariesInParents) + updateCachedBoundariesInParents = oldBoundaries != m_localBounds; + // Invalidate all resources of this client if our layout changed. if (m_everHadLayout && selfNeedsLayout()) SVGResourcesCache::clientLayoutChanged(this); + // If our bounds changed, notify the parents. + if (updateCachedBoundariesInParents) + RenderSVGModelObject::setNeedsBoundariesUpdate(); + repainter.repaintAfterLayout(); setNeedsLayout(false); } void RenderSVGImage::paint(PaintInfo& paintInfo, int, int) { - if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN) + if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN || !m_imageResource->hasImage()) return; - paintInfo.context->save(); - paintInfo.context->concatCTM(localToParentTransform()); - - if (paintInfo.phase == PaintPhaseForeground) { - PaintInfo savedInfo(paintInfo); + FloatRect boundingBox = repaintRectInLocalCoordinates(); + if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(boundingBox, m_localTransform, paintInfo)) + return; - if (SVGRenderSupport::prepareToRenderSVGContent(this, paintInfo)) { - FloatRect destRect = m_localBounds; - FloatRect srcRect(0, 0, image()->width(), image()->height()); + PaintInfo childPaintInfo(paintInfo); + bool drawsOutline = style()->outlineWidth() && (childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline); + if (drawsOutline || childPaintInfo.phase == PaintPhaseForeground) { + childPaintInfo.context->save(); + childPaintInfo.applyTransform(m_localTransform); - SVGImageElement* imageElt = static_cast<SVGImageElement*>(node()); - if (imageElt->preserveAspectRatio().align() != SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE) - imageElt->preserveAspectRatio().transformRect(destRect, srcRect); + if (childPaintInfo.phase == PaintPhaseForeground) { + PaintInfo savedInfo(childPaintInfo); - paintInfo.context->drawImage(image(), DeviceColorSpace, destRect, srcRect); - } - SVGRenderSupport::finishRenderSVGContent(this, paintInfo, savedInfo.context); - } + if (SVGRenderSupport::prepareToRenderSVGContent(this, childPaintInfo)) { + Image* image = m_imageResource->image(); + FloatRect destRect = m_localBounds; + FloatRect srcRect(0, 0, image->width(), image->height()); - if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth()) - paintOutline(paintInfo.context, 0, 0, width(), height()); + SVGImageElement* imageElement = static_cast<SVGImageElement*>(node()); + if (imageElement->preserveAspectRatio().align() != SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE) + imageElement->preserveAspectRatio().transformRect(destRect, srcRect); - paintInfo.context->restore(); -} - -void RenderSVGImage::destroy() -{ - SVGResourcesCache::clientDestroyed(this); - RenderImage::destroy(); -} + childPaintInfo.context->drawImage(image, DeviceColorSpace, destRect, srcRect); + } -void RenderSVGImage::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) -{ - RenderImage::styleDidChange(diff, oldStyle); - SVGResourcesCache::clientStyleChanged(this, diff, style()); -} + SVGRenderSupport::finishRenderSVGContent(this, childPaintInfo, savedInfo.context); + } -void RenderSVGImage::updateFromElement() -{ - RenderImage::updateFromElement(); - SVGResourcesCache::clientUpdatedFromElement(this, style()); + if (drawsOutline) + paintOutline(childPaintInfo.context, static_cast<int>(boundingBox.x()), static_cast<int>(boundingBox.y()), + static_cast<int>(boundingBox.width()), static_cast<int>(boundingBox.height())); + + childPaintInfo.context->restore(); + } } bool RenderSVGImage::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) @@ -152,12 +158,6 @@ bool RenderSVGImage::nodeAtFloatPoint(const HitTestRequest& request, HitTestResu return false; } -bool RenderSVGImage::nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int, HitTestAction) -{ - ASSERT_NOT_REACHED(); - return false; -} - FloatRect RenderSVGImage::repaintRectInLocalCoordinates() const { // If we already have a cached repaint rect, return that @@ -170,10 +170,8 @@ FloatRect RenderSVGImage::repaintRectInLocalCoordinates() const return m_cachedLocalRepaintRect; } -void RenderSVGImage::imageChanged(WrappedImagePtr image, const IntRect* rect) +void RenderSVGImage::imageChanged(WrappedImagePtr, const IntRect*) { - RenderImage::imageChanged(image, rect); - // The image resource defaults to nullImage until the resource arrives. // This empty image may be cached by SVG resources which must be invalidated. if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this)) @@ -185,21 +183,6 @@ void RenderSVGImage::imageChanged(WrappedImagePtr image, const IntRect* rect) repaint(); } -IntRect RenderSVGImage::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) -{ - return SVGRenderSupport::clippedOverflowRectForRepaint(this, repaintContainer); -} - -void RenderSVGImage::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& repaintRect, bool fixed) -{ - SVGRenderSupport::computeRectForRepaint(this, repaintContainer, repaintRect, fixed); -} - -void RenderSVGImage::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed , bool useTransforms, TransformState& transformState) const -{ - SVGRenderSupport::mapLocalToContainer(this, repaintContainer, fixed, useTransforms, transformState); -} - void RenderSVGImage::addFocusRingRects(Vector<IntRect>& rects, int, int) { // this is called from paint() after the localTransform has already been applied @@ -208,17 +191,6 @@ void RenderSVGImage::addFocusRingRects(Vector<IntRect>& rects, int, int) rects.append(contentRect); } -void RenderSVGImage::absoluteRects(Vector<IntRect>&, int, int) -{ - // This code path should never be taken for SVG, as we're assuming useTransforms=true everywhere, absoluteQuads should be used. - ASSERT_NOT_REACHED(); -} - -void RenderSVGImage::absoluteQuads(Vector<FloatQuad>& quads) -{ - quads.append(localToAbsoluteQuad(strokeBoundingBox())); -} - -} +} // namespace WebCore #endif // ENABLE(SVG) diff --git a/WebCore/rendering/RenderSVGImage.h b/WebCore/rendering/RenderSVGImage.h index 38e3a13..da94568 100644 --- a/WebCore/rendering/RenderSVGImage.h +++ b/WebCore/rendering/RenderSVGImage.h @@ -3,6 +3,7 @@ Copyright (C) 2006, 2009 Apple Inc. All rights reserved. Copyright (C) 2007 Rob Buis <buis@kde.org> Copyright (C) 2009 Google, Inc. + Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -26,20 +27,25 @@ #if ENABLE(SVG) #include "AffineTransform.h" #include "FloatRect.h" -#include "RenderImage.h" +#include "RenderSVGModelObject.h" #include "SVGPreserveAspectRatio.h" #include "SVGRenderSupport.h" namespace WebCore { +class RenderImageResource; class SVGImageElement; -class RenderSVGImage : public RenderImage { +class RenderSVGImage : public RenderSVGModelObject { public: RenderSVGImage(SVGImageElement*); + virtual ~RenderSVGImage(); virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; } + RenderImageResource* imageResource() { return m_imageResource.get(); } + const RenderImageResource* imageResource() const { return m_imageResource.get(); } + private: virtual const char* renderName() const { return "RenderSVGImage"; } virtual bool isSVGImage() const { return true; } @@ -50,28 +56,16 @@ private: virtual FloatRect strokeBoundingBox() const { return m_localBounds; } virtual FloatRect repaintRectInLocalCoordinates() const; - virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer); - virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false); - - virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&) const; - - virtual void absoluteRects(Vector<IntRect>&, int tx, int ty); - virtual void absoluteQuads(Vector<FloatQuad>&); virtual void addFocusRingRects(Vector<IntRect>&, int tx, int ty); virtual void imageChanged(WrappedImagePtr, const IntRect* = 0); - + virtual void layout(); virtual void paint(PaintInfo&, int parentX, int parentY); - virtual void destroy(); - virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); - virtual void updateFromElement(); - virtual bool requiresLayer() const { return false; } virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction); - virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); virtual AffineTransform localTransform() const { return m_localTransform; } @@ -79,6 +73,7 @@ private: AffineTransform m_localTransform; FloatRect m_localBounds; mutable FloatRect m_cachedLocalRepaintRect; + OwnPtr<RenderImageResource> m_imageResource; }; inline RenderSVGImage* toRenderSVGImage(RenderObject* object) diff --git a/WebCore/rendering/RenderSVGInline.cpp b/WebCore/rendering/RenderSVGInline.cpp index 93e6a06..bc6bc12 100644 --- a/WebCore/rendering/RenderSVGInline.cpp +++ b/WebCore/rendering/RenderSVGInline.cpp @@ -99,6 +99,13 @@ void RenderSVGInline::destroy() RenderInline::destroy(); } +void RenderSVGInline::styleWillChange(StyleDifference diff, const RenderStyle* newStyle) +{ + if (diff == StyleDifferenceLayout) + setNeedsBoundariesUpdate(); + RenderInline::styleWillChange(diff, newStyle); +} + void RenderSVGInline::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { RenderInline::styleDidChange(diff, oldStyle); diff --git a/WebCore/rendering/RenderSVGInline.h b/WebCore/rendering/RenderSVGInline.h index 56d911f..fb38f1b 100644 --- a/WebCore/rendering/RenderSVGInline.h +++ b/WebCore/rendering/RenderSVGInline.h @@ -56,6 +56,7 @@ private: virtual InlineFlowBox* createInlineFlowBox(); virtual void destroy(); + virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle); virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); virtual void updateFromElement(); }; diff --git a/WebCore/rendering/RenderSVGModelObject.cpp b/WebCore/rendering/RenderSVGModelObject.cpp index 5a19749..28760a0 100644 --- a/WebCore/rendering/RenderSVGModelObject.cpp +++ b/WebCore/rendering/RenderSVGModelObject.cpp @@ -87,6 +87,13 @@ void RenderSVGModelObject::destroy() RenderObject::destroy(); } +void RenderSVGModelObject::styleWillChange(StyleDifference diff, const RenderStyle* newStyle) +{ + if (diff == StyleDifferenceLayout) + setNeedsBoundariesUpdate(); + RenderObject::styleWillChange(diff, newStyle); +} + void RenderSVGModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { RenderObject::styleDidChange(diff, oldStyle); diff --git a/WebCore/rendering/RenderSVGModelObject.h b/WebCore/rendering/RenderSVGModelObject.h index 35c4dc3..9de217c 100644 --- a/WebCore/rendering/RenderSVGModelObject.h +++ b/WebCore/rendering/RenderSVGModelObject.h @@ -39,7 +39,7 @@ namespace WebCore { // Most renderers in the SVG rendering tree will inherit from this class -// but not all. (e.g. RenderSVGForeignObject, RenderSVGBlock, RenderSVGImage) thus methods +// but not all. (e.g. RenderSVGForeignObject, RenderSVGBlock) thus methods // required by SVG renders need to be declared on RenderObject, but shared // logic can go in this class or in SVGRenderSupport. @@ -61,6 +61,7 @@ public: virtual void destroy(); virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&) const; + virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle); virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); virtual void updateFromElement(); diff --git a/WebCore/rendering/RenderSVGResourceFilter.cpp b/WebCore/rendering/RenderSVGResourceFilter.cpp index 09e83f4..982375e 100644 --- a/WebCore/rendering/RenderSVGResourceFilter.cpp +++ b/WebCore/rendering/RenderSVGResourceFilter.cpp @@ -262,16 +262,17 @@ void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo if (!filterData->builded) { filterData->filter->setSourceImage(filterData->sourceGraphicBuffer.release()); lastEffect->apply(filterData->filter.get()); +#if !PLATFORM(CG) + ImageBuffer* resultImage = lastEffect->resultImage(); + if (resultImage) + resultImage->transformColorSpace(LinearRGB, DeviceRGB); +#endif filterData->builded = true; } ImageBuffer* resultImage = lastEffect->resultImage(); - if (resultImage) { -#if !PLATFORM(CG) - resultImage->transformColorSpace(LinearRGB, DeviceRGB); -#endif + if (resultImage) context->drawImageBuffer(resultImage, object->style()->colorSpace(), lastEffect->subRegion()); - } } filterData->sourceGraphicBuffer.clear(); diff --git a/WebCore/rendering/RenderSVGRoot.cpp b/WebCore/rendering/RenderSVGRoot.cpp index b66a870..3fd439c 100644 --- a/WebCore/rendering/RenderSVGRoot.cpp +++ b/WebCore/rendering/RenderSVGRoot.cpp @@ -48,6 +48,7 @@ namespace WebCore { RenderSVGRoot::RenderSVGRoot(SVGStyledElement* node) : RenderBox(node) , m_isLayoutSizeChanged(false) + , m_needsBoundariesOrTransformUpdate(true) { setReplaced(true); } @@ -124,6 +125,13 @@ void RenderSVGRoot::layout() SVGRenderSupport::layoutChildren(this, needsLayout); m_isLayoutSizeChanged = false; + // At this point LayoutRepainter already grabbed the old bounds, + // recalculate them now so repaintAfterLayout() uses the new bounds. + if (m_needsBoundariesOrTransformUpdate) { + updateCachedBoundaries(); + m_needsBoundariesOrTransformUpdate = false; + } + repainter.repaintAfterLayout(); view()->enableLayoutState(); @@ -196,6 +204,13 @@ void RenderSVGRoot::destroy() RenderBox::destroy(); } +void RenderSVGRoot::styleWillChange(StyleDifference diff, const RenderStyle* newStyle) +{ + if (diff == StyleDifferenceLayout) + setNeedsBoundariesUpdate(); + RenderBox::styleWillChange(diff, newStyle); +} + void RenderSVGRoot::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { RenderBox::styleDidChange(diff, oldStyle); @@ -267,24 +282,6 @@ const AffineTransform& RenderSVGRoot::localToParentTransform() const return m_localToParentTransform; } -FloatRect RenderSVGRoot::objectBoundingBox() const -{ - return SVGRenderSupport::computeContainerBoundingBox(this, SVGRenderSupport::ObjectBoundingBox); -} - -FloatRect RenderSVGRoot::strokeBoundingBox() const -{ - return SVGRenderSupport::computeContainerBoundingBox(this, SVGRenderSupport::StrokeBoundingBox); -} - -FloatRect RenderSVGRoot::repaintRectInLocalCoordinates() const -{ - FloatRect repaintRect = SVGRenderSupport::computeContainerBoundingBox(this, SVGRenderSupport::RepaintBoundingBox); - style()->svgStyle()->inflateForShadow(repaintRect); - repaintRect.inflate(borderAndPaddingWidth()); - return repaintRect; -} - IntRect RenderSVGRoot::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) { return SVGRenderSupport::clippedOverflowRectForRepaint(this, repaintContainer); @@ -299,7 +296,10 @@ void RenderSVGRoot::computeRectForRepaint(RenderBoxModelObject* repaintContainer // Apply initial viewport clip - not affected by overflow settings repaintRect.intersect(enclosingIntRect(FloatRect(FloatPoint(), m_viewportSize))); - style()->svgStyle()->inflateForShadow(repaintRect); + const SVGRenderStyle* svgStyle = style()->svgStyle(); + if (const ShadowData* shadow = svgStyle->shadow()) + shadow->adjustRectForShadow(repaintRect); + RenderBox::computeRectForRepaint(repaintContainer, repaintRect, fixed); } @@ -313,6 +313,17 @@ void RenderSVGRoot::mapLocalToContainer(RenderBoxModelObject* repaintContainer, RenderBox::mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState); } +void RenderSVGRoot::updateCachedBoundaries() +{ + m_objectBoundingBox = FloatRect(); + m_strokeBoundingBox = FloatRect(); + m_repaintBoundingBox = FloatRect(); + + SVGRenderSupport::computeContainerBoundingBoxes(this, m_objectBoundingBox, m_strokeBoundingBox, m_repaintBoundingBox); + SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingBox); + m_repaintBoundingBox.inflate(borderAndPaddingWidth()); +} + bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction) { IntPoint pointInContainer(_x, _y); diff --git a/WebCore/rendering/RenderSVGRoot.h b/WebCore/rendering/RenderSVGRoot.h index b90113c..63a7b3f 100644 --- a/WebCore/rendering/RenderSVGRoot.h +++ b/WebCore/rendering/RenderSVGRoot.h @@ -41,6 +41,8 @@ public: RenderObjectChildList* children() { return &m_children; } bool isLayoutSizeChanged() const { return m_isLayoutSizeChanged; } + virtual void setNeedsBoundariesUpdate() { m_needsBoundariesOrTransformUpdate = true; } + virtual void setNeedsTransformUpdate() { m_needsBoundariesOrTransformUpdate = true; } private: virtual RenderObjectChildList* virtualChildren() { return children(); } @@ -58,6 +60,7 @@ private: virtual void paint(PaintInfo&, int parentX, int parentY); virtual void destroy(); + virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle); virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); virtual void updateFromElement(); @@ -66,9 +69,9 @@ private: bool fillContains(const FloatPoint&) const; bool strokeContains(const FloatPoint&) const; - virtual FloatRect objectBoundingBox() const; - virtual FloatRect strokeBoundingBox() const; - virtual FloatRect repaintRectInLocalCoordinates() const; + virtual FloatRect objectBoundingBox() const { return m_objectBoundingBox; } + virtual FloatRect strokeBoundingBox() const { return m_strokeBoundingBox; } + virtual FloatRect repaintRectInLocalCoordinates() const { return m_repaintBoundingBox; } virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); @@ -80,6 +83,7 @@ private: void calcViewport(); bool selfWillPaint(); + void updateCachedBoundaries(); IntSize parentOriginToBorderBox() const; IntSize borderOriginToContentBox() const; @@ -88,8 +92,12 @@ private: RenderObjectChildList m_children; FloatSize m_viewportSize; + FloatRect m_objectBoundingBox; + FloatRect m_strokeBoundingBox; + FloatRect m_repaintBoundingBox; mutable AffineTransform m_localToParentTransform; bool m_isLayoutSizeChanged : 1; + bool m_needsBoundariesOrTransformUpdate : 1; }; inline RenderSVGRoot* toRenderSVGRoot(RenderObject* object) diff --git a/WebCore/rendering/RenderSVGShadowTreeRootContainer.cpp b/WebCore/rendering/RenderSVGShadowTreeRootContainer.cpp index 888dd57..d3064c6 100644 --- a/WebCore/rendering/RenderSVGShadowTreeRootContainer.cpp +++ b/WebCore/rendering/RenderSVGShadowTreeRootContainer.cpp @@ -53,7 +53,7 @@ void RenderSVGShadowTreeRootContainer::updateFromElement() SVGUseElement* useElement = static_cast<SVGUseElement*>(node()); if (!m_shadowRoot) { ASSERT(!m_recreateTree); - m_shadowRoot = new SVGShadowTreeRootElement(document(), useElement); + m_shadowRoot = SVGShadowTreeRootElement::create(document(), useElement); useElement->buildPendingResource(); } diff --git a/WebCore/rendering/RenderSVGText.cpp b/WebCore/rendering/RenderSVGText.cpp index 20c8a7c..80b8a91 100644 --- a/WebCore/rendering/RenderSVGText.cpp +++ b/WebCore/rendering/RenderSVGText.cpp @@ -75,10 +75,12 @@ void RenderSVGText::layout() ASSERT(needsLayout()); LayoutRepainter repainter(*this, m_everHadLayout && checkForRepaintDuringLayout()); + bool updateCachedBoundariesInParents = false; if (m_needsTransformUpdate) { SVGTextElement* text = static_cast<SVGTextElement*>(node()); m_localTransform = text->animatedLocalTransform(); m_needsTransformUpdate = false; + updateCachedBoundariesInParents = true; } // Reduced version of RenderBlock::layoutBlock(), which only takes care of SVG text. @@ -95,13 +97,22 @@ void RenderSVGText::layout() if (!firstChild()) setChildrenInline(true); + // FIXME: We need to find a way to only layout the child boxes, if needed. + FloatRect oldBoundaries = objectBoundingBox(); ASSERT(childrenInline()); forceLayoutInlineChildren(); + if (!updateCachedBoundariesInParents) + updateCachedBoundariesInParents = oldBoundaries != objectBoundingBox(); + // Invalidate all resources of this client if our layout changed. if (m_everHadLayout && selfNeedsLayout()) SVGResourcesCache::clientLayoutChanged(this); + // If our bounds changed, notify the parents. + if (updateCachedBoundariesInParents) + RenderSVGBlock::setNeedsBoundariesUpdate(); + repainter.repaintAfterLayout(); setNeedsLayout(false); } @@ -178,6 +189,9 @@ FloatRect RenderSVGText::repaintRectInLocalCoordinates() const FloatRect repaintRect = strokeBoundingBox(); SVGRenderSupport::intersectRepaintRectWithResources(this, repaintRect); + if (const ShadowData* textShadow = style()->textShadow()) + textShadow->adjustRectForShadow(repaintRect); + return repaintRect; } diff --git a/WebCore/rendering/RenderSVGTransformableContainer.cpp b/WebCore/rendering/RenderSVGTransformableContainer.cpp index 94b9eea..c7d2029 100644 --- a/WebCore/rendering/RenderSVGTransformableContainer.cpp +++ b/WebCore/rendering/RenderSVGTransformableContainer.cpp @@ -35,7 +35,7 @@ RenderSVGTransformableContainer::RenderSVGTransformableContainer(SVGStyledTransf { } -void RenderSVGTransformableContainer::calculateLocalTransform() +bool RenderSVGTransformableContainer::calculateLocalTransform() { SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node()); @@ -46,17 +46,18 @@ void RenderSVGTransformableContainer::calculateLocalTransform() } if (!element->hasTagName(SVGNames::gTag) || !static_cast<SVGGElement*>(element)->isShadowTreeContainerElement()) - return; + return needsUpdate; FloatSize translation = static_cast<SVGShadowTreeContainerElement*>(element)->containerTranslation(); if (translation.width() == 0 && translation.height() == 0) - return; + return needsUpdate; // FIXME: Could optimize this case for use to avoid refetching the animatedLocalTransform() here, if only the containerTranslation() changed. if (!needsUpdate) m_localTransform = element->animatedLocalTransform(); m_localTransform.translate(translation.width(), translation.height()); + return true; } } diff --git a/WebCore/rendering/RenderSVGTransformableContainer.h b/WebCore/rendering/RenderSVGTransformableContainer.h index e6de054..b63b91c 100644 --- a/WebCore/rendering/RenderSVGTransformableContainer.h +++ b/WebCore/rendering/RenderSVGTransformableContainer.h @@ -35,7 +35,7 @@ namespace WebCore { virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; } private: - virtual void calculateLocalTransform(); + virtual bool calculateLocalTransform(); virtual AffineTransform localTransform() const { return m_localTransform; } bool m_needsTransformUpdate : 1; diff --git a/WebCore/rendering/RenderSVGViewportContainer.cpp b/WebCore/rendering/RenderSVGViewportContainer.cpp index f314bde..ccf67fa 100644 --- a/WebCore/rendering/RenderSVGViewportContainer.cpp +++ b/WebCore/rendering/RenderSVGViewportContainer.cpp @@ -48,10 +48,15 @@ void RenderSVGViewportContainer::calcViewport() SVGElement* element = static_cast<SVGElement*>(node()); if (element->hasTagName(SVGNames::svgTag)) { SVGSVGElement* svg = static_cast<SVGSVGElement*>(element); + + FloatRect oldViewport = m_viewport; m_viewport = FloatRect(svg->x().value(svg) , svg->y().value(svg) , svg->width().value(svg) , svg->height().value(svg)); + + if (oldViewport != m_viewport) + setNeedsBoundariesUpdate(); } } diff --git a/WebCore/rendering/RenderScrollbar.cpp b/WebCore/rendering/RenderScrollbar.cpp index 7378056..e7a70a4 100644 --- a/WebCore/rendering/RenderScrollbar.cpp +++ b/WebCore/rendering/RenderScrollbar.cpp @@ -27,6 +27,7 @@ #include "RenderScrollbar.h" #include "Frame.h" +#include "FrameView.h" #include "RenderPart.h" #include "RenderScrollbarPart.h" #include "RenderScrollbarTheme.h" @@ -150,6 +151,14 @@ PassRefPtr<RenderStyle> RenderScrollbar::getScrollbarPseudoStyle(ScrollbarPart p RefPtr<RenderStyle> result = owningRenderer()->getUncachedPseudoStyle(pseudoId, owningRenderer()->style()); s_styleResolvePart = NoPart; s_styleResolveScrollbar = 0; + + // Scrollbars for root frames should always have background color + // unless explicitly specified as transparent. So we force it. + // This is because WebKit assumes scrollbar to be always painted and missing background + // causes visual artifact like non-repainted dirty region. + if (result && m_owningFrame && m_owningFrame->view() && !m_owningFrame->view()->isTransparent() && !result->hasBackground()) + result->setBackgroundColor(Color::white); + return result; } diff --git a/WebCore/rendering/RenderTable.cpp b/WebCore/rendering/RenderTable.cpp index f9f0f56..48f3920 100644 --- a/WebCore/rendering/RenderTable.cpp +++ b/WebCore/rendering/RenderTable.cpp @@ -392,7 +392,7 @@ void RenderTable::layout() toRenderTableSection(child)->layoutRows(child == m_firstBody ? max(0, th - calculatedHeight) : 0); } - if (!m_firstBody && th > calculatedHeight && !style()->htmlHacks()) { + if (!m_firstBody && th > calculatedHeight && !document()->inQuirksMode()) { // Completely empty tables (with no sections or anything) should at least honor specified height // in strict mode. setHeight(height() + th); diff --git a/WebCore/rendering/RenderTableSection.cpp b/WebCore/rendering/RenderTableSection.cpp index 8cb54c0..a9052ce 100644 --- a/WebCore/rendering/RenderTableSection.cpp +++ b/WebCore/rendering/RenderTableSection.cpp @@ -386,7 +386,7 @@ int RenderTableSection::calcRowHeight() // Explicit heights use the border box in quirks mode. In strict mode do the right // thing and actually add in the border and padding. ch = cell->style()->height().calcValue(0) + - (cell->style()->htmlHacks() ? 0 : (adjustedPaddingTop + adjustedPaddingBottom + + (document()->inQuirksMode() ? 0 : (adjustedPaddingTop + adjustedPaddingBottom + cell->borderTop() + cell->borderBottom())); ch = max(ch, adjustedHeight); diff --git a/WebCore/rendering/RenderTextControl.cpp b/WebCore/rendering/RenderTextControl.cpp index 9098bab..e66e4ed 100644 --- a/WebCore/rendering/RenderTextControl.cpp +++ b/WebCore/rendering/RenderTextControl.cpp @@ -355,26 +355,22 @@ String RenderTextControl::textWithHardLineBreaks() { if (!m_innerText) return ""; - Node* firstChild = m_innerText->firstChild(); - if (!firstChild) - return ""; - RenderObject* renderer = firstChild->renderer(); + RenderBlock* renderer = toRenderBlock(m_innerText->renderer()); if (!renderer) return ""; - InlineBox* box = renderer->isText() ? toRenderText(renderer)->firstTextBox() : toRenderBox(renderer)->inlineBoxWrapper(); - if (!box) - return ""; - Node* breakNode; unsigned breakOffset; - RootInlineBox* line = box->root(); + RootInlineBox* line = renderer->firstRootBox(); + if (!line) + return ""; + getNextSoftBreak(line, breakNode, breakOffset); Vector<UChar> result; - for (Node* n = firstChild; n; n = n->traverseNextNode(m_innerText.get())) { + for (Node* n = m_innerText->firstChild(); n; n = n->traverseNextNode(m_innerText.get())) { if (n->hasTagName(brTag)) result.append(&newlineCharacter, 1); else if (n->isTextNode()) { diff --git a/WebCore/rendering/RenderTextControlSingleLine.h b/WebCore/rendering/RenderTextControlSingleLine.h index e57e37e..0deb063 100644 --- a/WebCore/rendering/RenderTextControlSingleLine.h +++ b/WebCore/rendering/RenderTextControlSingleLine.h @@ -82,7 +82,7 @@ private: virtual int scrollHeight() const; virtual void setScrollLeft(int); virtual void setScrollTop(int); - virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1.0f, Node** stopNode = 0); + virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1, Node** stopNode = 0); int textBlockWidth() const; virtual float getAvgCharWidth(AtomicString family); diff --git a/WebCore/rendering/RenderTheme.cpp b/WebCore/rendering/RenderTheme.cpp index 5d00f5a..522bd4d 100644 --- a/WebCore/rendering/RenderTheme.cpp +++ b/WebCore/rendering/RenderTheme.cpp @@ -1043,7 +1043,7 @@ void RenderTheme::platformColorsDidChange() m_activeListBoxSelectionBackgroundColor = Color(); m_inactiveListBoxSelectionForegroundColor = Color(); - Page::setNeedsReapplyStyles(); + Page::scheduleForcedStyleRecalcForAllPages(); } Color RenderTheme::systemColor(int cssValueId) const diff --git a/WebCore/rendering/RenderVideo.cpp b/WebCore/rendering/RenderVideo.cpp index 0f444b2..3f4e2bf 100644 --- a/WebCore/rendering/RenderVideo.cpp +++ b/WebCore/rendering/RenderVideo.cpp @@ -110,7 +110,7 @@ IntSize RenderVideo::calculateIntrinsicSize() if (player() && video->readyState() >= HTMLVideoElement::HAVE_METADATA) return player()->naturalSize(); - if (video->shouldDisplayPosterImage() && !m_cachedImageSize.isEmpty() && !errorOccurred()) + if (video->shouldDisplayPosterImage() && !m_cachedImageSize.isEmpty() && !imageResource()->errorOccurred()) return m_cachedImageSize; // When the natural size of the video is unavailable, we use the provided diff --git a/WebCore/rendering/RootInlineBox.cpp b/WebCore/rendering/RootInlineBox.cpp index bec288c..e8f24b5 100644 --- a/WebCore/rendering/RootInlineBox.cpp +++ b/WebCore/rendering/RootInlineBox.cpp @@ -215,14 +215,10 @@ int RootInlineBox::verticallyAlignBoxes(int heightOfBlock, GlyphOverflowAndFallb int maxAscent = 0; int maxDescent = 0; - // Figure out if we're in strict mode. Note that we can't simply use !style()->htmlHacks(), - // because that would match almost strict mode as well. - RenderObject* curr = renderer(); - while (curr && !curr->node()) - curr = curr->container(); - bool strictMode = (curr && curr->document()->inStrictMode()); + // Figure out if we're in no-quirks mode. + bool noQuirksMode = renderer()->document()->inNoQuirksMode(); - computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode, textBoxDataMap); + computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, noQuirksMode, textBoxDataMap); if (maxAscent + maxDescent < max(maxPositionTop, maxPositionBottom)) adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom); @@ -230,8 +226,8 @@ int RootInlineBox::verticallyAlignBoxes(int heightOfBlock, GlyphOverflowAndFallb int maxHeight = maxAscent + maxDescent; int lineTop = heightOfBlock; int lineBottom = heightOfBlock; - placeBoxesVertically(heightOfBlock, maxHeight, maxAscent, strictMode, lineTop, lineBottom); - computeVerticalOverflow(lineTop, lineBottom, strictMode, textBoxDataMap); + placeBoxesVertically(heightOfBlock, maxHeight, maxAscent, noQuirksMode, lineTop, lineBottom); + computeVerticalOverflow(lineTop, lineBottom, noQuirksMode, textBoxDataMap); setLineTopBottomPositions(lineTop, lineBottom); heightOfBlock += maxHeight; diff --git a/WebCore/rendering/SVGRenderSupport.cpp b/WebCore/rendering/SVGRenderSupport.cpp index 12d6d77..644ff70 100644 --- a/WebCore/rendering/SVGRenderSupport.cpp +++ b/WebCore/rendering/SVGRenderSupport.cpp @@ -61,7 +61,9 @@ IntRect SVGRenderSupport::clippedOverflowRectForRepaint(RenderObject* object, Re void SVGRenderSupport::computeRectForRepaint(RenderObject* object, RenderBoxModelObject* repaintContainer, IntRect& repaintRect, bool fixed) { - object->style()->svgStyle()->inflateForShadow(repaintRect); + const SVGRenderStyle* svgStyle = object->style()->svgStyle(); + if (const ShadowData* shadow = svgStyle->shadow()) + shadow->adjustRectForShadow(repaintRect); // Translate to coords in our parent renderer, and then call computeRectForRepaint on our parent repaintRect = object->localToParentTransform().mapRect(repaintRect); @@ -86,24 +88,22 @@ bool SVGRenderSupport::prepareToRenderSVGContent(RenderObject* object, PaintInfo const SVGRenderStyle* svgStyle = style->svgStyle(); ASSERT(svgStyle); - FloatRect repaintRect; - // Setup transparency layers before setting up SVG resources! float opacity = style->opacity(); - if (opacity < 1) { - repaintRect = object->repaintRectInLocalCoordinates(); - paintInfo.context->clip(repaintRect); - paintInfo.context->beginTransparencyLayer(opacity); - } + const ShadowData* shadow = svgStyle->shadow(); + if (opacity < 1 || shadow) { + FloatRect repaintRect = object->repaintRectInLocalCoordinates(); - if (const ShadowData* shadow = svgStyle->shadow()) { - // Eventually compute repaint rect, if not done so far. - if (opacity >= 1) - repaintRect = object->repaintRectInLocalCoordinates(); + if (opacity < 1) { + paintInfo.context->clip(repaintRect); + paintInfo.context->beginTransparencyLayer(opacity); + } - paintInfo.context->clip(repaintRect); - paintInfo.context->setShadow(IntSize(shadow->x(), shadow->y()), shadow->blur(), shadow->color(), style->colorSpace()); - paintInfo.context->beginTransparencyLayer(1); + if (shadow) { + paintInfo.context->clip(repaintRect); + paintInfo.context->setShadow(IntSize(shadow->x(), shadow->y()), shadow->blur(), shadow->color(), style->colorSpace()); + paintInfo.context->beginTransparencyLayer(1); + } } SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object); @@ -154,39 +154,38 @@ void SVGRenderSupport::finishRenderSVGContent(RenderObject* object, PaintInfo& p } #endif - float opacity = style->opacity(); - if (opacity < 1) + if (style->opacity() < 1) paintInfo.context->endTransparencyLayer(); - // This needs to be done separately from opacity, because if both properties are set, - // then the transparency layers are nested. if (svgStyle->shadow()) paintInfo.context->endTransparencyLayer(); } -FloatRect SVGRenderSupport::computeContainerBoundingBox(const RenderObject* container, ContainerBoundingBoxMode mode) +void SVGRenderSupport::computeContainerBoundingBoxes(const RenderObject* container, FloatRect& objectBoundingBox, FloatRect& strokeBoundingBox, FloatRect& repaintBoundingBox) { - FloatRect boundingBox; - for (RenderObject* current = container->firstChild(); current; current = current->nextSibling()) { - FloatRect childBoundingBox; - - switch (mode) { - case ObjectBoundingBox: - childBoundingBox = current->objectBoundingBox(); - break; - case StrokeBoundingBox: - childBoundingBox = current->strokeBoundingBox(); - break; - case RepaintBoundingBox: - childBoundingBox = current->repaintRectInLocalCoordinates(); - break; + if (current->isSVGHiddenContainer()) + continue; + + const AffineTransform& transform = current->localToParentTransform(); + if (transform.isIdentity()) { + objectBoundingBox.unite(current->objectBoundingBox()); + strokeBoundingBox.unite(current->strokeBoundingBox()); + repaintBoundingBox.unite(current->repaintRectInLocalCoordinates()); + } else { + objectBoundingBox.unite(transform.mapRect(current->objectBoundingBox())); + strokeBoundingBox.unite(transform.mapRect(current->strokeBoundingBox())); + repaintBoundingBox.unite(transform.mapRect(current->repaintRectInLocalCoordinates())); } - - boundingBox.unite(current->localToParentTransform().mapRect(childBoundingBox)); } +} + +bool SVGRenderSupport::paintInfoIntersectsRepaintRect(const FloatRect& localRepaintRect, const AffineTransform& localTransform, const PaintInfo& paintInfo) +{ + if (localTransform.isIdentity()) + return localRepaintRect.intersects(paintInfo.rect); - return boundingBox; + return localTransform.mapRect(localRepaintRect).intersects(paintInfo.rect); } const RenderSVGRoot* SVGRenderSupport::findTreeRootObject(const RenderObject* start) @@ -281,7 +280,8 @@ void SVGRenderSupport::intersectRepaintRectWithResources(const RenderObject* obj RenderObject* renderer = const_cast<RenderObject*>(object); SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer); if (!resources) { - svgStyle->inflateForShadow(repaintRect); + if (const ShadowData* shadow = svgStyle->shadow()) + shadow->adjustRectForShadow(repaintRect); return; } @@ -296,7 +296,8 @@ void SVGRenderSupport::intersectRepaintRectWithResources(const RenderObject* obj if (RenderSVGResourceMasker* masker = resources->masker()) repaintRect.intersect(masker->resourceBoundingBox(renderer)); - svgStyle->inflateForShadow(repaintRect); + if (const ShadowData* shadow = svgStyle->shadow()) + shadow->adjustRectForShadow(repaintRect); } bool SVGRenderSupport::pointInClippingArea(RenderObject* object, const FloatPoint& point) diff --git a/WebCore/rendering/SVGRenderSupport.h b/WebCore/rendering/SVGRenderSupport.h index 2de1e99..54622d2 100644 --- a/WebCore/rendering/SVGRenderSupport.h +++ b/WebCore/rendering/SVGRenderSupport.h @@ -58,15 +58,8 @@ public: // Determines whether the passed point lies in a clipping area static bool pointInClippingArea(RenderObject*, const FloatPoint&); - enum ContainerBoundingBoxMode { - ObjectBoundingBox, - StrokeBoundingBox, - RepaintBoundingBox - }; - - // Used to share the "walk all the children" logic between objectBoundingBox - // and repaintRectInLocalCoordinates in RenderSVGRoot and RenderSVGContainer - static FloatRect computeContainerBoundingBox(const RenderObject* container, ContainerBoundingBoxMode); + static void computeContainerBoundingBoxes(const RenderObject* container, FloatRect& objectBoundingBox, FloatRect& strokeBoundingBox, FloatRect& repaintBoundingBox); + static bool paintInfoIntersectsRepaintRect(const FloatRect& localRepaintRect, const AffineTransform& localTransform, const PaintInfo& paintInfo); // Important functions used by nearly all SVG renderers centralizing coordinate transformations / repaint rect calculations static IntRect clippedOverflowRectForRepaint(RenderObject*, RenderBoxModelObject* repaintContainer); diff --git a/WebCore/rendering/SVGResources.h b/WebCore/rendering/SVGResources.h index 5f6e746..49591cf 100644 --- a/WebCore/rendering/SVGResources.h +++ b/WebCore/rendering/SVGResources.h @@ -38,7 +38,7 @@ class RenderSVGResourceMasker; class SVGRenderStyle; // Holds a set of resources associated with a RenderObject -class SVGResources { +class SVGResources : public Noncopyable { public: SVGResources(); diff --git a/WebCore/rendering/SVGResourcesCache.cpp b/WebCore/rendering/SVGResourcesCache.cpp index a4089d6..88cbb3a 100644 --- a/WebCore/rendering/SVGResourcesCache.cpp +++ b/WebCore/rendering/SVGResourcesCache.cpp @@ -34,11 +34,7 @@ SVGResourcesCache::SVGResourcesCache() SVGResourcesCache::~SVGResourcesCache() { - if (m_cache.isEmpty()) - return; - deleteAllValues(m_cache); - m_cache.clear(); } void SVGResourcesCache::addResourcesFromRenderObject(RenderObject* object, const RenderStyle* style) diff --git a/WebCore/rendering/SVGShadowTreeElements.cpp b/WebCore/rendering/SVGShadowTreeElements.cpp index 311874c..8a66991 100644 --- a/WebCore/rendering/SVGShadowTreeElements.cpp +++ b/WebCore/rendering/SVGShadowTreeElements.cpp @@ -26,17 +26,20 @@ #include "FloatSize.h" #include "RenderObject.h" #include "SVGNames.h" +#include "SVGUseElement.h" namespace WebCore { // SVGShadowTreeContainerElement + SVGShadowTreeContainerElement::SVGShadowTreeContainerElement(Document* document) : SVGGElement(SVGNames::gTag, document) { } - -SVGShadowTreeContainerElement::~SVGShadowTreeContainerElement() + +PassRefPtr<SVGShadowTreeContainerElement> SVGShadowTreeContainerElement::create(Document* document) { + return adoptRef(new SVGShadowTreeContainerElement(document)); } FloatSize SVGShadowTreeContainerElement::containerTranslation() const @@ -45,15 +48,17 @@ FloatSize SVGShadowTreeContainerElement::containerTranslation() const } // SVGShadowTreeRootElement -SVGShadowTreeRootElement::SVGShadowTreeRootElement(Document* document, Element* shadowParent) + +inline SVGShadowTreeRootElement::SVGShadowTreeRootElement(Document* document, SVGUseElement* shadowParent) : SVGShadowTreeContainerElement(document) , m_shadowParent(shadowParent) { setInDocument(); } -SVGShadowTreeRootElement::~SVGShadowTreeRootElement() +PassRefPtr<SVGShadowTreeRootElement> SVGShadowTreeRootElement::create(Document* document, SVGUseElement* shadowParent) { + return adoptRef(new SVGShadowTreeRootElement(document, shadowParent)); } void SVGShadowTreeRootElement::attachElement(PassRefPtr<RenderStyle> style, RenderArena* arena) diff --git a/WebCore/rendering/SVGShadowTreeElements.h b/WebCore/rendering/SVGShadowTreeElements.h index 7611b8a..d49fbaa 100644 --- a/WebCore/rendering/SVGShadowTreeElements.h +++ b/WebCore/rendering/SVGShadowTreeElements.h @@ -27,13 +27,11 @@ namespace WebCore { class FloatSize; +class SVGUseElement; class SVGShadowTreeContainerElement : public SVGGElement { public: - SVGShadowTreeContainerElement(Document*); - virtual ~SVGShadowTreeContainerElement(); - - virtual bool isShadowTreeContainerElement() const { return true; } + static PassRefPtr<SVGShadowTreeContainerElement> create(Document*); FloatSize containerTranslation() const; void setContainerOffset(const SVGLength& x, const SVGLength& y) @@ -42,22 +40,29 @@ public: m_yOffset = y; } +protected: + SVGShadowTreeContainerElement(Document*); + private: + virtual bool isShadowTreeContainerElement() const { return true; } + SVGLength m_xOffset; SVGLength m_yOffset; }; class SVGShadowTreeRootElement : public SVGShadowTreeContainerElement { public: - SVGShadowTreeRootElement(Document*, Element* shadowParent); - virtual ~SVGShadowTreeRootElement(); - - virtual bool isShadowNode() const { return m_shadowParent; } - virtual ContainerNode* shadowParentNode() { return m_shadowParent; } + static PassRefPtr<SVGShadowTreeRootElement> create(Document*, SVGUseElement* shadowParent); void attachElement(PassRefPtr<RenderStyle>, RenderArena*); + virtual ContainerNode* shadowParentNode() { return m_shadowParent; } + private: + SVGShadowTreeRootElement(Document*, SVGUseElement* shadowParent); + + virtual bool isShadowNode() const { return m_shadowParent; } + ContainerNode* m_shadowParent; }; diff --git a/WebCore/rendering/style/BorderData.h b/WebCore/rendering/style/BorderData.h index 96caf97..03635d9 100644 --- a/WebCore/rendering/style/BorderData.h +++ b/WebCore/rendering/style/BorderData.h @@ -26,7 +26,7 @@ #define BorderData_h #include "BorderValue.h" -#include "IntSize.h" +#include "LengthSize.h" #include "NinePieceImage.h" namespace WebCore { @@ -34,6 +34,12 @@ namespace WebCore { class BorderData { friend class RenderStyle; public: + BorderData() : m_topLeft(Length(0, Fixed), Length(0, Fixed)) + , m_topRight(Length(0, Fixed), Length(0, Fixed)) + , m_bottomLeft(Length(0, Fixed), Length(0, Fixed)) + , m_bottomRight(Length(0, Fixed), Length(0, Fixed)) + { + } bool hasBorder() const { bool haveImage = m_image.hasImage(); @@ -42,13 +48,13 @@ public: bool hasBorderRadius() const { - if (m_topLeft.width() > 0) + if (m_topLeft.width().rawValue() > 0) return true; - if (m_topRight.width() > 0) + if (m_topRight.width().rawValue() > 0) return true; - if (m_bottomLeft.width() > 0) + if (m_bottomLeft.width().rawValue() > 0) return true; - if (m_bottomRight.width() > 0) + if (m_bottomRight.width().rawValue() > 0) return true; return false; } @@ -99,10 +105,10 @@ public: const NinePieceImage& image() const { return m_image; } - const IntSize& topLeft() const { return m_topLeft; } - const IntSize& topRight() const { return m_topRight; } - const IntSize& bottomLeft() const { return m_bottomLeft; } - const IntSize& bottomRight() const { return m_bottomRight; } + const LengthSize& topLeft() const { return m_topLeft; } + const LengthSize& topRight() const { return m_topRight; } + const LengthSize& bottomLeft() const { return m_bottomLeft; } + const LengthSize& bottomRight() const { return m_bottomRight; } private: BorderValue m_left; @@ -112,10 +118,10 @@ private: NinePieceImage m_image; - IntSize m_topLeft; - IntSize m_topRight; - IntSize m_bottomLeft; - IntSize m_bottomRight; + LengthSize m_topLeft; + LengthSize m_topRight; + LengthSize m_bottomLeft; + LengthSize m_bottomRight; }; } // namespace WebCore diff --git a/WebCore/rendering/style/ContentData.cpp b/WebCore/rendering/style/ContentData.cpp index b0f9e81..d150f77 100644 --- a/WebCore/rendering/style/ContentData.cpp +++ b/WebCore/rendering/style/ContentData.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 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 @@ -22,7 +22,6 @@ #include "config.h" #include "ContentData.h" -#include "CounterContent.h" #include "StyleImage.h" #include <wtf/text/StringImpl.h> @@ -32,42 +31,26 @@ void ContentData::clear() { deleteContent(); - ContentData* n = m_next; - m_next = 0; - - // Reverse the list so we can delete without recursing. - ContentData* last = 0; - ContentData* c; - while ((c = n)) { - n = c->m_next; - c->m_next = last; - last = c; - } - for (c = last; c; c = n) { - n = c->m_next; - c->m_next = 0; - delete c; - } + // Delete the singly-linked list without recursing. + for (OwnPtr<ContentData> next = m_next.release(); next; next = next->m_next.release()) { } } +// FIXME: Why isn't this just operator==? +// FIXME: This is not a good name for a boolean-returning function. bool ContentData::dataEquivalent(const ContentData& other) const { if (type() != other.type()) return false; switch (type()) { - case CONTENT_NONE: - return true; - break; - case CONTENT_TEXT: - return equal(text(), other.text()); - break; - case CONTENT_OBJECT: - return StyleImage::imagesEquivalent(image(), other.image()); - break; - case CONTENT_COUNTER: - return *counter() == *other.counter(); - break; + case CONTENT_NONE: + return true; + case CONTENT_TEXT: + return equal(text(), other.text()); + case CONTENT_OBJECT: + return StyleImage::imagesEquivalent(image(), other.image()); + case CONTENT_COUNTER: + return *counter() == *other.counter(); } ASSERT_NOT_REACHED(); @@ -77,17 +60,17 @@ bool ContentData::dataEquivalent(const ContentData& other) const void ContentData::deleteContent() { switch (m_type) { - case CONTENT_NONE: - break; - case CONTENT_OBJECT: - m_content.m_image->deref(); - break; - case CONTENT_TEXT: - m_content.m_text->deref(); - break; - case CONTENT_COUNTER: - delete m_content.m_counter; - break; + case CONTENT_NONE: + break; + case CONTENT_OBJECT: + m_content.m_image->deref(); + break; + case CONTENT_TEXT: + m_content.m_text->deref(); + break; + case CONTENT_COUNTER: + delete m_content.m_counter; + break; } m_type = CONTENT_NONE; diff --git a/WebCore/rendering/style/ContentData.h b/WebCore/rendering/style/ContentData.h index 5c3565e..4f964a2 100644 --- a/WebCore/rendering/style/ContentData.h +++ b/WebCore/rendering/style/ContentData.h @@ -2,7 +2,7 @@ * Copyright (C) 2000 Lars Knoll (knoll@kde.org) * (C) 2000 Antti Koivisto (koivisto@kde.org) * (C) 2000 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com) * * This library is free software; you can redistribute it and/or @@ -25,21 +25,18 @@ #ifndef ContentData_h #define ContentData_h -#include "RenderStyleConstants.h" -#include <wtf/Forward.h> -#include <wtf/Noncopyable.h> -#include <wtf/PassRefPtr.h> +#include "CounterContent.h" +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> namespace WebCore { -class CounterContent; class StyleImage; struct ContentData : Noncopyable { public: ContentData() : m_type(CONTENT_NONE) - , m_next(0) { } @@ -59,35 +56,44 @@ public: bool dataEquivalent(const ContentData&) const; - StyleImage* image() const { return m_content.m_image; } + StyleImage* image() const + { + ASSERT(isImage()); + return m_content.m_image; + } void setImage(PassRefPtr<StyleImage> image) { deleteContent(); m_type = CONTENT_OBJECT; - m_content.m_image = image.releaseRef(); + m_content.m_image = image.leakRef(); } - StringImpl* text() const { return m_content.m_text; } + StringImpl* text() const + { + ASSERT(isText()); + return m_content.m_text; + } void setText(PassRefPtr<StringImpl> text) { deleteContent(); m_type = CONTENT_TEXT; - m_content.m_text = text.releaseRef(); + m_content.m_text = text.leakRef(); } - CounterContent* counter() const { return m_content.m_counter; } - void setCounter(CounterContent* counter) + CounterContent* counter() const + { + ASSERT(isCounter()); + return m_content.m_counter; + } + void setCounter(PassOwnPtr<CounterContent> counter) { deleteContent(); m_type = CONTENT_COUNTER; - m_content.m_counter = counter; + m_content.m_counter = counter.leakPtr(); } - ContentData* next() const { return m_next; } - void setNext(ContentData* next) - { - m_next = next; - } + ContentData* next() const { return m_next.get(); } + void setNext(PassOwnPtr<ContentData> next) { m_next = next; } private: void deleteContent(); @@ -98,7 +104,7 @@ private: StringImpl* m_text; CounterContent* m_counter; } m_content; - ContentData* m_next; + OwnPtr<ContentData> m_next; }; } // namespace WebCore diff --git a/WebCore/rendering/style/CursorData.h b/WebCore/rendering/style/CursorData.h index 2341e71..6d0a273 100644 --- a/WebCore/rendering/style/CursorData.h +++ b/WebCore/rendering/style/CursorData.h @@ -25,15 +25,14 @@ #ifndef CursorData_h #define CursorData_h -#include "CachedImage.h" -#include "CachedResourceHandle.h" #include "IntPoint.h" +#include "StyleImage.h" namespace WebCore { class CursorData { public: - CursorData(CachedImage* image, const IntPoint& hotSpot) + CursorData(PassRefPtr<StyleImage> image, const IntPoint& hotSpot) : m_image(image) , m_hotSpot(hotSpot) { @@ -49,11 +48,13 @@ public: return !(*this == o); } - const CachedImage* image() const { return m_image.get(); } + StyleImage* image() const { return m_image.get(); } + void setImage(PassRefPtr<StyleImage> image) { m_image = image; } + const IntPoint& hotSpot() const { return m_hotSpot; } private: - CachedResourceHandle<CachedImage> m_image; + RefPtr<StyleImage> m_image; IntPoint m_hotSpot; // for CSS3 support }; diff --git a/WebCore/rendering/style/CursorList.h b/WebCore/rendering/style/CursorList.h index bdd65d4..1b82684 100644 --- a/WebCore/rendering/style/CursorList.h +++ b/WebCore/rendering/style/CursorList.h @@ -39,6 +39,7 @@ public: } const CursorData& operator[](int i) const { return m_vector[i]; } + CursorData& operator[](int i) { return m_vector[i]; } bool operator==(const CursorList& o) const { return m_vector == o.m_vector; } bool operator!=(const CursorList& o) const { return m_vector != o.m_vector; } diff --git a/WebCore/rendering/style/KeyframeList.cpp b/WebCore/rendering/style/KeyframeList.cpp index 41fbbe2..bafa426 100644 --- a/WebCore/rendering/style/KeyframeList.cpp +++ b/WebCore/rendering/style/KeyframeList.cpp @@ -43,10 +43,10 @@ bool KeyframeList::operator==(const KeyframeList& o) const Vector<KeyframeValue>::const_iterator it2 = o.m_keyframes.begin(); for (Vector<KeyframeValue>::const_iterator it1 = m_keyframes.begin(); it1 != m_keyframes.end(); ++it1) { - if (it1->m_key != it2->m_key) + if (it1->key() != it2->key()) return false; - const RenderStyle& style1 = *it1->m_style; - const RenderStyle& style2 = *it2->m_style; + const RenderStyle& style1 = *it1->style(); + const RenderStyle& style2 = *it2->style(); if (style1 != style2) return false; ++it2; @@ -55,34 +55,43 @@ bool KeyframeList::operator==(const KeyframeList& o) const return true; } -void KeyframeList::insert(float key, PassRefPtr<RenderStyle> style) +void KeyframeList::insert(const KeyframeValue& keyframe) { - if (key < 0 || key > 1) + if (keyframe.key() < 0 || keyframe.key() > 1) return; - int index = -1; - + bool inserted = false; + bool replaced = false; for (size_t i = 0; i < m_keyframes.size(); ++i) { - if (m_keyframes[i].m_key == key) { - index = (int) i; + if (m_keyframes[i].key() == keyframe.key()) { + m_keyframes[i] = keyframe; + replaced = true; break; } - if (m_keyframes[i].m_key > key) { + + if (m_keyframes[i].key() > keyframe.key()) { // insert before - m_keyframes.insert(i, KeyframeValue()); - index = (int) i; + m_keyframes.insert(i, keyframe); + inserted = true; break; } } - if (index < 0) { - // append - index = (int) m_keyframes.size(); - m_keyframes.append(KeyframeValue()); + if (!replaced && !inserted) + m_keyframes.append(keyframe); + + if (replaced) { + // We have to rebuild the properties list from scratch. + m_properties.clear(); + for (Vector<KeyframeValue>::const_iterator it = m_keyframes.begin(); it != m_keyframes.end(); ++it) { + const KeyframeValue& currKeyframe = *it; + for (HashSet<int>::const_iterator it = currKeyframe.properties().begin(); it != currKeyframe.properties().end(); ++it) + m_properties.add(*it); + } + } else { + for (HashSet<int>::const_iterator it = keyframe.properties().begin(); it != keyframe.properties().end(); ++it) + m_properties.add(*it); } - - m_keyframes[index].m_key = key; - m_keyframes[index].m_style = style; } } // namespace WebCore diff --git a/WebCore/rendering/style/KeyframeList.h b/WebCore/rendering/style/KeyframeList.h index bb5f180..64170ce 100644 --- a/WebCore/rendering/style/KeyframeList.h +++ b/WebCore/rendering/style/KeyframeList.h @@ -37,15 +37,25 @@ class RenderStyle; class KeyframeValue { public: - KeyframeValue() - : m_key(-1) + KeyframeValue(float key, PassRefPtr<RenderStyle> style) + : m_key(key) + , m_style(style) { } + void addProperty(int prop) { m_properties.add(prop); } + bool containsProperty(int prop) const { return m_properties.contains(prop); } + const HashSet<int>& properties() const { return m_properties; } + float key() const { return m_key; } + void setKey(float key) { m_key = key; } + const RenderStyle* style() const { return m_style.get(); } + void setStyle(PassRefPtr<RenderStyle> style) { m_style = style; } +private: float m_key; + HashSet<int> m_properties; // The properties specified in this keyframe. RefPtr<RenderStyle> m_style; }; @@ -55,8 +65,8 @@ public: : m_animationName(animationName) , m_renderer(renderer) { - insert(0, 0); - insert(1, 0); + insert(KeyframeValue(0, 0)); + insert(KeyframeValue(1, 0)); } ~KeyframeList(); @@ -65,7 +75,7 @@ public: const AtomicString& animationName() const { return m_animationName; } - void insert(float key, PassRefPtr<RenderStyle> style); + void insert(const KeyframeValue& keyframe); void addProperty(int prop) { m_properties.add(prop); } bool containsProperty(int prop) const { return m_properties.contains(prop); } @@ -75,13 +85,12 @@ public: void clear(); bool isEmpty() const { return m_keyframes.isEmpty(); } size_t size() const { return m_keyframes.size(); } - Vector<KeyframeValue>::const_iterator beginKeyframes() const { return m_keyframes.begin(); } - Vector<KeyframeValue>::const_iterator endKeyframes() const { return m_keyframes.end(); } + const KeyframeValue& operator[](size_t index) const { return m_keyframes[index]; } private: AtomicString m_animationName; - Vector<KeyframeValue> m_keyframes; - HashSet<int> m_properties; // the properties being animated + Vector<KeyframeValue> m_keyframes; // kept sorted by key + HashSet<int> m_properties; // the properties being animated RenderObject* m_renderer; }; diff --git a/WebCore/rendering/style/RenderStyle.cpp b/WebCore/rendering/style/RenderStyle.cpp index aaccbf7..93cd8de 100644 --- a/WebCore/rendering/style/RenderStyle.cpp +++ b/WebCore/rendering/style/RenderStyle.cpp @@ -24,8 +24,6 @@ #include "CSSPropertyNames.h" #include "CSSStyleSelector.h" -#include "CachedImage.h" -#include "CounterContent.h" #include "FontSelector.h" #include "RenderArena.h" #include "RenderObject.h" @@ -403,7 +401,6 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon inherited->vertical_border_spacing != other->inherited->vertical_border_spacing || inherited_flags._box_direction != other->inherited_flags._box_direction || inherited_flags._visuallyOrdered != other->inherited_flags._visuallyOrdered || - inherited_flags._htmlHacks != other->inherited_flags._htmlHacks || noninherited_flags._position != other->noninherited_flags._position || noninherited_flags._floating != other->noninherited_flags._floating || noninherited_flags._originalDisplay != other->noninherited_flags._originalDisplay) @@ -552,7 +549,7 @@ void RenderStyle::setClip(Length top, Length right, Length bottom, Length left) data->clip.m_left = left; } -void RenderStyle::addCursor(CachedImage* image, const IntPoint& hotSpot) +void RenderStyle::addCursor(PassRefPtr<StyleImage> image, const IntPoint& hotSpot) { if (!rareInheritedData.access()->cursorData) rareInheritedData.access()->cursorData = CursorList::create(); @@ -576,92 +573,59 @@ void RenderStyle::clearContent() rareNonInheritedData->m_content->clear(); } -void RenderStyle::setContent(PassRefPtr<StyleImage> image, bool add) +ContentData* RenderStyle::prepareToSetContent(StringImpl* string, bool add) { - if (!image) - return; // The object is null. Nothing to do. Just bail. - OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content; ContentData* lastContent = content.get(); while (lastContent && lastContent->next()) lastContent = lastContent->next(); + if (string && add && lastContent && lastContent->isText()) { + // Augment the existing string and share the existing ContentData node. + String newText = lastContent->text(); + newText.append(string); + lastContent->setText(newText.impl()); + return 0; + } + bool reuseContent = !add; - ContentData* newContentData; + OwnPtr<ContentData> newContentData; if (reuseContent && content) { content->clear(); - newContentData = content.leakPtr(); + newContentData = content.release(); } else - newContentData = new ContentData; + newContentData = adoptPtr(new ContentData); + + ContentData* result = newContentData.get(); if (lastContent && !reuseContent) - lastContent->setNext(newContentData); + lastContent->setNext(newContentData.release()); else - content.set(newContentData); + content = newContentData.release(); - newContentData->setImage(image); + return result; } -void RenderStyle::setContent(PassRefPtr<StringImpl> s, bool add) +void RenderStyle::setContent(PassRefPtr<StyleImage> image, bool add) { - if (!s) - return; // The string is null. Nothing to do. Just bail. - - OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content; - ContentData* lastContent = content.get(); - while (lastContent && lastContent->next()) - lastContent = lastContent->next(); - - bool reuseContent = !add; - if (add && lastContent) { - if (lastContent->isText()) { - // We can augment the existing string and share this ContentData node. - String newStr = lastContent->text(); - newStr.append(s.get()); - lastContent->setText(newStr.impl()); - return; - } - } - - ContentData* newContentData = 0; - if (reuseContent && content) { - content->clear(); - newContentData = content.leakPtr(); - } else - newContentData = new ContentData; - - if (lastContent && !reuseContent) - lastContent->setNext(newContentData); - else - content.set(newContentData); - - newContentData->setText(s); + if (!image) + return; + prepareToSetContent(0, add)->setImage(image); } -void RenderStyle::setContent(CounterContent* c, bool add) +void RenderStyle::setContent(PassRefPtr<StringImpl> string, bool add) { - if (!c) + if (!string) return; + if (ContentData* data = prepareToSetContent(string.get(), add)) + data->setText(string); +} - OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content; - ContentData* lastContent = content.get(); - while (lastContent && lastContent->next()) - lastContent = lastContent->next(); - - bool reuseContent = !add; - ContentData* newContentData = 0; - if (reuseContent && content) { - content->clear(); - newContentData = content.leakPtr(); - } else - newContentData = new ContentData; - - if (lastContent && !reuseContent) - lastContent->setNext(newContentData); - else - content.set(newContentData); - - newContentData->setCounter(c); +void RenderStyle::setContent(PassOwnPtr<CounterContent> counter, bool add) +{ + if (!counter) + return; + prepareToSetContent(0, add)->setCounter(counter); } void RenderStyle::applyTransform(TransformationMatrix& transform, const IntSize& borderBoxSize, ApplyTransformOrigin applyOrigin) const @@ -774,21 +738,22 @@ static void constrainCornerRadiiForRect(const IntRect& r, IntSize& topLeft, IntS void RenderStyle::getBorderRadiiForRect(const IntRect& r, IntSize& topLeft, IntSize& topRight, IntSize& bottomLeft, IntSize& bottomRight) const { - topLeft = surround->border.topLeft(); - topRight = surround->border.topRight(); + topLeft = IntSize(surround->border.topLeft().width().calcValue(r.width()), surround->border.topLeft().height().calcValue(r.height())); + topRight = IntSize(surround->border.topRight().width().calcValue(r.width()), surround->border.topRight().height().calcValue(r.height())); - bottomLeft = surround->border.bottomLeft(); - bottomRight = surround->border.bottomRight(); + bottomLeft = IntSize(surround->border.bottomLeft().width().calcValue(r.width()), surround->border.bottomLeft().height().calcValue(r.height())); + bottomRight = IntSize(surround->border.bottomRight().width().calcValue(r.width()), surround->border.bottomRight().height().calcValue(r.height())); constrainCornerRadiiForRect(r, topLeft, topRight, bottomLeft, bottomRight); } void RenderStyle::getInnerBorderRadiiForRectWithBorderWidths(const IntRect& innerRect, unsigned short topWidth, unsigned short bottomWidth, unsigned short leftWidth, unsigned short rightWidth, IntSize& innerTopLeft, IntSize& innerTopRight, IntSize& innerBottomLeft, IntSize& innerBottomRight) const { - innerTopLeft = surround->border.topLeft(); - innerTopRight = surround->border.topRight(); - innerBottomLeft = surround->border.bottomLeft(); - innerBottomRight = surround->border.bottomRight(); + innerTopLeft = IntSize(surround->border.topLeft().width().calcValue(innerRect.width()), surround->border.topLeft().height().calcValue(innerRect.height())); + innerTopRight = IntSize(surround->border.topRight().width().calcValue(innerRect.width()), surround->border.topRight().height().calcValue(innerRect.height())); + innerBottomLeft = IntSize(surround->border.bottomLeft().width().calcValue(innerRect.width()), surround->border.bottomLeft().height().calcValue(innerRect.height())); + innerBottomRight = IntSize(surround->border.bottomRight().width().calcValue(innerRect.width()), surround->border.bottomRight().height().calcValue(innerRect.height())); + innerTopLeft.setWidth(max(0, innerTopLeft.width() - leftWidth)); innerTopLeft.setHeight(max(0, innerTopLeft.height() - topWidth)); diff --git a/WebCore/rendering/style/RenderStyle.h b/WebCore/rendering/style/RenderStyle.h index 1681890..e696735 100644 --- a/WebCore/rendering/style/RenderStyle.h +++ b/WebCore/rendering/style/RenderStyle.h @@ -35,7 +35,6 @@ #include "CSSPropertyNames.h" #include "CSSReflectionDirection.h" #include "CSSValueList.h" -#include "CachedImage.h" #include "CollapsedBorderValue.h" #include "Color.h" #include "ColorSpace.h" @@ -103,7 +102,6 @@ using std::max; class CSSStyleSelector; class CSSValueList; -class CachedImage; class Pair; class StyleImage; @@ -178,7 +176,6 @@ protected: (_white_space == other._white_space) && (_box_direction == other._box_direction) && (_visuallyOrdered == other._visuallyOrdered) && - (_htmlHacks == other._htmlHacks) && (_force_backgrounds_to_white == other._force_backgrounds_to_white) && (_pointerEvents == other._pointerEvents) && (_insideLink == other._insideLink); @@ -203,7 +200,6 @@ protected: // non CSS2 inherited bool _visuallyOrdered : 1; - bool _htmlHacks : 1; bool _force_backgrounds_to_white : 1; unsigned _pointerEvents : 4; // EPointerEvents unsigned _insideLink : 2; // EInsideLink @@ -279,7 +275,6 @@ protected: inherited_flags._border_collapse = initialBorderCollapse(); inherited_flags._white_space = initialWhiteSpace(); inherited_flags._visuallyOrdered = initialVisuallyOrdered(); - inherited_flags._htmlHacks=false; inherited_flags._box_direction = initialBoxDirection(); inherited_flags._force_backgrounds_to_white = false; inherited_flags._pointerEvents = initialPointerEvents(); @@ -348,6 +343,14 @@ public: bool hasFixedBackgroundImage() const { return m_background->background().hasFixedImage(); } bool hasAppearance() const { return appearance() != NoControlPart; } + bool hasBackground() const + { + Color color = visitedDependentColor(CSSPropertyBackgroundColor); + if (color.isValid() && color.alpha() > 0) + return true; + return hasBackgroundImage(); + } + bool visuallyOrdered() const { return inherited_flags._visuallyOrdered; } void setVisuallyOrdered(bool b) { inherited_flags._visuallyOrdered = b; } @@ -390,10 +393,10 @@ public: const NinePieceImage& borderImage() const { return surround->border.image(); } - const IntSize& borderTopLeftRadius() const { return surround->border.topLeft(); } - const IntSize& borderTopRightRadius() const { return surround->border.topRight(); } - const IntSize& borderBottomLeftRadius() const { return surround->border.bottomLeft(); } - const IntSize& borderBottomRightRadius() const { return surround->border.bottomRight(); } + const LengthSize& borderTopLeftRadius() const { return surround->border.topLeft(); } + const LengthSize& borderTopRightRadius() const { return surround->border.topRight(); } + const LengthSize& borderBottomLeftRadius() const { return surround->border.bottomLeft(); } + const LengthSize& borderBottomRightRadius() const { return surround->border.bottomRight(); } bool hasBorderRadius() const { return surround->border.hasBorderRadius(); } unsigned short borderLeftWidth() const { return surround->border.borderLeftWidth(); } @@ -788,18 +791,23 @@ public: void setBorderImage(const NinePieceImage& b) { SET_VAR(surround, border.m_image, b) } - void setBorderTopLeftRadius(const IntSize& s) { SET_VAR(surround, border.m_topLeft, s) } - void setBorderTopRightRadius(const IntSize& s) { SET_VAR(surround, border.m_topRight, s) } - void setBorderBottomLeftRadius(const IntSize& s) { SET_VAR(surround, border.m_bottomLeft, s) } - void setBorderBottomRightRadius(const IntSize& s) { SET_VAR(surround, border.m_bottomRight, s) } + void setBorderTopLeftRadius(const LengthSize& s) { SET_VAR(surround, border.m_topLeft, s) } + void setBorderTopRightRadius(const LengthSize& s) { SET_VAR(surround, border.m_topRight, s) } + void setBorderBottomLeftRadius(const LengthSize& s) { SET_VAR(surround, border.m_bottomLeft, s) } + void setBorderBottomRightRadius(const LengthSize& s) { SET_VAR(surround, border.m_bottomRight, s) } - void setBorderRadius(const IntSize& s) + void setBorderRadius(const LengthSize& s) { setBorderTopLeftRadius(s); setBorderTopRightRadius(s); setBorderBottomLeftRadius(s); setBorderBottomRightRadius(s); } + void setBorderRadius(const IntSize& s) + { + setBorderRadius(LengthSize(Length(s.width(), Fixed), Length(s.height(), Fixed))); + } + void getBorderRadiiForRect(const IntRect&, IntSize& topLeft, IntSize& topRight, IntSize& bottomLeft, IntSize& bottomRight) const; void getInnerBorderRadiiForRectWithBorderWidths(const IntRect&, unsigned short topWidth, @@ -914,7 +922,7 @@ public: void setCounterReset(short v) { SET_VAR(rareNonInheritedData, m_counterReset, v) } void setListStyleType(EListStyleType v) { inherited_flags._list_style_type = v; } - void setListStyleImage(StyleImage* v) { if (inherited->list_style_image != v) inherited.access()->list_style_image = v; } + void setListStyleImage(PassRefPtr<StyleImage> v) { if (inherited->list_style_image != v) inherited.access()->list_style_image = v; } void setListStylePosition(EListStylePosition v) { inherited_flags._list_style_position = v; } void resetMargin() { SET_VAR(surround, margin, LengthBox(Fixed)) } @@ -931,7 +939,7 @@ public: void setPaddingRight(Length v) { SET_VAR(surround, padding.m_right, v) } void setCursor(ECursor c) { inherited_flags._cursor_style = c; } - void addCursor(CachedImage*, const IntPoint& = IntPoint()); + void addCursor(PassRefPtr<StyleImage>, const IntPoint& hotSpot = IntPoint()); void setCursorList(PassRefPtr<CursorList>); void clearCursorList(); @@ -941,9 +949,6 @@ public: bool forceBackgroundsToWhite() const { return inherited_flags._force_backgrounds_to_white; } void setForceBackgroundsToWhite(bool b=true) { inherited_flags._force_backgrounds_to_white = b; } - bool htmlHacks() const { return inherited_flags._htmlHacks; } - void setHtmlHacks(bool b=true) { inherited_flags._htmlHacks = b; } - bool hasAutoZIndex() const { return m_box->hasAutoZIndex(); } void setHasAutoZIndex() { SET_VAR(m_box, m_hasAutoZIndex, true); SET_VAR(m_box, m_zIndex, 0) } int zIndex() const { return m_box->zIndex(); } @@ -1091,7 +1096,7 @@ public: void clearContent(); void setContent(PassRefPtr<StringImpl>, bool add = false); void setContent(PassRefPtr<StyleImage>, bool add = false); - void setContent(CounterContent*, bool add = false); + void setContent(PassOwnPtr<CounterContent>, bool add = false); const CounterDirectiveMap* counterDirectives() const; CounterDirectiveMap& accessCounterDirectives(); @@ -1153,7 +1158,7 @@ public: static bool initialBorderCollapse() { return false; } static EBorderStyle initialBorderStyle() { return BNONE; } static NinePieceImage initialNinePieceImage() { return NinePieceImage(); } - static IntSize initialBorderRadius() { return IntSize(0, 0); } + static LengthSize initialBorderRadius() { return LengthSize(Length(0, Fixed), Length(0, Fixed)); } static ECaptionSide initialCaptionSide() { return CAPTOP; } static EClear initialClear() { return CNONE; } static TextDirection initialDirection() { return LTR; } @@ -1281,6 +1286,8 @@ private: const Color& textStrokeColor() const { return rareInheritedData->textStrokeColor; } const Color colorIncludingFallback(int colorProperty, EBorderStyle borderStyle) const; + + ContentData* prepareToSetContent(StringImpl*, bool add); }; } // namespace WebCore diff --git a/WebCore/rendering/style/RenderStyleConstants.h b/WebCore/rendering/style/RenderStyleConstants.h index 70b128b..68c8113 100644 --- a/WebCore/rendering/style/RenderStyleConstants.h +++ b/WebCore/rendering/style/RenderStyleConstants.h @@ -79,6 +79,7 @@ enum PseudoId { METER_HORIZONTAL_BAR, METER_HORIZONTAL_OPTIMUM, METER_HORIZONTAL_SUBOPTIMAL, METER_HORIZONTAL_EVEN_LESS_GOOD, METER_VERTICAL_BAR, METER_VERTICAL_OPTIMUM, METER_VERTICAL_SUBOPTIMAL, METER_VERTICAL_EVEN_LESS_GOOD, AFTER_LAST_INTERNAL_PSEUDOID, + FULL_SCREEN, FULL_SCREEN_DOCUMENT, FIRST_PUBLIC_PSEUDOID = FIRST_LINE, FIRST_INTERNAL_PSEUDOID = FILE_UPLOAD_BUTTON, PUBLIC_PSEUDOID_MASK = ((1 << FIRST_INTERNAL_PSEUDOID) - 1) & ~((1 << FIRST_PUBLIC_PSEUDOID) - 1) @@ -276,6 +277,8 @@ enum EListStyleType { EthiopicAbegedeTiEt, UpperGreek, UpperNorwegian, + Asterisks, + Footnotes, Hebrew, Armenian, Georgian, diff --git a/WebCore/rendering/style/SVGRenderStyle.cpp b/WebCore/rendering/style/SVGRenderStyle.cpp index dc8a5af..7d1ad3b 100644 --- a/WebCore/rendering/style/SVGRenderStyle.cpp +++ b/WebCore/rendering/style/SVGRenderStyle.cpp @@ -162,6 +162,10 @@ StyleDifference SVGRenderStyle::diff(const SVGRenderStyle* other) const || svg_inherited_flags._joinStyle != other->svg_inherited_flags._joinStyle) return StyleDifferenceLayout; + // Shadow changes require relayouts, as they affect the repaint rects. + if (shadowSVG != other->shadowSVG) + return StyleDifferenceLayout; + // Some stroke properties, requires relayouts, as the cached stroke boundaries need to be recalculated. if (stroke != other->stroke) { if (stroke->width != other->stroke->width @@ -178,10 +182,6 @@ StyleDifference SVGRenderStyle::diff(const SVGRenderStyle* other) const // NOTE: All comparisions below may only return StyleDifferenceRepaint - // Shadow changes need to cause repaints. - if (shadowSVG != other->shadowSVG) - return StyleDifferenceRepaint; - // Painting related properties only need repaints. if (miscNotEqual) { if (misc->floodColor != other->misc->floodColor @@ -215,48 +215,6 @@ StyleDifference SVGRenderStyle::diff(const SVGRenderStyle* other) const return StyleDifferenceEqual; } -static void getSVGShadowExtent(ShadowData* shadow, float& top, float& right, float& bottom, float& left) -{ - top = 0.0f; - right = 0.0f; - bottom = 0.0f; - left = 0.0f; - - float blurAndSpread = shadow->blur() + shadow->spread(); - - top = min(top, shadow->y() - blurAndSpread); - right = max(right, shadow->x() + blurAndSpread); - bottom = max(bottom, shadow->y() + blurAndSpread); - left = min(left, shadow->x() - blurAndSpread); -} - -void SVGRenderStyle::inflateForShadow(IntRect& repaintRect) const -{ - ShadowData* svgShadow = shadow(); - if (!svgShadow) - return; - - FloatRect repaintFloatRect = FloatRect(repaintRect); - inflateForShadow(repaintFloatRect); - repaintRect = enclosingIntRect(repaintFloatRect); -} - -void SVGRenderStyle::inflateForShadow(FloatRect& repaintRect) const -{ - ShadowData* svgShadow = shadow(); - if (!svgShadow) - return; - - float shadowTop; - float shadowRight; - float shadowBottom; - float shadowLeft; - getSVGShadowExtent(svgShadow, shadowTop, shadowRight, shadowBottom, shadowLeft); - - repaintRect.move(shadowLeft, shadowTop); - repaintRect.setSize(repaintRect.size() + FloatSize(shadowRight - shadowLeft, shadowBottom - shadowTop)); -} - } #endif // ENABLE(SVG) diff --git a/WebCore/rendering/style/SVGRenderStyle.h b/WebCore/rendering/style/SVGRenderStyle.h index f071755..d57e4cf 100644 --- a/WebCore/rendering/style/SVGRenderStyle.h +++ b/WebCore/rendering/style/SVGRenderStyle.h @@ -47,10 +47,6 @@ public: bool inheritedNotEqual(const SVGRenderStyle*) const; void inheritFrom(const SVGRenderStyle*); - // FIXME: These functions should move to ShadowData. - void inflateForShadow(IntRect&) const; - void inflateForShadow(FloatRect&) const; - StyleDifference diff(const SVGRenderStyle*) const; bool operator==(const SVGRenderStyle&) const; diff --git a/WebCore/rendering/style/ShadowData.cpp b/WebCore/rendering/style/ShadowData.cpp index d4569d0..3a8f81d 100644 --- a/WebCore/rendering/style/ShadowData.cpp +++ b/WebCore/rendering/style/ShadowData.cpp @@ -22,6 +22,11 @@ #include "config.h" #include "ShadowData.h" +#include "FloatRect.h" +#include "IntRect.h" + +using namespace std; + namespace WebCore { ShadowData::ShadowData(const ShadowData& o) @@ -44,4 +49,45 @@ bool ShadowData::operator==(const ShadowData& o) const return m_x == o.m_x && m_y == o.m_y && m_blur == o.m_blur && m_spread == o.m_spread && m_style == o.m_style && m_color == o.m_color; } +static inline void calculateShadowExtent(const ShadowData* shadow, int additionalOutlineSize, int& shadowLeft, int& shadowRight, int& shadowTop, int& shadowBottom) +{ + do { + int blurAndSpread = shadow->blur() + shadow->spread() + additionalOutlineSize; + if (shadow->style() == Normal) { + shadowLeft = min(shadow->x() - blurAndSpread, shadowLeft); + shadowRight = max(shadow->x() + blurAndSpread, shadowRight); + shadowTop = min(shadow->y() - blurAndSpread, shadowTop); + shadowBottom = max(shadow->y() + blurAndSpread, shadowBottom); + } + + shadow = shadow->next(); + } while (shadow); +} + +void ShadowData::adjustRectForShadow(IntRect& rect, int additionalOutlineSize) const +{ + int shadowLeft = 0; + int shadowRight = 0; + int shadowTop = 0; + int shadowBottom = 0; + calculateShadowExtent(this, additionalOutlineSize, shadowLeft, shadowRight, shadowTop, shadowBottom); + + rect.move(shadowLeft, shadowTop); + rect.setWidth(rect.width() - shadowLeft + shadowRight); + rect.setHeight(rect.height() - shadowTop + shadowBottom); +} + +void ShadowData::adjustRectForShadow(FloatRect& rect, int additionalOutlineSize) const +{ + int shadowLeft = 0; + int shadowRight = 0; + int shadowTop = 0; + int shadowBottom = 0; + calculateShadowExtent(this, additionalOutlineSize, shadowLeft, shadowRight, shadowTop, shadowBottom); + + rect.move(shadowLeft, shadowTop); + rect.setWidth(rect.width() - shadowLeft + shadowRight); + rect.setHeight(rect.height() - shadowTop + shadowBottom); +} + } // namespace WebCore diff --git a/WebCore/rendering/style/ShadowData.h b/WebCore/rendering/style/ShadowData.h index 9252e13..ca83af0 100644 --- a/WebCore/rendering/style/ShadowData.h +++ b/WebCore/rendering/style/ShadowData.h @@ -30,6 +30,9 @@ namespace WebCore { +class FloatRect; +class IntRect; + enum ShadowStyle { Normal, Inset }; // This struct holds information about shadows for the text-shadow and box-shadow properties. @@ -76,6 +79,9 @@ public: const ShadowData* next() const { return m_next; } void setNext(ShadowData* shadow) { m_next = shadow; } + void adjustRectForShadow(IntRect&, int additionalOutlineSize = 0) const; + void adjustRectForShadow(FloatRect&, int additionalOutlineSize = 0) const; + private: int m_x; int m_y; diff --git a/WebCore/rendering/style/StyleCachedImage.cpp b/WebCore/rendering/style/StyleCachedImage.cpp index b55c5b9..1d7aba8 100644 --- a/WebCore/rendering/style/StyleCachedImage.cpp +++ b/WebCore/rendering/style/StyleCachedImage.cpp @@ -29,7 +29,7 @@ namespace WebCore { -PassRefPtr<CSSValue> StyleCachedImage::cssValue() +PassRefPtr<CSSValue> StyleCachedImage::cssValue() const { return CSSPrimitiveValue::create(m_image->url(), CSSPrimitiveValue::CSS_URI); } diff --git a/WebCore/rendering/style/StyleCachedImage.h b/WebCore/rendering/style/StyleCachedImage.h index 3d22868..3d6e1a2 100644 --- a/WebCore/rendering/style/StyleCachedImage.h +++ b/WebCore/rendering/style/StyleCachedImage.h @@ -38,7 +38,7 @@ public: virtual bool isCachedImage() const { return true; } - virtual PassRefPtr<CSSValue> cssValue(); + virtual PassRefPtr<CSSValue> cssValue() const; CachedImage* cachedImage() const { return m_image.get(); } diff --git a/WebCore/rendering/style/StyleGeneratedImage.cpp b/WebCore/rendering/style/StyleGeneratedImage.cpp index 610e73d..2322f5f 100644 --- a/WebCore/rendering/style/StyleGeneratedImage.cpp +++ b/WebCore/rendering/style/StyleGeneratedImage.cpp @@ -29,7 +29,7 @@ namespace WebCore { -PassRefPtr<CSSValue> StyleGeneratedImage::cssValue() +PassRefPtr<CSSValue> StyleGeneratedImage::cssValue() const { return m_generator; } diff --git a/WebCore/rendering/style/StyleGeneratedImage.h b/WebCore/rendering/style/StyleGeneratedImage.h index 532e383..7be1f6a 100644 --- a/WebCore/rendering/style/StyleGeneratedImage.h +++ b/WebCore/rendering/style/StyleGeneratedImage.h @@ -42,7 +42,7 @@ public: virtual bool isGeneratedImage() const { return true; } - virtual PassRefPtr<CSSValue> cssValue(); + virtual PassRefPtr<CSSValue> cssValue() const; virtual IntSize imageSize(const RenderObject*, float multiplier) const; virtual bool imageHasRelativeWidth() const { return !m_fixedSize; } diff --git a/WebCore/rendering/style/StyleImage.h b/WebCore/rendering/style/StyleImage.h index cb90288..ead8d4a 100644 --- a/WebCore/rendering/style/StyleImage.h +++ b/WebCore/rendering/style/StyleImage.h @@ -24,6 +24,7 @@ #ifndef StyleImage_h #define StyleImage_h +#include "CSSValue.h" #include "IntSize.h" #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> @@ -41,12 +42,12 @@ class StyleImage : public RefCounted<StyleImage> { public: virtual ~StyleImage() { } - bool operator==(const StyleImage& other) + bool operator==(const StyleImage& other) const { return data() == other.data(); } - - virtual PassRefPtr<CSSValue> cssValue() = 0; + + virtual PassRefPtr<CSSValue> cssValue() const = 0; virtual bool canRender(float /*multiplier*/) const { return true; } virtual bool isLoaded() const { return true; } @@ -60,7 +61,9 @@ public: virtual void removeClient(RenderObject*) = 0; virtual Image* image(RenderObject*, const IntSize&) const = 0; virtual WrappedImagePtr data() const = 0; + virtual bool isCachedImage() const { return false; } + virtual bool isPendingImage() const { return false; } virtual bool isGeneratedImage() const { return false; } static bool imagesEquivalent(StyleImage* image1, StyleImage* image2) diff --git a/WebCore/rendering/style/StylePendingImage.h b/WebCore/rendering/style/StylePendingImage.h new file mode 100644 index 0000000..b0c9b01 --- /dev/null +++ b/WebCore/rendering/style/StylePendingImage.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef StylePendingImage_h +#define StylePendingImage_h + +#include "StyleImage.h" + +namespace WebCore { + +// StylePendingImage is a placeholder StyleImage that is entered into the RenderStyle during +// style resolution, in order to avoid loading images that are not referenced by the final style. +// They should never exist in a RenderStyle after it has been returned from the style selector. + +class StylePendingImage : public StyleImage { +public: + static PassRefPtr<StylePendingImage> create(CSSImageValue* value) { return adoptRef(new StylePendingImage(value)); } + + virtual WrappedImagePtr data() const { return m_value; } + + virtual bool isPendingImage() const { return true; } + + virtual PassRefPtr<CSSValue> cssValue() const { return m_value; } + CSSImageValue* cssImageValue() const { return m_value; } + + virtual IntSize imageSize(const RenderObject*, float /*multiplier*/) const { return IntSize(); } + virtual bool imageHasRelativeWidth() const { return false; } + virtual bool imageHasRelativeHeight() const { return false; } + virtual bool usesImageContainerSize() const { return false; } + virtual void setImageContainerSize(const IntSize&) { } + virtual void addClient(RenderObject*) { } + virtual void removeClient(RenderObject*) { } + virtual Image* image(RenderObject*, const IntSize&) const + { + ASSERT_NOT_REACHED(); + return 0; + } + +private: + StylePendingImage(CSSImageValue* value) + : m_value(value) + { + } + + CSSImageValue* m_value; // Not retained; it owns us. +}; + +} +#endif |