OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> | 2 * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> |
3 * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> | 3 * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> |
4 * Copyright (C) 2005 Eric Seidel <eric@webkit.org> | 4 * Copyright (C) 2005 Eric Seidel <eric@webkit.org> |
5 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> | 5 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> |
6 * Copyright (C) Research In Motion Limited 2010. All rights reserved. | 6 * Copyright (C) Research In Motion Limited 2010. All rights reserved. |
7 * | 7 * |
8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 #include "SourceAlpha.h" | 50 #include "SourceAlpha.h" |
51 #include "SourceGraphic.h" | 51 #include "SourceGraphic.h" |
52 | 52 |
53 #include <wtf/UnusedParam.h> | 53 #include <wtf/UnusedParam.h> |
54 #include <wtf/Vector.h> | 54 #include <wtf/Vector.h> |
55 | 55 |
56 using namespace std; | 56 using namespace std; |
57 | 57 |
58 namespace WebCore { | 58 namespace WebCore { |
59 | 59 |
60 class ApplyingFilterEffectGuard { | |
61 public: | |
62 ApplyingFilterEffectGuard(FilterData* data) | |
63 : m_filterData(data) | |
64 { | |
65 // The guard must be constructed when the filter is not applying. | |
66 ASSERT(!m_filterData->isApplying); | |
67 m_filterData->isApplying = true; | |
68 } | |
69 | |
70 ~ApplyingFilterEffectGuard() | |
71 { | |
72 ASSERT(m_filterData->isApplying); | |
73 m_filterData->isApplying = false; | |
74 } | |
75 | |
76 FilterData* m_filterData; | |
77 }; | |
78 | |
79 RenderSVGResourceType RenderSVGResourceFilter::s_resourceType = FilterResourceTy
pe; | 60 RenderSVGResourceType RenderSVGResourceFilter::s_resourceType = FilterResourceTy
pe; |
80 | 61 |
81 RenderSVGResourceFilter::RenderSVGResourceFilter(SVGFilterElement* node) | 62 RenderSVGResourceFilter::RenderSVGResourceFilter(SVGFilterElement* node) |
82 : RenderSVGResourceContainer(node) | 63 : RenderSVGResourceContainer(node) |
83 { | 64 { |
84 } | 65 } |
85 | 66 |
86 RenderSVGResourceFilter::~RenderSVGResourceFilter() | 67 RenderSVGResourceFilter::~RenderSVGResourceFilter() |
87 { | 68 { |
88 if (m_filter.isEmpty()) | 69 if (m_filter.isEmpty()) |
(...skipping 12 matching lines...) Expand all Loading... |
101 | 82 |
102 markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInval
idation : ParentOnlyInvalidation); | 83 markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInval
idation : ParentOnlyInvalidation); |
103 } | 84 } |
104 | 85 |
105 void RenderSVGResourceFilter::removeClientFromCache(RenderObject* client, bool m
arkForInvalidation) | 86 void RenderSVGResourceFilter::removeClientFromCache(RenderObject* client, bool m
arkForInvalidation) |
106 { | 87 { |
107 ASSERT(client); | 88 ASSERT(client); |
108 | 89 |
109 if (FilterData* filterData = m_filter.get(client)) { | 90 if (FilterData* filterData = m_filter.get(client)) { |
110 if (filterData->savedContext) | 91 if (filterData->savedContext) |
111 filterData->markedForRemoval = true; | 92 filterData->state = FilterData::MarkedForRemoval; |
112 else | 93 else |
113 delete m_filter.take(client); | 94 delete m_filter.take(client); |
114 } | 95 } |
115 | 96 |
116 markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidati
on : ParentOnlyInvalidation); | 97 markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidati
on : ParentOnlyInvalidation); |
117 } | 98 } |
118 | 99 |
119 PassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFilter*
filter) | 100 PassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFilter*
filter) |
120 { | 101 { |
121 SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node()); | 102 SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node()); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 | 142 |
162 return matchesFilterSize; | 143 return matchesFilterSize; |
163 } | 144 } |
164 | 145 |
165 bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*,
GraphicsContext*& context, unsigned short resourceMode) | 146 bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*,
GraphicsContext*& context, unsigned short resourceMode) |
166 { | 147 { |
167 ASSERT(object); | 148 ASSERT(object); |
168 ASSERT(context); | 149 ASSERT(context); |
169 ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode); | 150 ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode); |
170 | 151 |
171 // Returning false here, to avoid drawings onto the context. We just want to | |
172 // draw the stored filter output, not the unfiltered object as well. | |
173 if (m_filter.contains(object)) { | 152 if (m_filter.contains(object)) { |
174 FilterData* filterData = m_filter.get(object); | 153 FilterData* filterData = m_filter.get(object); |
175 if (filterData->isBuilt || filterData->isApplying) | 154 if (filterData->state == FilterData::PaintingSource || filterData->state
== FilterData::Applying) |
176 return false; | 155 filterData->state = FilterData::CycleDetected; |
177 | 156 return false; // Already built, or we're in a cycle, or we're marked for
removal. Regardless, just do nothing more now. |
178 delete m_filter.take(object); // Oops, have to rebuild, go through norma
l code path | |
179 } | 157 } |
180 | 158 |
181 OwnPtr<FilterData> filterData(adoptPtr(new FilterData)); | 159 OwnPtr<FilterData> filterData(adoptPtr(new FilterData)); |
182 FloatRect targetBoundingBox = object->objectBoundingBox(); | 160 FloatRect targetBoundingBox = object->objectBoundingBox(); |
183 | 161 |
184 SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node()); | 162 SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node()); |
185 filterData->boundaries = SVGLengthContext::resolveRectangle<SVGFilterElement
>(filterElement, filterElement->filterUnits(), targetBoundingBox); | 163 filterData->boundaries = SVGLengthContext::resolveRectangle<SVGFilterElement
>(filterElement, filterElement->filterUnits(), targetBoundingBox); |
186 if (filterData->boundaries.isEmpty()) | 164 if (filterData->boundaries.isEmpty()) |
187 return false; | 165 return false; |
188 | 166 |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo
ntext*& context, unsigned short resourceMode, const Path*, const RenderSVGShape*
) | 263 void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo
ntext*& context, unsigned short resourceMode, const Path*, const RenderSVGShape*
) |
286 { | 264 { |
287 ASSERT(object); | 265 ASSERT(object); |
288 ASSERT(context); | 266 ASSERT(context); |
289 ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode); | 267 ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode); |
290 | 268 |
291 FilterData* filterData = m_filter.get(object); | 269 FilterData* filterData = m_filter.get(object); |
292 if (!filterData) | 270 if (!filterData) |
293 return; | 271 return; |
294 | 272 |
295 if (filterData->markedForRemoval) { | 273 switch (filterData->state) { |
| 274 case FilterData::MarkedForRemoval: |
296 delete m_filter.take(object); | 275 delete m_filter.take(object); |
297 return; | 276 return; |
298 } | |
299 | 277 |
300 // We have a cycle if we are already applying the data. | 278 case FilterData::CycleDetected: |
301 // This can occur due to FeImage referencing a source that makes use of the
FEImage itself. | 279 case FilterData::Applying: |
302 if (filterData->isApplying) | 280 // We have a cycle if we are already applying the data. |
| 281 // This can occur due to FeImage referencing a source that makes use of
the FEImage itself. |
| 282 // This is the first place we've hit the cycle, so set the state back to
PaintingSource so the return stack |
| 283 // will continue correctly. |
| 284 filterData->state = FilterData::PaintingSource; |
303 return; | 285 return; |
304 | 286 |
305 if (!filterData->isBuilt) { | 287 case FilterData::PaintingSource: |
306 if (!filterData->savedContext) { | 288 if (!filterData->savedContext) { |
307 removeClientFromCache(object); | 289 removeClientFromCache(object); |
308 return; | 290 return; |
309 } | 291 } |
310 | 292 |
311 context = filterData->savedContext; | 293 context = filterData->savedContext; |
312 filterData->savedContext = 0; | 294 filterData->savedContext = 0; |
| 295 break; |
| 296 |
| 297 case FilterData::Built: { } // Empty |
313 } | 298 } |
314 | 299 |
315 ApplyingFilterEffectGuard isApplyingGuard(filterData); | |
316 | |
317 FilterEffect* lastEffect = filterData->builder->lastEffect(); | 300 FilterEffect* lastEffect = filterData->builder->lastEffect(); |
318 | 301 |
319 if (lastEffect && !filterData->boundaries.isEmpty() && !lastEffect->filterPr
imitiveSubregion().isEmpty()) { | 302 if (lastEffect && !filterData->boundaries.isEmpty() && !lastEffect->filterPr
imitiveSubregion().isEmpty()) { |
320 // This is the real filtering of the object. It just needs to be called
on the | 303 // This is the real filtering of the object. It just needs to be called
on the |
321 // initial filtering process. We just take the stored filter result on a | 304 // initial filtering process. We just take the stored filter result on a |
322 // second drawing. | 305 // second drawing. |
323 if (!filterData->isBuilt) | 306 if (filterData->state != FilterData::Built) |
324 filterData->filter->setSourceImage(filterData->sourceGraphicBuffer.r
elease()); | 307 filterData->filter->setSourceImage(filterData->sourceGraphicBuffer.r
elease()); |
325 | 308 |
326 // Always true if filterData is just built (filterData->isBuilt is false
). | 309 // Always true if filterData is just built (filterData->state == FilterD
ata::Built). |
327 if (!lastEffect->hasResult()) { | 310 if (!lastEffect->hasResult()) { |
| 311 filterData->state = FilterData::Applying; |
328 lastEffect->apply(); | 312 lastEffect->apply(); |
329 lastEffect->correctFilterResultIfNeeded(); | 313 lastEffect->correctFilterResultIfNeeded(); |
330 #if !USE(CG) | 314 #if !USE(CG) |
331 ImageBuffer* resultImage = lastEffect->asImageBuffer(); | 315 ImageBuffer* resultImage = lastEffect->asImageBuffer(); |
332 if (resultImage) | 316 if (resultImage) |
333 resultImage->transformColorSpace(lastEffect->colorSpace(), Color
SpaceDeviceRGB); | 317 resultImage->transformColorSpace(lastEffect->colorSpace(), Color
SpaceDeviceRGB); |
334 #endif | 318 #endif |
335 } | 319 } |
336 filterData->isBuilt = true; | 320 filterData->state = FilterData::Built; |
337 | 321 |
338 ImageBuffer* resultImage = lastEffect->asImageBuffer(); | 322 ImageBuffer* resultImage = lastEffect->asImageBuffer(); |
339 if (resultImage) { | 323 if (resultImage) { |
340 context->concatCTM(filterData->shearFreeAbsoluteTransform.inverse())
; | 324 context->concatCTM(filterData->shearFreeAbsoluteTransform.inverse())
; |
341 | 325 |
342 context->scale(FloatSize(1 / filterData->filter->filterResolution().
width(), 1 / filterData->filter->filterResolution().height())); | 326 context->scale(FloatSize(1 / filterData->filter->filterResolution().
width(), 1 / filterData->filter->filterResolution().height())); |
343 context->drawImageBuffer(resultImage, object->style()->colorSpace(),
lastEffect->absolutePaintRect()); | 327 context->drawImageBuffer(resultImage, object->style()->colorSpace(),
lastEffect->absolutePaintRect()); |
344 context->scale(filterData->filter->filterResolution()); | 328 context->scale(filterData->filter->filterResolution()); |
345 | 329 |
346 context->concatCTM(filterData->shearFreeAbsoluteTransform); | 330 context->concatCTM(filterData->shearFreeAbsoluteTransform); |
(...skipping 11 matching lines...) Expand all Loading... |
358 } | 342 } |
359 | 343 |
360 void RenderSVGResourceFilter::primitiveAttributeChanged(RenderObject* object, co
nst QualifiedName& attribute) | 344 void RenderSVGResourceFilter::primitiveAttributeChanged(RenderObject* object, co
nst QualifiedName& attribute) |
361 { | 345 { |
362 HashMap<RenderObject*, FilterData*>::iterator it = m_filter.begin(); | 346 HashMap<RenderObject*, FilterData*>::iterator it = m_filter.begin(); |
363 HashMap<RenderObject*, FilterData*>::iterator end = m_filter.end(); | 347 HashMap<RenderObject*, FilterData*>::iterator end = m_filter.end(); |
364 SVGFilterPrimitiveStandardAttributes* primitve = static_cast<SVGFilterPrimit
iveStandardAttributes*>(object->node()); | 348 SVGFilterPrimitiveStandardAttributes* primitve = static_cast<SVGFilterPrimit
iveStandardAttributes*>(object->node()); |
365 | 349 |
366 for (; it != end; ++it) { | 350 for (; it != end; ++it) { |
367 FilterData* filterData = it->value; | 351 FilterData* filterData = it->value; |
368 if (!filterData->isBuilt) | 352 if (filterData->state != FilterData::Built) |
369 continue; | 353 continue; |
370 | 354 |
371 SVGFilterBuilder* builder = filterData->builder.get(); | 355 SVGFilterBuilder* builder = filterData->builder.get(); |
372 FilterEffect* effect = builder->effectByRenderer(object); | 356 FilterEffect* effect = builder->effectByRenderer(object); |
373 if (!effect) | 357 if (!effect) |
374 continue; | 358 continue; |
375 // Since all effects shares the same attribute value, all | 359 // Since all effects shares the same attribute value, all |
376 // or none of them will be changed. | 360 // or none of them will be changed. |
377 if (!primitve->setFilterEffectAttribute(effect, attribute)) | 361 if (!primitve->setFilterEffectAttribute(effect, attribute)) |
378 return; | 362 return; |
379 builder->clearResultsRecursive(effect); | 363 builder->clearResultsRecursive(effect); |
380 | 364 |
381 // Repaint the image on the screen. | 365 // Repaint the image on the screen. |
382 markClientForInvalidation(it->key, RepaintInvalidation); | 366 markClientForInvalidation(it->key, RepaintInvalidation); |
383 } | 367 } |
384 } | 368 } |
385 | 369 |
386 } | 370 } |
387 #endif | 371 #endif |
OLD | NEW |