summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/svg
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2012-11-07 11:22:47 +0100
committerSimon Hausmann <simon.hausmann@digia.com>2012-11-07 11:22:47 +0100
commitcfd86b747d32ac22246a1aa908eaa720c63a88c1 (patch)
tree24d68c6f61c464ecba1e05670b80390ea3b0e50c /Source/WebCore/rendering/svg
parent69d7c744c9de19d152dbe2d8e46eb7dfd4511d1a (diff)
downloadqtwebkit-cfd86b747d32ac22246a1aa908eaa720c63a88c1.tar.gz
Imported WebKit commit 20271caf2e2c016d5cef40184cddeefeac4f1876 (http://svn.webkit.org/repository/webkit/trunk@133733)
New snapshot that contains all previous fixes as well as build fix for latest QtMultimedia API changes.
Diffstat (limited to 'Source/WebCore/rendering/svg')
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGContainer.h3
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp60
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceFilter.h10
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGRoot.cpp22
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGRoot.h4
-rw-r--r--Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp13
6 files changed, 52 insertions, 60 deletions
diff --git a/Source/WebCore/rendering/svg/RenderSVGContainer.h b/Source/WebCore/rendering/svg/RenderSVGContainer.h
index 335732b84..3c0fa9814 100644
--- a/Source/WebCore/rendering/svg/RenderSVGContainer.h
+++ b/Source/WebCore/rendering/svg/RenderSVGContainer.h
@@ -36,6 +36,9 @@ public:
explicit RenderSVGContainer(SVGStyledElement*);
virtual ~RenderSVGContainer();
+ RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
+ RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
+
const RenderObjectChildList* children() const { return &m_children; }
RenderObjectChildList* children() { return &m_children; }
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp
index 74e5b36d3..7d4eedfc9 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp
@@ -57,25 +57,6 @@ using namespace std;
namespace WebCore {
-class ApplyingFilterEffectGuard {
-public:
- ApplyingFilterEffectGuard(FilterData* data)
- : m_filterData(data)
- {
- // The guard must be constructed when the filter is not applying.
- ASSERT(!m_filterData->isApplying);
- m_filterData->isApplying = true;
- }
-
- ~ApplyingFilterEffectGuard()
- {
- ASSERT(m_filterData->isApplying);
- m_filterData->isApplying = false;
- }
-
- FilterData* m_filterData;
-};
-
RenderSVGResourceType RenderSVGResourceFilter::s_resourceType = FilterResourceType;
RenderSVGResourceFilter::RenderSVGResourceFilter(SVGFilterElement* node)
@@ -108,7 +89,7 @@ void RenderSVGResourceFilter::removeClientFromCache(RenderObject* client, bool m
if (FilterData* filterData = m_filter.get(client)) {
if (filterData->savedContext)
- filterData->markedForRemoval = true;
+ filterData->state = FilterData::MarkedForRemoval;
else
delete m_filter.take(client);
}
@@ -168,14 +149,11 @@ bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*,
ASSERT(context);
ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode);
- // Returning false here, to avoid drawings onto the context. We just want to
- // draw the stored filter output, not the unfiltered object as well.
if (m_filter.contains(object)) {
FilterData* filterData = m_filter.get(object);
- if (filterData->isBuilt || filterData->isApplying)
- return false;
-
- delete m_filter.take(object); // Oops, have to rebuild, go through normal code path
+ if (filterData->state == FilterData::PaintingSource || filterData->state == FilterData::Applying)
+ filterData->state = FilterData::CycleDetected;
+ return false; // Already built, or we're in a cycle, or we're marked for removal. Regardless, just do nothing more now.
}
OwnPtr<FilterData> filterData(adoptPtr(new FilterData));
@@ -292,17 +270,21 @@ void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo
if (!filterData)
return;
- if (filterData->markedForRemoval) {
+ switch (filterData->state) {
+ case FilterData::MarkedForRemoval:
delete m_filter.take(object);
return;
- }
- // We have a cycle if we are already applying the data.
- // This can occur due to FeImage referencing a source that makes use of the FEImage itself.
- if (filterData->isApplying)
+ case FilterData::CycleDetected:
+ case FilterData::Applying:
+ // We have a cycle if we are already applying the data.
+ // This can occur due to FeImage referencing a source that makes use of the FEImage itself.
+ // This is the first place we've hit the cycle, so set the state back to PaintingSource so the return stack
+ // will continue correctly.
+ filterData->state = FilterData::PaintingSource;
return;
- if (!filterData->isBuilt) {
+ case FilterData::PaintingSource:
if (!filterData->savedContext) {
removeClientFromCache(object);
return;
@@ -310,9 +292,10 @@ void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo
context = filterData->savedContext;
filterData->savedContext = 0;
- }
+ break;
- ApplyingFilterEffectGuard isApplyingGuard(filterData);
+ case FilterData::Built: { } // Empty
+ }
FilterEffect* lastEffect = filterData->builder->lastEffect();
@@ -320,11 +303,12 @@ void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo
// This is the real filtering of the object. It just needs to be called on the
// initial filtering process. We just take the stored filter result on a
// second drawing.
- if (!filterData->isBuilt)
+ if (filterData->state != FilterData::Built)
filterData->filter->setSourceImage(filterData->sourceGraphicBuffer.release());
- // Always true if filterData is just built (filterData->isBuilt is false).
+ // Always true if filterData is just built (filterData->state == FilterData::Built).
if (!lastEffect->hasResult()) {
+ filterData->state = FilterData::Applying;
lastEffect->apply();
lastEffect->correctFilterResultIfNeeded();
#if !USE(CG)
@@ -333,7 +317,7 @@ void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo
resultImage->transformColorSpace(lastEffect->colorSpace(), ColorSpaceDeviceRGB);
#endif
}
- filterData->isBuilt = true;
+ filterData->state = FilterData::Built;
ImageBuffer* resultImage = lastEffect->asImageBuffer();
if (resultImage) {
@@ -365,7 +349,7 @@ void RenderSVGResourceFilter::primitiveAttributeChanged(RenderObject* object, co
for (; it != end; ++it) {
FilterData* filterData = it->value;
- if (!filterData->isBuilt)
+ if (filterData->state != FilterData::Built)
continue;
SVGFilterBuilder* builder = filterData->builder.get();
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h b/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h
index 0101bbc1e..db422c17e 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h
@@ -42,11 +42,11 @@ namespace WebCore {
struct FilterData {
WTF_MAKE_FAST_ALLOCATED;
public:
+ enum FilterDataState { PaintingSource, Applying, Built, CycleDetected, MarkedForRemoval };
+
FilterData()
: savedContext(0)
- , isBuilt(false)
- , isApplying(false)
- , markedForRemoval(false)
+ , state(PaintingSource)
{
}
@@ -57,9 +57,7 @@ public:
AffineTransform shearFreeAbsoluteTransform;
FloatRect boundaries;
FloatSize scale;
- bool isBuilt : 1;
- bool isApplying : 1;
- bool markedForRemoval : 1;
+ FilterDataState state;
};
class GraphicsContext;
diff --git a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp b/Source/WebCore/rendering/svg/RenderSVGRoot.cpp
index 797b70ea7..2733ae446 100644
--- a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGRoot.cpp
@@ -297,18 +297,22 @@ void RenderSVGRoot::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paint
// Convert from container offsets (html renderers) to a relative transform (svg renderers).
// Transform from our paint container's coordinate system to our local coords.
IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset);
- childPaintInfo.applyTransform(AffineTransform::translation(adjustedPaintOffset.x() - x(), adjustedPaintOffset.y() - y()) * localToParentTransform());
+ childPaintInfo.applyTransform(AffineTransform::translation(adjustedPaintOffset.x(), adjustedPaintOffset.y()) * localToBorderBoxTransform());
+
+ // SVGRenderingContext must be destroyed before we restore the childPaintInfo.context, because a filter may have
+ // changed the context and it is only reverted when the SVGRenderingContext destructor finishes applying the filter.
+ {
+ SVGRenderingContext renderingContext;
+ bool continueRendering = true;
+ if (childPaintInfo.phase == PaintPhaseForeground) {
+ renderingContext.prepareToRenderSVGContent(this, childPaintInfo);
+ continueRendering = renderingContext.isRenderingPrepared();
+ }
- SVGRenderingContext renderingContext;
- bool continueRendering = true;
- if (childPaintInfo.phase == PaintPhaseForeground) {
- renderingContext.prepareToRenderSVGContent(this, childPaintInfo);
- continueRendering = renderingContext.isRenderingPrepared();
+ if (continueRendering)
+ RenderBox::paint(childPaintInfo, LayoutPoint());
}
- if (continueRendering)
- RenderBox::paint(childPaintInfo, LayoutPoint());
-
childPaintInfo.context->restore();
}
diff --git a/Source/WebCore/rendering/svg/RenderSVGRoot.h b/Source/WebCore/rendering/svg/RenderSVGRoot.h
index 3fadc910b..1e112a199 100644
--- a/Source/WebCore/rendering/svg/RenderSVGRoot.h
+++ b/Source/WebCore/rendering/svg/RenderSVGRoot.h
@@ -43,6 +43,10 @@ public:
bool isEmbeddedThroughFrameContainingSVGDocument() const;
virtual void computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const;
+
+ RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
+ RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
+
const RenderObjectChildList* children() const { return &m_children; }
RenderObjectChildList* children() { return &m_children; }
diff --git a/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp b/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp
index 066ba31af..7341e69cd 100644
--- a/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp
+++ b/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp
@@ -188,6 +188,12 @@ GlyphData SVGTextRunRenderingContext::glyphDataForCharacter(const Font& font, co
return glyphData;
}
+ // Save data fromt he font fallback list because we may modify it later. Do this before the
+ // potential change to glyphData.fontData below.
+ FontFallbackList* fontList = font.fontList();
+ ASSERT(fontList);
+ FontFallbackList::GlyphPagesStateSaver glyphPagesSaver(*fontList);
+
// Characters enclosed by an <altGlyph> element, may not be registered in the GlyphPage.
const SimpleFontData* originalFontData = glyphData.fontData;
if (glyphData.fontData && !glyphData.fontData->isSVGFont()) {
@@ -225,14 +231,9 @@ GlyphData SVGTextRunRenderingContext::glyphDataForCharacter(const Font& font, co
GlyphPage* page = pair.second;
ASSERT(page);
- FontFallbackList* fontList = font.fontList();
- ASSERT(fontList);
-
// No suitable glyph found that is compatible with the requirments (same language, arabic-form, orientation etc.)
// Even though our GlyphPage contains an entry for eg. glyph "a", it's not compatible. So we have to temporarily
// remove the glyph data information from the GlyphPage, and retry the lookup, which handles font fallbacks correctly.
- GlyphPageTreeNode* originalGlyphPageZero = fontList->glyphPageZero();
- const FontFallbackList::GlyphPages& originalGlyphPages = fontList->glyphPages();
page->setGlyphDataForCharacter(character, glyphData.glyph, 0);
// Assure that the font fallback glyph selection worked, aka. the fallbackGlyphData font data is not the same as before.
@@ -242,8 +243,6 @@ GlyphData SVGTextRunRenderingContext::glyphDataForCharacter(const Font& font, co
// Restore original state of the SVG Font glyph table and the current font fallback list,
// to assure the next lookup of the same glyph won't immediately return the fallback glyph.
page->setGlyphDataForCharacter(character, glyphData.glyph, originalFontData);
- fontList->setGlyphPageZero(originalGlyphPageZero);
- fontList->setGlyphPages(originalGlyphPages);
ASSERT(fallbackGlyphData.fontData);
return fallbackGlyphData;
}