diff options
Diffstat (limited to 'WebCore/rendering')
55 files changed, 542 insertions, 285 deletions
diff --git a/WebCore/rendering/InlineTextBox.h b/WebCore/rendering/InlineTextBox.h index fcbf23a..7d828f3 100644 --- a/WebCore/rendering/InlineTextBox.h +++ b/WebCore/rendering/InlineTextBox.h @@ -67,6 +67,7 @@ public: bool hasHyphen() const { return m_hasEllipsisBoxOrHyphen; } void setHasHyphen(bool hasHyphen) { m_hasEllipsisBoxOrHyphen = hasHyphen; } + static inline bool compareByStart(const InlineTextBox* first, const InlineTextBox* second) { return first->start() < second->start(); } private: virtual int selectionTop(); diff --git a/WebCore/rendering/RenderApplet.h b/WebCore/rendering/RenderApplet.h index 343421e..62f46cd 100644 --- a/WebCore/rendering/RenderApplet.h +++ b/WebCore/rendering/RenderApplet.h @@ -23,7 +23,7 @@ #define RenderApplet_h #include "RenderWidget.h" -#include "StringHash.h" +#include <wtf/text/StringHash.h> namespace WebCore { diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp index c982d26..574d389 100644 --- a/WebCore/rendering/RenderBlock.cpp +++ b/WebCore/rendering/RenderBlock.cpp @@ -1021,8 +1021,8 @@ void RenderBlock::removeChild(RenderObject* oldChild) // If this was our last child be sure to clear out our line boxes. if (childrenInline()) lineBoxes()->deleteLineBoxes(renderArena()); - // If we're now an empty anonymous block then go ahead and delete ourselves. - else if (isAnonymousBlock() && parent() && parent()->isRenderBlock() && !continuation()) + // If we're now an empty anonymous columns or column span block, then go ahead and delete ourselves. + else if ((isAnonymousColumnsBlock() || isAnonymousColumnSpanBlock()) && parent() && parent()->isRenderBlock() && !continuation()) destroy(); } } @@ -2120,7 +2120,7 @@ void RenderBlock::paintChildren(PaintInfo& paintInfo, int tx, int ty) PaintInfo info(paintInfo); info.phase = newPhase; info.updatePaintingRootForChildren(this); - bool checkPageBreaks = document()->printing() && !document()->settings()->paginateDuringLayoutEnabled(); + bool checkPageBreaks = document()->paginated() && !document()->settings()->paginateDuringLayoutEnabled(); bool checkColumnBreaks = !checkPageBreaks && !view()->printRect().isEmpty() && !document()->settings()->paginateDuringLayoutEnabled(); for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) { @@ -4109,7 +4109,7 @@ void RenderBlock::calcColumnWidth() int desiredColumnWidth = contentWidth(); // For now, we don't support multi-column layouts when printing, since we have to do a lot of work for proper pagination. - if (document()->printing() || (style()->hasAutoColumnCount() && style()->hasAutoColumnWidth())) { + if (document()->paginated() || (style()->hasAutoColumnCount() && style()->hasAutoColumnWidth())) { setDesiredColumnCountAndWidth(desiredColumnCount, desiredColumnWidth); return; } diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp index e11c7ad..8a3ea8e 100644 --- a/WebCore/rendering/RenderBox.cpp +++ b/WebCore/rendering/RenderBox.cpp @@ -1476,6 +1476,12 @@ bool RenderBox::sizesToIntrinsicWidth(WidthType widthType) const && (parent()->style()->boxOrient() == HORIZONTAL || parent()->style()->boxAlign() != BSTRETCH)) return true; + // Button, input, select, textarea, legend and datagrid treat + // width value of 'auto' as 'intrinsic' unless it's in a + // stretching vertical flexbox. + if (width.type() == Auto && !(parent()->isFlexibleBox() && parent()->style()->boxOrient() == VERTICAL && parent()->style()->boxAlign() == BSTRETCH) && node() && (node()->hasTagName(inputTag) || node()->hasTagName(selectTag) || node()->hasTagName(buttonTag) || node()->hasTagName(textareaTag) || node()->hasTagName(legendTag) || node()->hasTagName(datagridTag))) + return true; + return false; } @@ -1579,9 +1585,9 @@ void RenderBox::calcHeight() // is specified. When we're printing, we also need this quirk if the body or root has a percentage // height since we don't set a height in RenderView when we're printing. So without this quirk, the // height has nothing to be a percentage of, and it ends up being 0. That is bad. - bool printingNeedsBaseHeight = document()->printing() && h.isPercent() + bool paginatedContentNeedsBaseHeight = document()->paginated() && h.isPercent() && (isRoot() || (isBody() && document()->documentElement()->renderer()->style()->height().isPercent())); - if (stretchesToViewHeight() || printingNeedsBaseHeight) { + if (stretchesToViewHeight() || paginatedContentNeedsBaseHeight) { int margins = collapsedMarginTop() + collapsedMarginBottom(); int visHeight = document()->printing() ? view()->frameView()->pageHeight() : view()->viewHeight(); if (isRoot()) diff --git a/WebCore/rendering/RenderBoxModelObject.cpp b/WebCore/rendering/RenderBoxModelObject.cpp index 9117ed8..78618d1 100644 --- a/WebCore/rendering/RenderBoxModelObject.cpp +++ b/WebCore/rendering/RenderBoxModelObject.cpp @@ -531,7 +531,7 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co // The mask has been created. Now we just need to clip to it. context->save(); - context->clipToImageBuffer(maskRect, maskImage.get()); + context->clipToImageBuffer(maskImage.get(), maskRect); } StyleImage* bg = bgLayer->image(); diff --git a/WebCore/rendering/RenderEmbeddedObject.cpp b/WebCore/rendering/RenderEmbeddedObject.cpp index e72825e..55b230b 100644 --- a/WebCore/rendering/RenderEmbeddedObject.cpp +++ b/WebCore/rendering/RenderEmbeddedObject.cpp @@ -231,8 +231,8 @@ void RenderEmbeddedObject::updateWidget(bool onlyCreateNonNetscapePlugins) url = p->value(); if (serviceType.isEmpty() && equalIgnoringCase(name, "type")) { serviceType = p->value(); - int pos = serviceType.find(";"); - if (pos != -1) + size_t pos = serviceType.find(";"); + if (pos != notFound) serviceType = serviceType.left(pos); } if (!embed && !name.isEmpty()) { diff --git a/WebCore/rendering/RenderInputSpeech.cpp b/WebCore/rendering/RenderInputSpeech.cpp index df17944..5472025 100644 --- a/WebCore/rendering/RenderInputSpeech.cpp +++ b/WebCore/rendering/RenderInputSpeech.cpp @@ -36,6 +36,7 @@ #include "GraphicsContext.h" #include "HTMLNames.h" #include "RenderBox.h" +#include "TextControlInnerElements.h" namespace WebCore { @@ -79,7 +80,16 @@ bool RenderInputSpeech::paintInputFieldSpeechButton(RenderObject* object, const buttonRect.move(rect.x(), rect.y()); DEFINE_STATIC_LOCAL(RefPtr<Image>, imageStateNormal, (Image::loadPlatformResource("inputSpeech"))); - paintInfo.context->drawImage(imageStateNormal.get(), object->style()->colorSpace(), buttonRect); + DEFINE_STATIC_LOCAL(RefPtr<Image>, imageStateRecording, (Image::loadPlatformResource("inputSpeechRecording"))); + DEFINE_STATIC_LOCAL(RefPtr<Image>, imageStateWaiting, (Image::loadPlatformResource("inputSpeechWaiting"))); + + InputFieldSpeechButtonElement* speechButton = reinterpret_cast<InputFieldSpeechButtonElement*>(object->node()); + Image* image = imageStateNormal.get(); + if (speechButton->state() == InputFieldSpeechButtonElement::Recording) + image = imageStateRecording.get(); + else if (speechButton->state() == InputFieldSpeechButtonElement::Recognizing) + image = imageStateWaiting.get(); + paintInfo.context->drawImage(image, object->style()->colorSpace(), buttonRect); return false; } diff --git a/WebCore/rendering/RenderRubyRun.cpp b/WebCore/rendering/RenderRubyRun.cpp index d6b724b..d48646b 100644 --- a/WebCore/rendering/RenderRubyRun.cpp +++ b/WebCore/rendering/RenderRubyRun.cpp @@ -143,14 +143,15 @@ void RenderRubyRun::addChild(RenderObject* child, RenderObject* beforeChild) RenderBlock::removeChild(beforeChild); newRun->addChild(beforeChild); } else { - ASSERT(hasRubyBase()); // Otherwise beforeChild would be borked. - // Insertion before a ruby base object. - // In this case we need insert a new run before the current one and split the base. - RenderObject* ruby = parent(); - RenderRubyRun* newRun = staticCreateRubyRun(ruby); - ruby->addChild(newRun, this); - newRun->addChild(child); - rubyBaseSafe()->moveChildren(newRun->rubyBaseSafe(), beforeChild); + if (hasRubyBase()) { + // Insertion before a ruby base object. + // In this case we need insert a new run before the current one and split the base. + RenderObject* ruby = parent(); + RenderRubyRun* newRun = staticCreateRubyRun(ruby); + ruby->addChild(newRun, this); + newRun->addChild(child); + rubyBaseSafe()->moveChildren(newRun->rubyBaseSafe(), beforeChild); + } } } else { // child is not a text -> insert it into the base @@ -171,13 +172,14 @@ void RenderRubyRun::removeChild(RenderObject* child) if (base && rightNeighbour && rightNeighbour->isRubyRun()) { // Ruby run without a base can happen only at the first run. RenderRubyRun* rightRun = static_cast<RenderRubyRun*>(rightNeighbour); - ASSERT(rightRun->hasRubyBase()); - RenderRubyBase* rightBase = rightRun->rubyBaseSafe(); - // Collect all children in a single base, then swap the bases. - rightBase->moveChildren(base); - moveChildTo(rightRun, base); - rightRun->moveChildTo(this, rightBase); - // The now empty ruby base will be removed below. + if (rightRun->hasRubyBase()) { + RenderRubyBase* rightBase = rightRun->rubyBaseSafe(); + // Collect all children in a single base, then swap the bases. + rightBase->moveChildren(base); + moveChildTo(rightRun, base); + rightRun->moveChildTo(this, rightBase); + // The now empty ruby base will be removed below. + } } } diff --git a/WebCore/rendering/RenderSVGAllInOne.cpp b/WebCore/rendering/RenderSVGAllInOne.cpp index fa5709e..2d44ca2 100644 --- a/WebCore/rendering/RenderSVGAllInOne.cpp +++ b/WebCore/rendering/RenderSVGAllInOne.cpp @@ -53,6 +53,7 @@ #include "RenderSVGViewportContainer.cpp" #include "SVGCharacterData.cpp" #include "SVGCharacterLayoutInfo.cpp" +#include "SVGImageBufferTools.cpp" #include "SVGInlineFlowBox.cpp" #include "SVGInlineTextBox.cpp" #include "SVGMarkerLayoutInfo.cpp" diff --git a/WebCore/rendering/RenderSVGGradientStop.cpp b/WebCore/rendering/RenderSVGGradientStop.cpp index 3494aa7..ebf7385 100644 --- a/WebCore/rendering/RenderSVGGradientStop.cpp +++ b/WebCore/rendering/RenderSVGGradientStop.cpp @@ -47,6 +47,8 @@ RenderSVGGradientStop::~RenderSVGGradientStop() void RenderSVGGradientStop::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { RenderObject::styleDidChange(diff, oldStyle); + if (diff == StyleDifferenceEqual) + return; // <stop> elements should only be allowed to make renderers under gradient elements // but I can imagine a few cases we might not be catching, so let's not crash if our parent isn't a gradient. @@ -60,7 +62,7 @@ void RenderSVGGradientStop::styleDidChange(StyleDifference diff, const RenderSty ASSERT(renderer->isSVGResourceContainer()); RenderSVGResourceContainer* container = renderer->toRenderSVGResourceContainer(); - container->invalidateClients(); + container->removeAllClientsFromCache(); } void RenderSVGGradientStop::layout() diff --git a/WebCore/rendering/RenderSVGImage.cpp b/WebCore/rendering/RenderSVGImage.cpp index 993278c..893a4ea 100644 --- a/WebCore/rendering/RenderSVGImage.cpp +++ b/WebCore/rendering/RenderSVGImage.cpp @@ -177,7 +177,7 @@ void RenderSVGImage::imageChanged(WrappedImagePtr image, const IntRect* 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)) - resources->invalidateClient(this); + resources->removeClientFromCache(this); // Eventually notify parent resources, that we've changed. RenderSVGResource::markForLayoutAndParentResourceInvalidation(this, false); diff --git a/WebCore/rendering/RenderSVGImage.h b/WebCore/rendering/RenderSVGImage.h index 6ee0179..38e3a13 100644 --- a/WebCore/rendering/RenderSVGImage.h +++ b/WebCore/rendering/RenderSVGImage.h @@ -81,6 +81,21 @@ private: mutable FloatRect m_cachedLocalRepaintRect; }; +inline RenderSVGImage* toRenderSVGImage(RenderObject* object) +{ + ASSERT(!object || object->isSVGImage()); + return static_cast<RenderSVGImage*>(object); +} + +inline const RenderSVGImage* toRenderSVGImage(const RenderObject* object) +{ + ASSERT(!object || object->isSVGImage()); + return static_cast<const RenderSVGImage*>(object); +} + +// This will catch anyone doing an unnecessary cast. +void toRenderSVGImage(const RenderSVGImage*); + } // namespace WebCore #endif // ENABLE(SVG) diff --git a/WebCore/rendering/RenderSVGResource.cpp b/WebCore/rendering/RenderSVGResource.cpp index 9c89d3c..0c943e5 100644 --- a/WebCore/rendering/RenderSVGResource.cpp +++ b/WebCore/rendering/RenderSVGResource.cpp @@ -171,7 +171,7 @@ void RenderSVGResource::markForLayoutAndParentResourceInvalidation(RenderObject* RenderObject* current = object->parent(); while (current) { if (current->isSVGResourceContainer()) { - current->toRenderSVGResourceContainer()->invalidateClients(); + current->toRenderSVGResourceContainer()->removeAllClientsFromCache(); break; } diff --git a/WebCore/rendering/RenderSVGResource.h b/WebCore/rendering/RenderSVGResource.h index e2d8216..a70ce52 100644 --- a/WebCore/rendering/RenderSVGResource.h +++ b/WebCore/rendering/RenderSVGResource.h @@ -57,8 +57,8 @@ public: RenderSVGResource() { } virtual ~RenderSVGResource() { } - virtual void invalidateClients() = 0; - virtual void invalidateClient(RenderObject*) = 0; + virtual void removeAllClientsFromCache(bool markForInvalidation = true) = 0; + virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true) = 0; virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode) = 0; virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short) { } diff --git a/WebCore/rendering/RenderSVGResourceClipper.cpp b/WebCore/rendering/RenderSVGResourceClipper.cpp index a201d1f..626a880 100644 --- a/WebCore/rendering/RenderSVGResourceClipper.cpp +++ b/WebCore/rendering/RenderSVGResourceClipper.cpp @@ -64,7 +64,7 @@ RenderSVGResourceClipper::~RenderSVGResourceClipper() m_clipper.clear(); } -void RenderSVGResourceClipper::invalidateClients() +void RenderSVGResourceClipper::removeAllClientsFromCache(bool markForInvalidation) { if (m_invalidationBlocked) return; @@ -75,20 +75,19 @@ void RenderSVGResourceClipper::invalidateClients() m_clipper.clear(); } - markAllClientsForInvalidation(LayoutAndBoundariesInvalidation); + markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInvalidation : ParentOnlyInvalidation); } -void RenderSVGResourceClipper::invalidateClient(RenderObject* client) +void RenderSVGResourceClipper::removeClientFromCache(RenderObject* client, bool markForInvalidation) { ASSERT(client); if (m_invalidationBlocked) return; - ASSERT(client->selfNeedsLayout()); if (m_clipper.contains(client)) delete m_clipper.take(client); - markClientForInvalidation(client, BoundariesInvalidation); + markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidation : ParentOnlyInvalidation); } bool RenderSVGResourceClipper::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode) @@ -174,7 +173,7 @@ bool RenderSVGResourceClipper::applyClippingToContext(RenderObject* object, cons if (!clipperData->clipMaskImage) return false; - context->clipToImageBuffer(repaintRect, clipperData->clipMaskImage.get()); + context->clipToImageBuffer(clipperData->clipMaskImage.get(), repaintRect); return true; } diff --git a/WebCore/rendering/RenderSVGResourceClipper.h b/WebCore/rendering/RenderSVGResourceClipper.h index d334c7d..0f68c67 100644 --- a/WebCore/rendering/RenderSVGResourceClipper.h +++ b/WebCore/rendering/RenderSVGResourceClipper.h @@ -47,8 +47,8 @@ public: virtual const char* renderName() const { return "RenderSVGResourceClipper"; } - virtual void invalidateClients(); - virtual void invalidateClient(RenderObject*); + virtual void removeAllClientsFromCache(bool markForInvalidation = true); + virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true); virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); virtual FloatRect resourceBoundingBox(RenderObject*); diff --git a/WebCore/rendering/RenderSVGResourceContainer.cpp b/WebCore/rendering/RenderSVGResourceContainer.cpp index 7e43300..5652dcc 100644 --- a/WebCore/rendering/RenderSVGResourceContainer.cpp +++ b/WebCore/rendering/RenderSVGResourceContainer.cpp @@ -52,7 +52,7 @@ void RenderSVGResourceContainer::layout() { // Invalidate all resources if our layout changed. if (m_everHadLayout && selfNeedsLayout()) - invalidateClients(); + removeAllClientsFromCache(); RenderSVGHiddenContainer::layout(); } @@ -76,7 +76,7 @@ void RenderSVGResourceContainer::styleDidChange(StyleDifference diff, const Rend void RenderSVGResourceContainer::idChanged() { // Invalidate all our current clients. - invalidateClients(); + removeAllClientsFromCache(); // Remove old id, that is guaranteed to be present in cache. SVGDocumentExtensions* extensions = svgExtensionsFromNode(node()); @@ -92,17 +92,32 @@ void RenderSVGResourceContainer::markAllClientsForInvalidation(InvalidationMode return; bool needsLayout = mode == LayoutAndBoundariesInvalidation; + bool markForInvalidation = mode != ParentOnlyInvalidation; HashSet<RenderObject*>::iterator end = m_clients.end(); for (HashSet<RenderObject*>::iterator it = m_clients.begin(); it != end; ++it) { RenderObject* client = *it; if (client->isSVGResourceContainer()) { - client->toRenderSVGResourceContainer()->invalidateClients(); + client->toRenderSVGResourceContainer()->removeAllClientsFromCache(markForInvalidation); continue; } - markClientForInvalidation(client, mode); - RenderSVGResource::markForLayoutAndParentResourceInvalidation(client, needsLayout); + if (markForInvalidation) + markClientForInvalidation(client, mode); + + if (needsLayout) + client->setNeedsLayout(true); + + // Invalidate resources in ancestor chain, if needed. + RenderObject* current = client->parent(); + while (current) { + if (current->isSVGResourceContainer()) { + current->toRenderSVGResourceContainer()->removeAllClientsFromCache(markForInvalidation); + break; + } + + current = current->parent(); + } } } @@ -120,6 +135,8 @@ void RenderSVGResourceContainer::markClientForInvalidation(RenderObject* client, if (client->view()) client->repaint(); break; + case ParentOnlyInvalidation: + break; } } diff --git a/WebCore/rendering/RenderSVGResourceContainer.h b/WebCore/rendering/RenderSVGResourceContainer.h index 4271a5f..08e18d4 100644 --- a/WebCore/rendering/RenderSVGResourceContainer.h +++ b/WebCore/rendering/RenderSVGResourceContainer.h @@ -49,7 +49,8 @@ protected: enum InvalidationMode { LayoutAndBoundariesInvalidation, BoundariesInvalidation, - RepaintInvalidation + RepaintInvalidation, + ParentOnlyInvalidation }; // Used from the invalidateClient/invalidateClients methods from classes, inheriting from us. diff --git a/WebCore/rendering/RenderSVGResourceFilter.cpp b/WebCore/rendering/RenderSVGResourceFilter.cpp index bc5feaf..09e83f4 100644 --- a/WebCore/rendering/RenderSVGResourceFilter.cpp +++ b/WebCore/rendering/RenderSVGResourceFilter.cpp @@ -67,25 +67,24 @@ RenderSVGResourceFilter::~RenderSVGResourceFilter() m_filter.clear(); } -void RenderSVGResourceFilter::invalidateClients() +void RenderSVGResourceFilter::removeAllClientsFromCache(bool markForInvalidation) { if (!m_filter.isEmpty()) { deleteAllValues(m_filter); m_filter.clear(); } - markAllClientsForInvalidation(LayoutAndBoundariesInvalidation); + markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInvalidation : ParentOnlyInvalidation); } -void RenderSVGResourceFilter::invalidateClient(RenderObject* client) +void RenderSVGResourceFilter::removeClientFromCache(RenderObject* client, bool markForInvalidation) { ASSERT(client); - ASSERT(client->selfNeedsLayout()); if (m_filter.contains(client)) delete m_filter.take(client); - markClientForInvalidation(client, BoundariesInvalidation); + markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidation : ParentOnlyInvalidation); } PassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives() @@ -243,7 +242,7 @@ void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo FilterData* filterData = m_filter.get(object); if (!filterData->builded) { if (!filterData->savedContext) { - invalidateClient(object); + removeClientFromCache(object); return; } @@ -271,7 +270,7 @@ void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo #if !PLATFORM(CG) resultImage->transformColorSpace(LinearRGB, DeviceRGB); #endif - context->drawImage(resultImage->image(), object->style()->colorSpace(), lastEffect->subRegion()); + context->drawImageBuffer(resultImage, object->style()->colorSpace(), lastEffect->subRegion()); } } diff --git a/WebCore/rendering/RenderSVGResourceFilter.h b/WebCore/rendering/RenderSVGResourceFilter.h index 7b5ab09..314c94d 100644 --- a/WebCore/rendering/RenderSVGResourceFilter.h +++ b/WebCore/rendering/RenderSVGResourceFilter.h @@ -64,8 +64,8 @@ public: virtual const char* renderName() const { return "RenderSVGResourceFilter"; } - virtual void invalidateClients(); - virtual void invalidateClient(RenderObject*); + virtual void removeAllClientsFromCache(bool markForInvalidation = true); + virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true); virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode); diff --git a/WebCore/rendering/RenderSVGResourceGradient.cpp b/WebCore/rendering/RenderSVGResourceGradient.cpp index 73b2ab6..d29192a 100644 --- a/WebCore/rendering/RenderSVGResourceGradient.cpp +++ b/WebCore/rendering/RenderSVGResourceGradient.cpp @@ -28,6 +28,7 @@ #include "GradientAttributes.h" #include "GraphicsContext.h" +#include "SVGImageBufferTools.h" #include "SVGRenderSupport.h" #include <wtf/UnusedParam.h> @@ -50,81 +51,64 @@ RenderSVGResourceGradient::~RenderSVGResourceGradient() m_gradient.clear(); } -void RenderSVGResourceGradient::invalidateClients() +void RenderSVGResourceGradient::removeAllClientsFromCache(bool markForInvalidation) { if (!m_gradient.isEmpty()) { deleteAllValues(m_gradient); m_gradient.clear(); } - markAllClientsForInvalidation(RepaintInvalidation); + markAllClientsForInvalidation(markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation); } -void RenderSVGResourceGradient::invalidateClient(RenderObject* client) +void RenderSVGResourceGradient::removeClientFromCache(RenderObject* client, bool markForInvalidation) { ASSERT(client); - ASSERT(client->selfNeedsLayout()); if (m_gradient.contains(client)) delete m_gradient.take(client); - markClientForInvalidation(client, RepaintInvalidation); + markClientForInvalidation(client, markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation); } #if PLATFORM(CG) -static inline AffineTransform absoluteTransformFromContext(GraphicsContext* context) -{ - // Extract current transformation matrix used in the original context. Note that this coordinate - // system is flipped compared to SVGs internal coordinate system, done in WebKit level. Fix - // this transformation by flipping the y component. - return context->getCTM() * AffineTransform().flipY(); -} - static inline bool createMaskAndSwapContextForTextGradient(GraphicsContext*& context, GraphicsContext*& savedContext, OwnPtr<ImageBuffer>& imageBuffer, const RenderObject* object) { const RenderObject* textRootBlock = SVGRenderSupport::findTextRootObject(object); + ASSERT(textRootBlock); - AffineTransform transform(absoluteTransformFromContext(context)); - FloatRect maskAbsoluteBoundingBox = transform.mapRect(textRootBlock->repaintRectInLocalCoordinates()); + AffineTransform absoluteTransform(SVGImageBufferTools::absoluteTransformFromContext(context)); + FloatRect absoluteTargetRect = absoluteTransform.mapRect(textRootBlock->repaintRectInLocalCoordinates()); - IntRect maskImageRect = enclosingIntRect(maskAbsoluteBoundingBox); - if (maskImageRect.isEmpty()) + OwnPtr<ImageBuffer> maskImage; + if (!SVGImageBufferTools::createImageBuffer(absoluteTransform, absoluteTargetRect, maskImage, DeviceRGB)) return false; - // Allocate an image buffer as big as the absolute unclipped size of the object - OwnPtr<ImageBuffer> maskImage = ImageBuffer::create(maskImageRect.size()); - if (!maskImage) - return false; - - GraphicsContext* maskImageContext = maskImage->context(); - - // Transform the mask image coordinate system to absolute screen coordinates - maskImageContext->translate(-maskAbsoluteBoundingBox.x(), -maskAbsoluteBoundingBox.y()); - maskImageContext->concatCTM(transform); - - imageBuffer = maskImage.release(); + ASSERT(maskImage); savedContext = context; - context = maskImageContext; - + context = maskImage->context(); + imageBuffer = maskImage.release(); return true; } static inline AffineTransform clipToTextMask(GraphicsContext* context, OwnPtr<ImageBuffer>& imageBuffer, + FloatRect& repaintRect, const RenderObject* object, GradientData* gradientData) { const RenderObject* textRootBlock = SVGRenderSupport::findTextRootObject(object); + ASSERT(textRootBlock); - // The mask image has been created in the device coordinate space, as the image should not be scaled. - // So the actual masking process has to be done in the device coordinate space as well. - AffineTransform transform(absoluteTransformFromContext(context)); - context->concatCTM(transform.inverse()); - context->clipToImageBuffer(transform.mapRect(textRootBlock->repaintRectInLocalCoordinates()), imageBuffer.get()); - context->concatCTM(transform); + repaintRect = textRootBlock->repaintRectInLocalCoordinates(); + + AffineTransform absoluteTransform(SVGImageBufferTools::absoluteTransformFromContext(context)); + FloatRect absoluteTargetRect = absoluteTransform.mapRect(repaintRect); + + SVGImageBufferTools::clipToImageBuffer(context, absoluteTransform, absoluteTargetRect, imageBuffer.get()); AffineTransform matrix; if (gradientData->boundingBoxMode) { @@ -146,7 +130,7 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle* // Be sure to synchronize all SVG properties on the gradientElement _before_ processing any further. // Otherwhise the call to collectGradientAttributes() in createTileImage(), may cause the SVG DOM property - // synchronization to kick in, which causes invalidateClients() to be called, which in turn deletes our + // synchronization to kick in, which causes removeAllClientsFromCache() to be called, which in turn deletes our // GradientData object! Leaving out the line below will cause svg/dynamic-updates/SVG*GradientElement-svgdom* to crash. SVGGradientElement* gradientElement = static_cast<SVGGradientElement*>(node()); if (!gradientElement) @@ -232,12 +216,11 @@ void RenderSVGResourceGradient::postApplyResource(RenderObject* object, Graphics context = m_savedContext; m_savedContext = 0; - gradientData->gradient->setGradientSpaceTransform(clipToTextMask(context, m_imageBuffer, object, gradientData)); + FloatRect repaintRect; + gradientData->gradient->setGradientSpaceTransform(clipToTextMask(context, m_imageBuffer, repaintRect, object, gradientData)); context->setFillGradient(gradientData->gradient); - const RenderObject* textRootBlock = SVGRenderSupport::findTextRootObject(object); - context->fillRect(textRootBlock->repaintRectInLocalCoordinates()); - + context->fillRect(repaintRect); m_imageBuffer.clear(); } #else diff --git a/WebCore/rendering/RenderSVGResourceGradient.h b/WebCore/rendering/RenderSVGResourceGradient.h index b01af6d..4de4272 100644 --- a/WebCore/rendering/RenderSVGResourceGradient.h +++ b/WebCore/rendering/RenderSVGResourceGradient.h @@ -50,8 +50,8 @@ public: RenderSVGResourceGradient(SVGGradientElement*); virtual ~RenderSVGResourceGradient(); - virtual void invalidateClients(); - virtual void invalidateClient(RenderObject*); + virtual void removeAllClientsFromCache(bool markForInvalidation = true); + virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true); virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode); diff --git a/WebCore/rendering/RenderSVGResourceMarker.cpp b/WebCore/rendering/RenderSVGResourceMarker.cpp index fa00fa3..1d5663b 100644 --- a/WebCore/rendering/RenderSVGResourceMarker.cpp +++ b/WebCore/rendering/RenderSVGResourceMarker.cpp @@ -50,7 +50,7 @@ void RenderSVGResourceMarker::layout() { // Invalidate all resources if our layout changed. if (m_everHadLayout && selfNeedsLayout()) - invalidateClients(); + removeAllClientsFromCache(); // RenderSVGHiddenContainer overwrites layout(). We need the // layouting of RenderSVGContainer for calculating local @@ -58,16 +58,15 @@ void RenderSVGResourceMarker::layout() RenderSVGContainer::layout(); } -void RenderSVGResourceMarker::invalidateClients() +void RenderSVGResourceMarker::removeAllClientsFromCache(bool markForInvalidation) { - markAllClientsForInvalidation(LayoutAndBoundariesInvalidation); + markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInvalidation : ParentOnlyInvalidation); } -void RenderSVGResourceMarker::invalidateClient(RenderObject* client) +void RenderSVGResourceMarker::removeClientFromCache(RenderObject* client, bool markForInvalidation) { ASSERT(client); - ASSERT(client->selfNeedsLayout()); - markClientForInvalidation(client, BoundariesInvalidation); + markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidation : ParentOnlyInvalidation); } void RenderSVGResourceMarker::applyViewportClip(PaintInfo& paintInfo) diff --git a/WebCore/rendering/RenderSVGResourceMarker.h b/WebCore/rendering/RenderSVGResourceMarker.h index 8509aca..e41096e 100644 --- a/WebCore/rendering/RenderSVGResourceMarker.h +++ b/WebCore/rendering/RenderSVGResourceMarker.h @@ -41,8 +41,8 @@ public: virtual const char* renderName() const { return "RenderSVGResourceMarker"; } - virtual void invalidateClients(); - virtual void invalidateClient(RenderObject*); + virtual void removeAllClientsFromCache(bool markForInvalidation = true); + virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true); void draw(PaintInfo&, const AffineTransform&); diff --git a/WebCore/rendering/RenderSVGResourceMasker.cpp b/WebCore/rendering/RenderSVGResourceMasker.cpp index 2c36c96..9713dd6 100644 --- a/WebCore/rendering/RenderSVGResourceMasker.cpp +++ b/WebCore/rendering/RenderSVGResourceMasker.cpp @@ -35,6 +35,7 @@ #include "IntRect.h" #include "RenderSVGResource.h" #include "SVGElement.h" +#include "SVGImageBufferTools.h" #include "SVGMaskElement.h" #include "SVGStyledElement.h" #include "SVGUnitTypes.h" @@ -59,26 +60,25 @@ RenderSVGResourceMasker::~RenderSVGResourceMasker() m_masker.clear(); } -void RenderSVGResourceMasker::invalidateClients() +void RenderSVGResourceMasker::removeAllClientsFromCache(bool markForInvalidation) { - m_maskBoundaries = FloatRect(); + m_maskContentBoundaries = FloatRect(); if (!m_masker.isEmpty()) { deleteAllValues(m_masker); m_masker.clear(); } - markAllClientsForInvalidation(LayoutAndBoundariesInvalidation); + markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInvalidation : ParentOnlyInvalidation); } -void RenderSVGResourceMasker::invalidateClient(RenderObject* client) +void RenderSVGResourceMasker::removeClientFromCache(RenderObject* client, bool markForInvalidation) { ASSERT(client); - ASSERT(client->selfNeedsLayout()); if (m_masker.contains(client)) delete m_masker.take(client); - markClientForInvalidation(client, BoundariesInvalidation); + markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidation : ParentOnlyInvalidation); } bool RenderSVGResourceMasker::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode) @@ -95,73 +95,47 @@ bool RenderSVGResourceMasker::applyResource(RenderObject* object, RenderStyle*, m_masker.set(object, new MaskerData); MaskerData* maskerData = m_masker.get(object); - if (!maskerData->maskImage && !maskerData->emptyMask) { + + AffineTransform absoluteTransform(SVGImageBufferTools::absoluteTransformFromContext(context)); + FloatRect maskRect = absoluteTransform.mapRect(object->repaintRectInLocalCoordinates()); + + if (!maskerData->maskImage && !maskRect.isEmpty()) { SVGMaskElement* maskElement = static_cast<SVGMaskElement*>(node()); if (!maskElement) return false; - createMaskImage(maskerData, maskElement, object); + + if (!SVGImageBufferTools::createImageBuffer(absoluteTransform, maskRect, maskerData->maskImage, LinearRGB)) + return false; + + ASSERT(maskerData->maskImage); + drawContentIntoMaskImage(maskRect, maskerData, maskElement, object); } if (!maskerData->maskImage) return false; - context->clipToImageBuffer(maskerData->maskRect, maskerData->maskImage.get()); + SVGImageBufferTools::clipToImageBuffer(context, absoluteTransform, maskRect, maskerData->maskImage.get()); return true; } -void RenderSVGResourceMasker::createMaskImage(MaskerData* maskerData, const SVGMaskElement* maskElement, RenderObject* object) +void RenderSVGResourceMasker::drawContentIntoMaskImage(const FloatRect& maskRect, MaskerData* maskerData, const SVGMaskElement* maskElement, RenderObject* object) { - FloatRect objectBoundingBox = object->objectBoundingBox(); - - // Mask rect clipped with clippingBoundingBox and filterBoundingBox as long as they are present. - maskerData->maskRect = object->repaintRectInLocalCoordinates(); - if (maskerData->maskRect.isEmpty()) { - maskerData->emptyMask = true; - return; - } - - if (m_maskBoundaries.isEmpty()) - calculateMaskContentRepaintRect(); + IntRect maskImageRect = enclosingIntRect(maskRect); + maskImageRect.setLocation(IntPoint()); - FloatRect repaintRect = m_maskBoundaries; - AffineTransform contextTransform; - // We need to scale repaintRect for objectBoundingBox to get the drawing area. + // Eventually adjust the mask image context according to the target objectBoundingBox. if (maskElement->maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { - contextTransform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); - FloatPoint contextAdjustment = repaintRect.location(); - repaintRect = contextTransform.mapRect(repaintRect); - repaintRect.move(objectBoundingBox.x(), objectBoundingBox.y()); - contextTransform.translate(-contextAdjustment.x(), -contextAdjustment.y()); - } - repaintRect.intersect(maskerData->maskRect); - maskerData->maskRect = repaintRect; - IntRect maskImageRect = enclosingIntRect(maskerData->maskRect); - - maskImageRect.setLocation(IntPoint()); + GraphicsContext* maskImageContext = maskerData->maskImage->context(); + ASSERT(maskImageContext); - // Don't create ImageBuffers with image size of 0 - if (maskImageRect.isEmpty()) { - maskerData->emptyMask = true; - return; + FloatRect objectBoundingBox = object->objectBoundingBox(); + AffineTransform contextTransform; + contextTransform.translate(objectBoundingBox.x(), objectBoundingBox.y()); + contextTransform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); + maskImageContext->concatCTM(contextTransform); } - // FIXME: This changes color space to linearRGB, the default color space - // for masking operations in SVG. We need a switch for the other color-space - // attribute values sRGB, inherit and auto. - maskerData->maskImage = ImageBuffer::create(maskImageRect.size(), LinearRGB); - if (!maskerData->maskImage) - return; - - GraphicsContext* maskImageContext = maskerData->maskImage->context(); - ASSERT(maskImageContext); - - maskImageContext->save(); - - if (maskElement->maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE) - maskImageContext->translate(-maskerData->maskRect.x(), -maskerData->maskRect.y()); - maskImageContext->concatCTM(contextTransform); - - // draw the content into the ImageBuffer + // Draw the content into the ImageBuffer. for (Node* node = maskElement->firstChild(); node; node = node->nextSibling()) { RenderObject* renderer = node->renderer(); if (!node->isSVGElement() || !static_cast<SVGElement*>(node)->isStyled() || !renderer) @@ -172,8 +146,6 @@ void RenderSVGResourceMasker::createMaskImage(MaskerData* maskerData, const SVGM SVGRenderSupport::renderSubtreeToImage(maskerData->maskImage.get(), renderer); } - maskImageContext->restore(); - #if !PLATFORM(CG) maskerData->maskImage->transformColorSpace(DeviceRGB, LinearRGB); #endif @@ -206,31 +178,31 @@ void RenderSVGResourceMasker::calculateMaskContentRepaintRect() RenderStyle* style = renderer->style(); if (!style || style->display() == NONE || style->visibility() != VISIBLE) continue; - m_maskBoundaries.unite(renderer->localToParentTransform().mapRect(renderer->repaintRectInLocalCoordinates())); + m_maskContentBoundaries.unite(renderer->localToParentTransform().mapRect(renderer->repaintRectInLocalCoordinates())); } } FloatRect RenderSVGResourceMasker::resourceBoundingBox(RenderObject* object) { - // Resource was not layouted yet. Give back clipping rect of the mask. SVGMaskElement* maskElement = static_cast<SVGMaskElement*>(node()); + ASSERT(maskElement); + FloatRect objectBoundingBox = object->objectBoundingBox(); FloatRect maskBoundaries = maskElement->maskBoundingBox(objectBoundingBox); + + // Resource was not layouted yet. Give back clipping rect of the mask. if (selfNeedsLayout()) return maskBoundaries; - if (m_maskBoundaries.isEmpty()) + if (m_maskContentBoundaries.isEmpty()) calculateMaskContentRepaintRect(); - if (!maskElement) - return FloatRect(); - - FloatRect maskRect = m_maskBoundaries; + FloatRect maskRect = m_maskContentBoundaries; if (maskElement->maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { AffineTransform transform; transform.translate(objectBoundingBox.x(), objectBoundingBox.y()); transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); - maskRect = transform.mapRect(maskRect); + maskRect = transform.mapRect(maskRect); } maskRect.intersect(maskBoundaries); diff --git a/WebCore/rendering/RenderSVGResourceMasker.h b/WebCore/rendering/RenderSVGResourceMasker.h index f6301cb..f2d8cb2 100644 --- a/WebCore/rendering/RenderSVGResourceMasker.h +++ b/WebCore/rendering/RenderSVGResourceMasker.h @@ -36,14 +36,7 @@ namespace WebCore { struct MaskerData { - MaskerData() - : emptyMask(false) - { - } - OwnPtr<ImageBuffer> maskImage; - FloatRect maskRect; - bool emptyMask; }; class RenderSVGResourceMasker : public RenderSVGResourceContainer { @@ -53,9 +46,8 @@ public: virtual const char* renderName() const { return "RenderSVGResourceMasker"; } - virtual void invalidateClients(); - virtual void invalidateClient(RenderObject*); - + virtual void removeAllClientsFromCache(bool markForInvalidation = true); + virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true); virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); virtual FloatRect resourceBoundingBox(RenderObject*); @@ -66,10 +58,10 @@ public: static RenderSVGResourceType s_resourceType; private: - void createMaskImage(MaskerData*, const SVGMaskElement*, RenderObject*); + void drawContentIntoMaskImage(const FloatRect& maskRect, MaskerData*, const SVGMaskElement*, RenderObject*); void calculateMaskContentRepaintRect(); - FloatRect m_maskBoundaries; + FloatRect m_maskContentBoundaries; HashMap<RenderObject*, MaskerData*> m_masker; }; diff --git a/WebCore/rendering/RenderSVGResourcePattern.cpp b/WebCore/rendering/RenderSVGResourcePattern.cpp index 902ff02..f4f5cf4 100644 --- a/WebCore/rendering/RenderSVGResourcePattern.cpp +++ b/WebCore/rendering/RenderSVGResourcePattern.cpp @@ -47,25 +47,24 @@ RenderSVGResourcePattern::~RenderSVGResourcePattern() m_pattern.clear(); } -void RenderSVGResourcePattern::invalidateClients() +void RenderSVGResourcePattern::removeAllClientsFromCache(bool markForInvalidation) { if (!m_pattern.isEmpty()) { deleteAllValues(m_pattern); m_pattern.clear(); } - markAllClientsForInvalidation(RepaintInvalidation); + markAllClientsForInvalidation(markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation); } -void RenderSVGResourcePattern::invalidateClient(RenderObject* client) +void RenderSVGResourcePattern::removeClientFromCache(RenderObject* client, bool markForInvalidation) { ASSERT(client); - ASSERT(client->selfNeedsLayout()); if (m_pattern.contains(client)) delete m_pattern.take(client); - markClientForInvalidation(client, RepaintInvalidation); + markClientForInvalidation(client, markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation); } bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle* style, GraphicsContext*& context, unsigned short resourceMode) @@ -77,7 +76,7 @@ bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle* // Be sure to synchronize all SVG properties on the patternElement _before_ processing any further. // Otherwhise the call to collectPatternAttributes() in createTileImage(), may cause the SVG DOM property - // synchronization to kick in, which causes invalidateClients() to be called, which in turn deletes our + // synchronization to kick in, which causes removeAllClientsFromCache() to be called, which in turn deletes our // PatternData object! Leaving out the line below will cause svg/dynamic-updates/SVGPatternElement-svgdom* to crash. SVGPatternElement* patternElement = static_cast<SVGPatternElement*>(node()); if (!patternElement) @@ -298,14 +297,15 @@ PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(PatternData* p void RenderSVGResourcePattern::buildPattern(PatternData* patternData, PassOwnPtr<ImageBuffer> tileImage) const { - if (!tileImage->image()) { + RefPtr<Image> copiedImage = tileImage->copyImage(); + if (!copiedImage) { patternData->pattern = 0; return; } - - IntRect tileRect = tileImage->image()->rect(); + + IntRect tileRect = copiedImage->rect(); if (tileRect.width() <= patternData->boundaries.width() && tileRect.height() <= patternData->boundaries.height()) { - patternData->pattern = Pattern::create(tileImage->image(), true, true); + patternData->pattern = Pattern::create(copiedImage, true, true); return; } @@ -331,13 +331,13 @@ void RenderSVGResourcePattern::buildPattern(PatternData* patternData, PassOwnPtr newTileImageContext->translate(0, patternData->boundaries.height()); for (int j = numX; j > 0; --j) { newTileImageContext->translate(patternData->boundaries.width(), 0); - newTileImageContext->drawImage(tileImage->image(), style()->colorSpace(), tileRect, tileRect); + newTileImageContext->drawImage(copiedImage.get(), style()->colorSpace(), tileRect, tileRect); } newTileImageContext->translate(-patternData->boundaries.width() * numX, 0); } newTileImageContext->restore(); - patternData->pattern = Pattern::create(newTileImage->image(), true, true); + patternData->pattern = Pattern::create(newTileImage->copyImage(), true, true); } } diff --git a/WebCore/rendering/RenderSVGResourcePattern.h b/WebCore/rendering/RenderSVGResourcePattern.h index 690b0de..52bf09d 100644 --- a/WebCore/rendering/RenderSVGResourcePattern.h +++ b/WebCore/rendering/RenderSVGResourcePattern.h @@ -51,8 +51,8 @@ public: virtual const char* renderName() const { return "RenderSVGResourcePattern"; } - virtual void invalidateClients(); - virtual void invalidateClient(RenderObject*); + virtual void removeAllClientsFromCache(bool markForInvalidation = true); + virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true); virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode); diff --git a/WebCore/rendering/RenderSVGResourceSolidColor.h b/WebCore/rendering/RenderSVGResourceSolidColor.h index ad7fd27..44109db 100644 --- a/WebCore/rendering/RenderSVGResourceSolidColor.h +++ b/WebCore/rendering/RenderSVGResourceSolidColor.h @@ -33,8 +33,8 @@ public: RenderSVGResourceSolidColor(); virtual ~RenderSVGResourceSolidColor(); - virtual void invalidateClients() { } - virtual void invalidateClient(RenderObject*) { } + virtual void removeAllClientsFromCache(bool = true) { } + virtual void removeClientFromCache(RenderObject*, bool = true) { } virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode); diff --git a/WebCore/rendering/RenderTableSection.cpp b/WebCore/rendering/RenderTableSection.cpp index e192e29..8cb54c0 100644 --- a/WebCore/rendering/RenderTableSection.cpp +++ b/WebCore/rendering/RenderTableSection.cpp @@ -25,7 +25,6 @@ #include "config.h" #include "RenderTableSection.h" - #include "CachedImage.h" #include "Document.h" #include "HitTestResult.h" @@ -1116,38 +1115,43 @@ void RenderTableSection::paintObject(PaintInfo& paintInfo, int tx, int ty) // If some cell overflows, just paint all of them. if (!m_hasOverflowingCell) { - for (; startrow < totalRows; startrow++) { - if (ty + m_rowPos[startrow + 1] >= y - os) - break; - } - if (startrow == totalRows && ty + m_rowPos[totalRows] + table()->outerBorderBottom() >= y - os) - startrow--; + int relativeY = y - ty; + int top = relativeY - os; + // binary search to find a row + startrow = std::lower_bound(m_rowPos.begin(), m_rowPos.end(), top) - m_rowPos.begin(); + + // The binary search above gives us the first row with + // a y position >= the top of the paint rect. Thus, the previous + // may need to be repainted as well. + if (startrow == m_rowPos.size() || (startrow > 0 && (m_rowPos[startrow] > top))) + --startrow; + + int bottom = relativeY + h + os - 1; + endrow = std::lower_bound(m_rowPos.begin(), m_rowPos.end(), bottom) - m_rowPos.begin(); + if ((endrow == m_rowPos.size()) || (endrow > 0 && m_rowPos[endrow - 1] == bottom)) + --endrow; - for (; endrow > 0; endrow--) { - if (ty + m_rowPos[endrow - 1] <= y + h + os) - break; - } if (!endrow && ty + m_rowPos[0] - table()->outerBorderTop() <= y + h + os) - endrow++; + ++endrow; } - unsigned startcol = 0; unsigned endcol = totalCols; // FIXME: Implement RTL. if (!m_hasOverflowingCell && style()->direction() == LTR) { - for (; startcol < totalCols; startcol++) { - if (tx + table()->columnPositions()[startcol + 1] >= x - os) - break; - } - if (startcol == totalCols && tx + table()->columnPositions()[totalCols] + table()->outerBorderRight() >= x - os) - startcol--; + int relativeX = x - tx; + int left = relativeX - os; + Vector<int>& columnPos = table()->columnPositions(); + startcol = std::lower_bound(columnPos.begin(), columnPos.end(), left) - columnPos.begin(); + if ((startcol == columnPos.size()) || (startcol > 0 && (columnPos[startcol] > left))) + --startcol; + + int right = relativeX + w + os - 1; + endcol = std::lower_bound(columnPos.begin(), columnPos.end(), right) - columnPos.begin(); + if (endcol == columnPos.size() || (endcol > 0 && (columnPos[endcol - 1] == right))) + --endcol; - for (; endcol > 0; endcol--) { - if (tx + table()->columnPositions()[endcol - 1] <= x + w + os) - break; - } if (!endcol && tx + table()->columnPositions()[0] - table()->outerBorderLeft() <= y + w + os) - endcol++; + ++endcol; } #ifdef ANDROID_LAYOUT @@ -1282,6 +1286,10 @@ void RenderTableSection::splitColumn(int pos, int first) // Hit Testing bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int xPos, int yPos, int tx, int ty, HitTestAction action) { + // If we have no children then we have nothing to do. + if (!firstChild()) + return false; + // Table sections cannot ever be hit tested. Effectively they do not exist. // Just forward to our children always. tx += x(); @@ -1290,17 +1298,56 @@ bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResul if (hasOverflowClip() && !overflowClipRect(tx, ty).intersects(result.rectFromPoint(xPos, yPos))) return false; - for (RenderObject* child = lastChild(); child; child = child->previousSibling()) { - // FIXME: We have to skip over inline flows, since they can show up inside table rows - // at the moment (a demoted inline <form> for example). If we ever implement a - // table-specific hit-test method (which we should do for performance reasons anyway), - // then we can remove this check. - if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && child->nodeAtPoint(request, result, xPos, yPos, tx, ty, action)) { + if (m_hasOverflowingCell) { + for (RenderObject* child = lastChild(); child; child = child->previousSibling()) { + // FIXME: We have to skip over inline flows, since they can show up inside table rows + // at the moment (a demoted inline <form> for example). If we ever implement a + // table-specific hit-test method (which we should do for performance reasons anyway), + // then we can remove this check. + if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && child->nodeAtPoint(request, result, xPos, yPos, tx, ty, action)) { + updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty)); + return true; + } + } + return false; + } + + int relativeY = yPos - ty; + // leftrow corresponds to the first row that starts after the y mouse position + unsigned leftrow = std::upper_bound(m_rowPos.begin(), m_rowPos.end(), relativeY) - m_rowPos.begin(); + if (leftrow == m_rowPos.size()) + return false; + // Grab the last row that starts before the y mouse position. + if (leftrow > 0) + --leftrow; + + Vector<int>& columnPos = table()->columnPositions(); + bool rtl = style()->direction() == RTL; + int relativeX = xPos - tx; + if (rtl) + relativeX = columnPos[columnPos.size() - 1] - relativeX; + + unsigned leftcol = std::lower_bound(columnPos.begin(), columnPos.end(), relativeX) - columnPos.begin(); + if (leftcol == columnPos.size()) + return false; + if (leftcol > 0) + --leftcol; + + CellStruct& current = cellAt(leftrow, leftcol); + + // If the cell is empty, there's nothing to do + if (!current.hasCells()) + return false; + + for (int i = current.cells.size() - 1; i >= 0; --i) { + RenderTableCell* cell = current.cells[i]; + if (static_cast<RenderObject*>(cell)->nodeAtPoint(request, result, xPos, yPos, tx, ty, action)) { updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty)); return true; } } return false; + } } // namespace WebCore diff --git a/WebCore/rendering/RenderText.cpp b/WebCore/rendering/RenderText.cpp index bd050d8..da152b0 100644 --- a/WebCore/rendering/RenderText.cpp +++ b/WebCore/rendering/RenderText.cpp @@ -37,13 +37,13 @@ #include "RenderBlock.h" #include "RenderLayer.h" #include "RenderView.h" -#include "StringBuffer.h" #include "Text.h" #include "TextBreakIterator.h" #include "TextResourceDecoder.h" #include "VisiblePosition.h" #include "break_lines.h" #include <wtf/AlwaysInline.h> +#include <wtf/text/StringBuffer.h> using namespace std; using namespace WTF; diff --git a/WebCore/rendering/RenderTextControl.cpp b/WebCore/rendering/RenderTextControl.cpp index d1c8039..5f8c788 100644 --- a/WebCore/rendering/RenderTextControl.cpp +++ b/WebCore/rendering/RenderTextControl.cpp @@ -29,6 +29,7 @@ #include "EventNames.h" #include "Frame.h" #include "HTMLBRElement.h" +#include "HTMLFormControlElement.h" #include "HTMLNames.h" #include "HitTestResult.h" #include "RenderLayer.h" @@ -217,12 +218,14 @@ int RenderTextControl::selectionEnd() void RenderTextControl::setSelectionStart(int start) { - setSelectionRange(start, max(start, selectionEnd())); + HTMLTextFormControlElement* element = static_cast<HTMLTextFormControlElement*>(node()); + setSelectionRange(start, max(start, element->selectionEnd())); } void RenderTextControl::setSelectionEnd(int end) { - setSelectionRange(min(end, selectionStart()), end); + HTMLTextFormControlElement* element = static_cast<HTMLTextFormControlElement*>(node()); + setSelectionRange(min(end, element->selectionStart()), end); } void RenderTextControl::select() diff --git a/WebCore/rendering/RenderTheme.h b/WebCore/rendering/RenderTheme.h index 1e0b54c..aedb8eb 100644 --- a/WebCore/rendering/RenderTheme.h +++ b/WebCore/rendering/RenderTheme.h @@ -29,7 +29,6 @@ #include "ThemeTypes.h" #endif #include "RenderObject.h" -#include "RenderTheme.h" #include "ScrollTypes.h" #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> diff --git a/WebCore/rendering/RenderThemeChromiumMac.h b/WebCore/rendering/RenderThemeChromiumMac.h index 2309081..d1875fc 100644 --- a/WebCore/rendering/RenderThemeChromiumMac.h +++ b/WebCore/rendering/RenderThemeChromiumMac.h @@ -41,8 +41,11 @@ protected: virtual bool shouldRenderMediaControlPart(ControlPart, Element*); virtual String extraMediaControlsStyleSheet(); + virtual bool paintMediaSliderThumb(RenderObject*, const PaintInfo&, const IntRect&); + virtual bool paintMediaVolumeSliderContainer(RenderObject*, const PaintInfo&, const IntRect&); virtual bool paintMediaVolumeSliderTrack(RenderObject*, const PaintInfo&, const IntRect&); virtual bool paintMediaVolumeSliderThumb(RenderObject*, const PaintInfo&, const IntRect&); + virtual IntPoint volumeSliderOffsetFromMuteButton(Node*, const IntSize&) const; #endif diff --git a/WebCore/rendering/RenderThemeChromiumMac.mm b/WebCore/rendering/RenderThemeChromiumMac.mm index a43da1e..e8ffe6c 100644 --- a/WebCore/rendering/RenderThemeChromiumMac.mm +++ b/WebCore/rendering/RenderThemeChromiumMac.mm @@ -134,6 +134,11 @@ String RenderThemeChromiumMac::extraMediaControlsStyleSheet() return String(mediaControlsChromiumUserAgentStyleSheet, sizeof(mediaControlsChromiumUserAgentStyleSheet)); } +bool RenderThemeChromiumMac::paintMediaVolumeSliderContainer(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) +{ + return true; +} + bool RenderThemeChromiumMac::paintMediaVolumeSliderTrack(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) { return RenderMediaControlsChromium::paintMediaControlsPart(MediaVolumeSlider, object, paintInfo, rect); @@ -144,6 +149,15 @@ bool RenderThemeChromiumMac::paintMediaVolumeSliderThumb(RenderObject* object, c return RenderMediaControlsChromium::paintMediaControlsPart(MediaVolumeSliderThumb, object, paintInfo, rect); } +bool RenderThemeChromiumMac::paintMediaSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) +{ + return RenderMediaControlsChromium::paintMediaControlsPart(MediaSliderThumb, object, paintInfo, rect); +} + +IntPoint RenderThemeChromiumMac::volumeSliderOffsetFromMuteButton(Node* muteButton, const IntSize& size) const +{ + return RenderTheme::volumeSliderOffsetFromMuteButton(muteButton, size); +} #endif } // namespace WebCore diff --git a/WebCore/rendering/RenderThemeMac.mm b/WebCore/rendering/RenderThemeMac.mm index cc2ff1f..7982834 100644 --- a/WebCore/rendering/RenderThemeMac.mm +++ b/WebCore/rendering/RenderThemeMac.mm @@ -963,7 +963,8 @@ bool RenderThemeMac::paintProgressBar(RenderObject* renderObject, const PaintInf paintInfo.context->translate(2 * rect.x() + rect.width(), 0); paintInfo.context->scale(FloatSize(-1, 1)); } - paintInfo.context->drawImage(imageBuffer->image(), DeviceColorSpace, rect.location()); + + paintInfo.context->drawImageBuffer(imageBuffer.get(), DeviceColorSpace, rect.location()); paintInfo.context->restore(); return false; diff --git a/WebCore/rendering/RenderTreeAsText.cpp b/WebCore/rendering/RenderTreeAsText.cpp index 408015c..e10c2f1 100644 --- a/WebCore/rendering/RenderTreeAsText.cpp +++ b/WebCore/rendering/RenderTreeAsText.cpp @@ -442,7 +442,7 @@ void write(TextStream& ts, const RenderObject& o, int indent, RenderAsTextBehavi return; } if (o.isSVGImage()) { - writeSVGImage(ts, *toRenderImage(&o), indent); + writeSVGImage(ts, *toRenderSVGImage(&o), indent); return; } #endif diff --git a/WebCore/rendering/RenderVideo.cpp b/WebCore/rendering/RenderVideo.cpp index ab969cc..0f444b2 100644 --- a/WebCore/rendering/RenderVideo.cpp +++ b/WebCore/rendering/RenderVideo.cpp @@ -134,13 +134,14 @@ void RenderVideo::imageChanged(WrappedImagePtr newImage, const IntRect* rect) RenderMedia::imageChanged(newImage, rect); // Cache the image intrinsic size so we can continue to use it to draw the image correctly - // even after we know the video intrisic size but aren't able to draw video frames yet - // (we don't want to scale the poster to the video size). - if (videoElement()->shouldDisplayPosterImage()) { - if (errorOccurred()) - updateIntrinsicSize(); + // even if we know the video intrinsic size but aren't able to draw video frames yet + // (we don't want to scale the poster to the video size without keeping aspect ratio). + if (videoElement()->shouldDisplayPosterImage()) m_cachedImageSize = intrinsicSize(); - } + + // The intrinsic size is now that of the image, but in case we already had the + // intrinsic size of the video we call this here to restore the video size. + updateIntrinsicSize(); } IntRect RenderVideo::videoBox() const diff --git a/WebCore/rendering/RenderView.cpp b/WebCore/rendering/RenderView.cpp index 449c15c..acb8487 100644 --- a/WebCore/rendering/RenderView.cpp +++ b/WebCore/rendering/RenderView.cpp @@ -186,7 +186,7 @@ void RenderView::paint(PaintInfo& paintInfo, int tx, int ty) ASSERT(!needsLayout()); // Cache the print rect because the dirty rect could get changed during painting. - if (printing()) + if (document()->paginated()) setPrintRect(paintInfo.rect); else setPrintRect(IntRect()); diff --git a/WebCore/rendering/SVGImageBufferTools.cpp b/WebCore/rendering/SVGImageBufferTools.cpp new file mode 100644 index 0000000..5b45ccc --- /dev/null +++ b/WebCore/rendering/SVGImageBufferTools.cpp @@ -0,0 +1,73 @@ +/* + Copyright (C) Research In Motion Limited 2010. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(SVG) +#include "SVGImageBufferTools.h" + +#include "GraphicsContext.h" +#include "RenderObject.h" + +namespace WebCore { + +AffineTransform SVGImageBufferTools::absoluteTransformFromContext(GraphicsContext* context) +{ + // Extract current transformation matrix used in the original context. Note that this coordinate + // system is flipped compared to SVGs internal coordinate system, done in WebKit level. Fix + // this transformation by flipping the y component. + return context->getCTM() * AffineTransform().flipY(); +} + +bool SVGImageBufferTools::createImageBuffer(const AffineTransform& absoluteTransform, const FloatRect& absoluteTargetRect, OwnPtr<ImageBuffer>& imageBuffer, ImageColorSpace colorSpace) +{ + IntRect imageRect = enclosingIntRect(absoluteTargetRect); + if (imageRect.isEmpty()) + return false; + + // Allocate an image buffer as big as the absolute unclipped size of the object + OwnPtr<ImageBuffer> image = ImageBuffer::create(imageRect.size(), colorSpace); + if (!image) + return false; + + GraphicsContext* imageContext = image->context(); + + // Transform the mask image coordinate system to absolute screen coordinates + imageContext->translate(-absoluteTargetRect.x(), -absoluteTargetRect.y()); + imageContext->concatCTM(absoluteTransform); + + imageBuffer = image.release(); + return true; +} + +void SVGImageBufferTools::clipToImageBuffer(GraphicsContext* context, const AffineTransform& absoluteTransform, const FloatRect& absoluteTargetRect, ImageBuffer* imageBuffer) +{ + ASSERT(context); + ASSERT(imageBuffer); + + // The mask image has been created in the device coordinate space, as the image should not be scaled. + // So the actual masking process has to be done in the device coordinate space as well. + context->concatCTM(absoluteTransform.inverse()); + context->clipToImageBuffer(imageBuffer, absoluteTargetRect); + context->concatCTM(absoluteTransform); +} + +} + +#endif // ENABLE(SVG) diff --git a/WebCore/rendering/SVGImageBufferTools.h b/WebCore/rendering/SVGImageBufferTools.h new file mode 100644 index 0000000..bdbcb1c --- /dev/null +++ b/WebCore/rendering/SVGImageBufferTools.h @@ -0,0 +1,49 @@ +/* + Copyright (C) Research In Motion Limited 2010. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + aint 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 SVGImageBufferTools_h +#define SVGImageBufferTools_h + +#if ENABLE(SVG) +#include "ImageBuffer.h" +#include <wtf/Noncopyable.h> + +namespace WebCore { + +class AffineTransform; +class FloatRect; +class GraphicsContext; +class RenderObject; + +class SVGImageBufferTools : public Noncopyable { +public: + static bool createImageBuffer(const AffineTransform& absoluteTransform, const FloatRect& absoluteTargetRect, OwnPtr<ImageBuffer>&, ImageColorSpace); + static void clipToImageBuffer(GraphicsContext*, const AffineTransform& absoluteTransform, const FloatRect& absoluteTargetRect, ImageBuffer*); + + static AffineTransform absoluteTransformFromContext(GraphicsContext*); + +private: + SVGImageBufferTools() { } + ~SVGImageBufferTools() { } +}; + +} + +#endif +#endif diff --git a/WebCore/rendering/SVGRenderSupport.cpp b/WebCore/rendering/SVGRenderSupport.cpp index 67e19f2..e265b2b 100644 --- a/WebCore/rendering/SVGRenderSupport.cpp +++ b/WebCore/rendering/SVGRenderSupport.cpp @@ -229,9 +229,20 @@ static inline RenderSVGRoot* svgRootTreeObject(RenderObject* start) return toRenderSVGRoot(start); } +static inline void invalidateResourcesOfChildren(RenderObject* start) +{ + ASSERT(!start->needsLayout()); + if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(start)) + resources->removeClientFromCache(start, false); + + for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) + invalidateResourcesOfChildren(child); +} + void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout) { bool layoutSizeChanged = svgRootTreeObject(start)->isLayoutSizeChanged(); + HashSet<RenderObject*> notlayoutedObjects; for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) { bool needsLayout = selfNeedsLayout; @@ -252,11 +263,25 @@ void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout) if (needsLayout) { child->setNeedsLayout(true, false); child->layout(); - } else - child->layoutIfNeeded(); + } else { + if (child->needsLayout()) + child->layout(); + else if (layoutSizeChanged) + notlayoutedObjects.add(child); + } ASSERT(!child->needsLayout()); } + + if (!layoutSizeChanged) { + ASSERT(notlayoutedObjects.isEmpty()); + return; + } + + // If the layout size changed, invalidate all resources of all children that didn't go through the layout() code path. + HashSet<RenderObject*>::iterator end = notlayoutedObjects.end(); + for (HashSet<RenderObject*>::iterator it = notlayoutedObjects.begin(); it != end; ++it) + invalidateResourcesOfChildren(*it); } bool SVGRenderSupport::isOverflowHidden(const RenderObject* object) diff --git a/WebCore/rendering/SVGRenderTreeAsText.cpp b/WebCore/rendering/SVGRenderTreeAsText.cpp index db4c07a..0c9b7e1 100644 --- a/WebCore/rendering/SVGRenderTreeAsText.cpp +++ b/WebCore/rendering/SVGRenderTreeAsText.cpp @@ -43,6 +43,7 @@ #include "RenderPath.h" #include "RenderSVGContainer.h" #include "RenderSVGGradientStop.h" +#include "RenderSVGImage.h" #include "RenderSVGInlineText.h" #include "RenderSVGResourceClipper.h" #include "RenderSVGResourceFilter.h" @@ -708,7 +709,7 @@ void writeSVGInlineText(TextStream& ts, const RenderText& text, int indent) writeSVGInlineTextBoxes(ts, text, indent); } -void writeSVGImage(TextStream& ts, const RenderImage& image, int indent) +void writeSVGImage(TextStream& ts, const RenderSVGImage& image, int indent) { writeStandardPrefix(ts, image, indent); writePositionAndStyle(ts, image); diff --git a/WebCore/rendering/SVGRenderTreeAsText.h b/WebCore/rendering/SVGRenderTreeAsText.h index 0fda958..d4aeaac 100644 --- a/WebCore/rendering/SVGRenderTreeAsText.h +++ b/WebCore/rendering/SVGRenderTreeAsText.h @@ -44,6 +44,7 @@ namespace WebCore { class RenderObject; class RenderPath; class RenderSVGGradientStop; + class RenderSVGImage; class RenderSVGRoot; class RenderText; class AffineTransform; @@ -55,7 +56,7 @@ void write(TextStream&, const RenderSVGRoot&, int indent); void writeSVGGradientStop(TextStream&, const RenderSVGGradientStop&, int indent); void writeSVGResourceContainer(TextStream&, const RenderObject&, int indent); void writeSVGContainer(TextStream&, const RenderObject&, int indent); -void writeSVGImage(TextStream&, const RenderImage&, int indent); +void writeSVGImage(TextStream&, const RenderSVGImage&, int indent); void writeSVGInlineText(TextStream&, const RenderText&, int indent); void writeSVGText(TextStream&, const RenderBlock&, int indent); void writeResources(TextStream&, const RenderObject&, int indent); diff --git a/WebCore/rendering/SVGResources.cpp b/WebCore/rendering/SVGResources.cpp index 290ef41..799301b 100644 --- a/WebCore/rendering/SVGResources.cpp +++ b/WebCore/rendering/SVGResources.cpp @@ -279,7 +279,7 @@ bool SVGResources::buildCachedResources(const RenderObject* object, const SVGRen return foundResources; } -void SVGResources::invalidateClient(RenderObject* object) const +void SVGResources::removeClientFromCache(RenderObject* object, bool markForInvalidation) const { if (!m_clipperFilterMaskerData && !m_markerData && !m_fillStrokeData && !m_linkedResource) return; @@ -288,35 +288,35 @@ void SVGResources::invalidateClient(RenderObject* object) const ASSERT(!m_clipperFilterMaskerData); ASSERT(!m_markerData); ASSERT(!m_fillStrokeData); - m_linkedResource->invalidateClient(object); + m_linkedResource->removeClientFromCache(object, markForInvalidation); return; } if (m_clipperFilterMaskerData) { if (m_clipperFilterMaskerData->clipper) - m_clipperFilterMaskerData->clipper->invalidateClient(object); + m_clipperFilterMaskerData->clipper->removeClientFromCache(object, markForInvalidation); #if ENABLE(FILTERS) if (m_clipperFilterMaskerData->filter) - m_clipperFilterMaskerData->filter->invalidateClient(object); + m_clipperFilterMaskerData->filter->removeClientFromCache(object, markForInvalidation); #endif if (m_clipperFilterMaskerData->masker) - m_clipperFilterMaskerData->masker->invalidateClient(object); + m_clipperFilterMaskerData->masker->removeClientFromCache(object, markForInvalidation); } if (m_markerData) { if (m_markerData->markerStart) - m_markerData->markerStart->invalidateClient(object); + m_markerData->markerStart->removeClientFromCache(object, markForInvalidation); if (m_markerData->markerMid) - m_markerData->markerMid->invalidateClient(object); + m_markerData->markerMid->removeClientFromCache(object, markForInvalidation); if (m_markerData->markerEnd) - m_markerData->markerEnd->invalidateClient(object); + m_markerData->markerEnd->removeClientFromCache(object, markForInvalidation); } if (m_fillStrokeData) { if (m_fillStrokeData->fill) - m_fillStrokeData->fill->invalidateClient(object); + m_fillStrokeData->fill->removeClientFromCache(object, markForInvalidation); if (m_fillStrokeData->stroke) - m_fillStrokeData->stroke->invalidateClient(object); + m_fillStrokeData->stroke->removeClientFromCache(object, markForInvalidation); } } @@ -330,7 +330,7 @@ void SVGResources::resourceDestroyed(RenderSVGResourceContainer* resource) ASSERT(!m_clipperFilterMaskerData); ASSERT(!m_markerData); ASSERT(!m_fillStrokeData); - m_linkedResource->invalidateClients(); + m_linkedResource->removeAllClientsFromCache(); m_linkedResource = 0; return; } @@ -340,7 +340,7 @@ void SVGResources::resourceDestroyed(RenderSVGResourceContainer* resource) if (!m_clipperFilterMaskerData) break; if (m_clipperFilterMaskerData->masker == resource) { - m_clipperFilterMaskerData->masker->invalidateClients(); + m_clipperFilterMaskerData->masker->removeAllClientsFromCache(); m_clipperFilterMaskerData->masker = 0; } break; @@ -348,15 +348,15 @@ void SVGResources::resourceDestroyed(RenderSVGResourceContainer* resource) if (!m_markerData) break; if (m_markerData->markerStart == resource) { - m_markerData->markerStart->invalidateClients(); + m_markerData->markerStart->removeAllClientsFromCache(); m_markerData->markerStart = 0; } if (m_markerData->markerMid == resource) { - m_markerData->markerMid->invalidateClients(); + m_markerData->markerMid->removeAllClientsFromCache(); m_markerData->markerMid = 0; } if (m_markerData->markerEnd == resource) { - m_markerData->markerEnd->invalidateClients(); + m_markerData->markerEnd->removeAllClientsFromCache(); m_markerData->markerEnd = 0; } break; @@ -366,11 +366,11 @@ void SVGResources::resourceDestroyed(RenderSVGResourceContainer* resource) if (!m_fillStrokeData) break; if (m_fillStrokeData->fill == resource) { - m_fillStrokeData->fill->invalidateClients(); + m_fillStrokeData->fill->removeAllClientsFromCache(); m_fillStrokeData->fill = 0; } if (m_fillStrokeData->stroke == resource) { - m_fillStrokeData->stroke->invalidateClients(); + m_fillStrokeData->stroke->removeAllClientsFromCache(); m_fillStrokeData->stroke = 0; } break; @@ -379,7 +379,7 @@ void SVGResources::resourceDestroyed(RenderSVGResourceContainer* resource) if (!m_clipperFilterMaskerData) break; if (m_clipperFilterMaskerData->filter == resource) { - m_clipperFilterMaskerData->filter->invalidateClients(); + m_clipperFilterMaskerData->filter->removeAllClientsFromCache(); m_clipperFilterMaskerData->filter = 0; } #else @@ -390,7 +390,7 @@ void SVGResources::resourceDestroyed(RenderSVGResourceContainer* resource) if (!m_clipperFilterMaskerData) break; if (m_clipperFilterMaskerData->clipper == resource) { - m_clipperFilterMaskerData->clipper->invalidateClients(); + m_clipperFilterMaskerData->clipper->removeAllClientsFromCache(); m_clipperFilterMaskerData->clipper = 0; } break; diff --git a/WebCore/rendering/SVGResources.h b/WebCore/rendering/SVGResources.h index a07a990..5f6e746 100644 --- a/WebCore/rendering/SVGResources.h +++ b/WebCore/rendering/SVGResources.h @@ -64,7 +64,7 @@ public: void buildSetOfResources(HashSet<RenderSVGResourceContainer*>&); // Methods operating on all cached resources - void invalidateClient(RenderObject*) const; + void removeClientFromCache(RenderObject*, bool markForInvalidation = true) const; void resourceDestroyed(RenderSVGResourceContainer*); #ifndef NDEBUG diff --git a/WebCore/rendering/SVGResourcesCache.cpp b/WebCore/rendering/SVGResourcesCache.cpp index b922b44..a4089d6 100644 --- a/WebCore/rendering/SVGResourcesCache.cpp +++ b/WebCore/rendering/SVGResourcesCache.cpp @@ -121,7 +121,7 @@ void SVGResourcesCache::clientLayoutChanged(RenderObject* object) if (!resources) return; - resources->invalidateClient(object); + resources->removeClientFromCache(object); } void SVGResourcesCache::clientStyleChanged(RenderObject* renderer, StyleDifference diff, const RenderStyle* newStyle) diff --git a/WebCore/rendering/TextControlInnerElements.cpp b/WebCore/rendering/TextControlInnerElements.cpp index cf0e864..9852aa6 100644 --- a/WebCore/rendering/TextControlInnerElements.cpp +++ b/WebCore/rendering/TextControlInnerElements.cpp @@ -345,9 +345,21 @@ void SpinButtonElement::setHovered(bool flag) inline InputFieldSpeechButtonElement::InputFieldSpeechButtonElement(Node* shadowParent) : TextControlInnerElement(shadowParent->document(), shadowParent) , m_capturing(false) + , m_state(Idle) + , m_listenerId(document()->page()->speechInput()->registerListener(this)) { } +InputFieldSpeechButtonElement::~InputFieldSpeechButtonElement() +{ + SpeechInput* speech = speechInput(); + if (speech) { // Could be null when page is unloading. + if (m_state != Idle) + speech->cancelRecognition(m_listenerId); + speech->unregisterListener(m_listenerId); + } +} + PassRefPtr<InputFieldSpeechButtonElement> InputFieldSpeechButtonElement::create(Node* shadowParent) { return adoptRef(new InputFieldSpeechButtonElement(shadowParent)); @@ -383,7 +395,18 @@ void InputFieldSpeechButtonElement::defaultEventHandler(Event* event) } if (event->type() == eventNames().clickEvent) { - speechInput()->startRecognition(this); + switch (m_state) { + case Idle: + if (speechInput()->startRecognition(m_listenerId)) + setState(Recording); + break; + case Recording: + speechInput()->stopRecording(m_listenerId); + break; + case Recognizing: + // Nothing to do here, we will continue to wait for results. + break; + } event->setDefaultHandled(); } @@ -391,23 +414,30 @@ void InputFieldSpeechButtonElement::defaultEventHandler(Event* event) HTMLDivElement::defaultEventHandler(event); } +void InputFieldSpeechButtonElement::setState(SpeechInputState state) +{ + if (m_state != state) { + m_state = state; + shadowAncestorNode()->renderer()->repaint(); + } +} + SpeechInput* InputFieldSpeechButtonElement::speechInput() { - return document()->page()->speechInput(); + return document()->page() ? document()->page()->speechInput() : 0; } -void InputFieldSpeechButtonElement::didCompleteRecording() +void InputFieldSpeechButtonElement::didCompleteRecording(int) { - // FIXME: Add UI feedback here to indicate that audio recording stopped and recognition is - // in progress. + setState(Recognizing); } -void InputFieldSpeechButtonElement::didCompleteRecognition() +void InputFieldSpeechButtonElement::didCompleteRecognition(int) { - // FIXME: Add UI feedback here to indicate that audio recognition has ended. + setState(Idle); } -void InputFieldSpeechButtonElement::setRecognitionResult(const String& result) +void InputFieldSpeechButtonElement::setRecognitionResult(int, const String& result) { HTMLInputElement* input = static_cast<HTMLInputElement*>(shadowAncestorNode()); // The call to setValue() below dispatches an event, and an event handler in the page might diff --git a/WebCore/rendering/TextControlInnerElements.h b/WebCore/rendering/TextControlInnerElements.h index 2859bd5..3fbc9c8 100644 --- a/WebCore/rendering/TextControlInnerElements.h +++ b/WebCore/rendering/TextControlInnerElements.h @@ -119,21 +119,32 @@ class InputFieldSpeechButtonElement : public TextControlInnerElement, public SpeechInputListener { public: + enum SpeechInputState { + Idle, + Recording, + Recognizing, + }; + static PassRefPtr<InputFieldSpeechButtonElement> create(Node*); + virtual ~InputFieldSpeechButtonElement(); virtual void detach(); virtual void defaultEventHandler(Event*); + SpeechInputState state() const { return m_state; } // SpeechInputListener methods. - void didCompleteRecording(); - void didCompleteRecognition(); - void setRecognitionResult(const String& result); + void didCompleteRecording(int); + void didCompleteRecognition(int); + void setRecognitionResult(int, const String& result); private: InputFieldSpeechButtonElement(Node*); SpeechInput* speechInput(); + void setState(SpeechInputState state); bool m_capturing; + SpeechInputState m_state; + int m_listenerId; }; #endif // ENABLE(INPUT_SPEECH) diff --git a/WebCore/rendering/style/BindingURI.h b/WebCore/rendering/style/BindingURI.h index 923f1aa..c844b1d 100644 --- a/WebCore/rendering/style/BindingURI.h +++ b/WebCore/rendering/style/BindingURI.h @@ -26,7 +26,7 @@ #define BindingURI_h #if ENABLE(XBL) -#include "StringImpl.h" +#include <wtf/text/StringImpl.h> namespace WebCore { diff --git a/WebCore/rendering/style/ContentData.cpp b/WebCore/rendering/style/ContentData.cpp index 410cad4..b0f9e81 100644 --- a/WebCore/rendering/style/ContentData.cpp +++ b/WebCore/rendering/style/ContentData.cpp @@ -23,8 +23,8 @@ #include "ContentData.h" #include "CounterContent.h" -#include "StringImpl.h" #include "StyleImage.h" +#include <wtf/text/StringImpl.h> namespace WebCore { diff --git a/WebCore/rendering/style/CounterContent.h b/WebCore/rendering/style/CounterContent.h index 702d9c2..52757ad 100644 --- a/WebCore/rendering/style/CounterContent.h +++ b/WebCore/rendering/style/CounterContent.h @@ -25,8 +25,8 @@ #ifndef CounterContent_h #define CounterContent_h -#include "AtomicString.h" #include "RenderStyleConstants.h" +#include <wtf/text/AtomicString.h> namespace WebCore { diff --git a/WebCore/rendering/style/CounterDirectives.h b/WebCore/rendering/style/CounterDirectives.h index 9cbdeae..e54028e 100644 --- a/WebCore/rendering/style/CounterDirectives.h +++ b/WebCore/rendering/style/CounterDirectives.h @@ -25,9 +25,9 @@ #ifndef CounterDirectives_h #define CounterDirectives_h -#include "AtomicStringImpl.h" #include <wtf/HashMap.h> #include <wtf/RefPtr.h> +#include <wtf/text/AtomicStringImpl.h> namespace WebCore { diff --git a/WebCore/rendering/style/KeyframeList.h b/WebCore/rendering/style/KeyframeList.h index b1009d2..bb5f180 100644 --- a/WebCore/rendering/style/KeyframeList.h +++ b/WebCore/rendering/style/KeyframeList.h @@ -25,10 +25,10 @@ #ifndef KeyframeList_h #define KeyframeList_h -#include "AtomicString.h" #include <wtf/Vector.h> #include <wtf/HashSet.h> #include <wtf/RefPtr.h> +#include <wtf/text/AtomicString.h> namespace WebCore { diff --git a/WebCore/rendering/style/StyleRareInheritedData.h b/WebCore/rendering/style/StyleRareInheritedData.h index 07541d3..ba914d4 100644 --- a/WebCore/rendering/style/StyleRareInheritedData.h +++ b/WebCore/rendering/style/StyleRareInheritedData.h @@ -25,11 +25,11 @@ #ifndef StyleRareInheritedData_h #define StyleRareInheritedData_h -#include "AtomicString.h" #include "Color.h" #include "Length.h" #include <wtf/RefCounted.h> #include <wtf/PassRefPtr.h> +#include <wtf/text/AtomicString.h> namespace WebCore { |