Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(182)

Side by Side Diff: Source/core/rendering/svg/RenderSVGResourceFilter.cpp

Issue 500233002: First pass at ripping out non-deferred SVG filter path. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Nuke more code Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 void RenderSVGResourceFilter::removeAllClientsFromCache(bool markForInvalidation ) 62 void RenderSVGResourceFilter::removeAllClientsFromCache(bool markForInvalidation )
63 { 63 {
64 m_filter.clear(); 64 m_filter.clear();
65 markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInval idation : ParentOnlyInvalidation); 65 markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInval idation : ParentOnlyInvalidation);
66 } 66 }
67 67
68 void RenderSVGResourceFilter::removeClientFromCache(RenderObject* client, bool m arkForInvalidation) 68 void RenderSVGResourceFilter::removeClientFromCache(RenderObject* client, bool m arkForInvalidation)
69 { 69 {
70 ASSERT(client); 70 ASSERT(client);
71 71
72 if (FilterData* filterData = m_filter.get(client)) { 72 m_filter.remove(client);
73 if (filterData->savedContext)
74 filterData->state = FilterData::MarkedForRemoval;
75 else
76 m_filter.remove(client);
77 }
78 73
79 markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidati on : ParentOnlyInvalidation); 74 markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidati on : ParentOnlyInvalidation);
80 } 75 }
81 76
82 PassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFilter* filter) 77 PassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFilter* filter)
83 { 78 {
84 SVGFilterElement* filterElement = toSVGFilterElement(element()); 79 SVGFilterElement* filterElement = toSVGFilterElement(element());
85 FloatRect targetBoundingBox = filter->targetBoundingBox(); 80 FloatRect targetBoundingBox = filter->targetBoundingBox();
86 81
87 // Add effects to the builder 82 // Add effects to the builder
(...skipping 11 matching lines...) Expand all
99 builder->appendEffectToEffectReferences(effect, effectElement->renderer( )); 94 builder->appendEffectToEffectReferences(effect, effectElement->renderer( ));
100 effectElement->setStandardAttributes(effect.get()); 95 effectElement->setStandardAttributes(effect.get());
101 effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilter PrimitiveStandardAttributes>(effectElement, filterElement->primitiveUnits()->cur rentValue()->enumValue(), targetBoundingBox)); 96 effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilter PrimitiveStandardAttributes>(effectElement, filterElement->primitiveUnits()->cur rentValue()->enumValue(), targetBoundingBox));
102 effect->setOperatingColorSpace( 97 effect->setOperatingColorSpace(
103 effectElement->renderer()->style()->svgStyle().colorInterpolationFil ters() == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB); 98 effectElement->renderer()->style()->svgStyle().colorInterpolationFil ters() == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB);
104 builder->add(AtomicString(effectElement->result()->currentValue()->value ()), effect); 99 builder->add(AtomicString(effectElement->result()->currentValue()->value ()), effect);
105 } 100 }
106 return builder.release(); 101 return builder.release();
107 } 102 }
108 103
109 void RenderSVGResourceFilter::adjustScaleForMaximumImageSize(const FloatSize& si ze, FloatSize& filterScale)
110 {
111 FloatSize scaledSize(size);
112 scaledSize.scale(filterScale.width(), filterScale.height());
113 float scaledArea = scaledSize.width() * scaledSize.height();
114
115 if (scaledArea <= FilterEffect::maxFilterArea())
116 return;
117
118 // If area of scaled size is bigger than the upper limit, adjust the scale
119 // to fit.
120 filterScale.scale(sqrt(FilterEffect::maxFilterArea() / scaledArea));
121 }
122
123 static bool createImageBuffer(const Filter* filter, OwnPtr<ImageBuffer>& imageBu ffer)
124 {
125 IntRect paintRect = filter->sourceImageRect();
126 // Don't create empty ImageBuffers.
127 if (paintRect.isEmpty())
128 return false;
129
130 OwnPtr<ImageBufferSurface> surface = adoptPtr(new UnacceleratedImageBufferSu rface(paintRect.size()));
131 if (!surface->isValid())
132 return false;
133 OwnPtr<ImageBuffer> image = ImageBuffer::create(surface.release());
134 if (!image)
135 return false;
136
137 GraphicsContext* imageContext = image->context();
138 ASSERT(imageContext);
139
140 imageContext->translate(-paintRect.x(), -paintRect.y());
141 imageContext->concatCTM(filter->absoluteTransform());
142 imageBuffer = image.release();
143 return true;
144 }
145
146 static void beginDeferredFilter(GraphicsContext* context, FilterData* filterData ) 104 static void beginDeferredFilter(GraphicsContext* context, FilterData* filterData )
147 { 105 {
148 context->beginRecording(filterData->boundaries); 106 context->beginRecording(filterData->boundaries);
149 // We pass the boundaries to SkPictureImageFilter so it knows the 107 // We pass the boundaries to SkPictureImageFilter so it knows the
150 // world-space position of the filter primitives. It gets them 108 // world-space position of the filter primitives. It gets them
151 // from the DisplayList, which also applies the inverse translate 109 // from the DisplayList, which also applies the inverse translate
152 // to the origin. So we apply the forward translate here to avoid 110 // to the origin. So we apply the forward translate here to avoid
153 // it being applied twice. 111 // it being applied twice.
154 // FIXME: we should fix SkPicture to handle this offset itself, or 112 // FIXME: we should fix SkPicture to handle this offset itself, or
155 // make the translate optional on SkPictureImageFilter. 113 // make the translate optional on SkPictureImageFilter.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 } 184 }
227 185
228 bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode) 186 bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode)
229 { 187 {
230 ASSERT(object); 188 ASSERT(object);
231 ASSERT(context); 189 ASSERT(context);
232 ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode); 190 ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode);
233 191
234 clearInvalidationMask(); 192 clearInvalidationMask();
235 193
236 bool deferredFiltersEnabled = object->document().settings()->deferredFilters Enabled();
237 if (m_filter.contains(object)) { 194 if (m_filter.contains(object)) {
238 FilterData* filterData = m_filter.get(object); 195 FilterData* filterData = m_filter.get(object);
239 if (filterData->state == FilterData::PaintingSource || filterData->state == FilterData::Applying) 196 if (filterData->state == FilterData::PaintingSource || filterData->state == FilterData::Applying)
240 filterData->state = FilterData::CycleDetected; 197 filterData->state = FilterData::CycleDetected;
241 return false; // Already built, or we're in a cycle, or we're marked for removal. Regardless, just do nothing more now. 198 return false; // Already built, or we're in a cycle, or we're marked for removal. Regardless, just do nothing more now.
242 } 199 }
243 200
244 OwnPtr<FilterData> filterData(adoptPtr(new FilterData)); 201 OwnPtr<FilterData> filterData(adoptPtr(new FilterData));
245 FloatRect targetBoundingBox = object->objectBoundingBox(); 202 FloatRect targetBoundingBox = object->objectBoundingBox();
246 203
247 SVGFilterElement* filterElement = toSVGFilterElement(element()); 204 SVGFilterElement* filterElement = toSVGFilterElement(element());
248 filterData->boundaries = SVGLengthContext::resolveRectangle<SVGFilterElement >(filterElement, filterElement->filterUnits()->currentValue()->enumValue(), targ etBoundingBox); 205 filterData->boundaries = SVGLengthContext::resolveRectangle<SVGFilterElement >(filterElement, filterElement->filterUnits()->currentValue()->enumValue(), targ etBoundingBox);
249 if (filterData->boundaries.isEmpty()) 206 if (filterData->boundaries.isEmpty())
250 return false; 207 return false;
251 208
252 // Determine absolute transformation matrix for filter.
253 AffineTransform absoluteTransform;
254 SVGRenderingContext::calculateDeviceSpaceTransformation(object, absoluteTran sform);
255 if (!absoluteTransform.isInvertible())
256 return false;
257
258 // Filters cannot handle a full transformation, only scales in each directio n.
259 FloatSize filterScale;
260
261 // Calculate the scale factor for the filter.
262 // Also see http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion
263 if (filterElement->hasAttribute(SVGNames::filterResAttr)) {
264 // If resolution is specified, scale to match it.
265 filterScale = FloatSize(
266 filterElement->filterResX()->currentValue()->value() / filterData->b oundaries.width(),
267 filterElement->filterResY()->currentValue()->value() / filterData->b oundaries.height());
268 } else {
269 // Otherwise, use the scale of the absolute transform.
270 filterScale = FloatSize(absoluteTransform.xScale(), absoluteTransform.yS cale());
271 }
272 // The size of the scaled filter boundaries shouldn't be bigger than kMaxFil terSize.
273 // Intermediate filters are limited by the filter boundaries so they can't b e bigger than this.
274 adjustScaleForMaximumImageSize(filterData->boundaries.size(), filterScale);
275
276 filterData->drawingRegion = object->strokeBoundingBox(); 209 filterData->drawingRegion = object->strokeBoundingBox();
277 filterData->drawingRegion.intersect(filterData->boundaries); 210 filterData->drawingRegion.intersect(filterData->boundaries);
278 FloatRect absoluteDrawingRegion = filterData->drawingRegion; 211 IntRect intDrawingRegion = enclosingIntRect(filterData->drawingRegion);
279 if (!deferredFiltersEnabled)
280 absoluteDrawingRegion.scale(filterScale.width(), filterScale.height());
281
282 IntRect intDrawingRegion = enclosingIntRect(absoluteDrawingRegion);
283 212
284 // Create the SVGFilter object. 213 // Create the SVGFilter object.
285 bool primitiveBoundingBoxMode = filterElement->primitiveUnits()->currentValu e()->enumValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX; 214 bool primitiveBoundingBoxMode = filterElement->primitiveUnits()->currentValu e()->enumValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
286 filterData->shearFreeAbsoluteTransform = AffineTransform(); 215 filterData->filter = SVGFilter::create(intDrawingRegion, targetBoundingBox, filterData->boundaries, primitiveBoundingBoxMode);
287 if (!deferredFiltersEnabled)
288 filterData->shearFreeAbsoluteTransform.scale(filterScale.width(), filter Scale.height());
289 filterData->filter = SVGFilter::create(filterData->shearFreeAbsoluteTransfor m, intDrawingRegion, targetBoundingBox, filterData->boundaries, primitiveBoundin gBoxMode);
290 216
291 // Create all relevant filter primitives. 217 // Create all relevant filter primitives.
292 filterData->builder = buildPrimitives(filterData->filter.get()); 218 filterData->builder = buildPrimitives(filterData->filter.get());
293 if (!filterData->builder) 219 if (!filterData->builder)
294 return false; 220 return false;
295 221
296 FilterEffect* lastEffect = filterData->builder->lastEffect(); 222 FilterEffect* lastEffect = filterData->builder->lastEffect();
297 if (!lastEffect) 223 if (!lastEffect)
298 return false; 224 return false;
299 225
300 lastEffect->determineFilterPrimitiveSubregion(ClipToFilterRegion); 226 lastEffect->determineFilterPrimitiveSubregion(ClipToFilterRegion);
301 227
302 if (deferredFiltersEnabled) { 228 FilterData* data = filterData.get();
303 FilterData* data = filterData.get();
304 m_filter.set(object, filterData.release());
305 beginDeferredFilter(context, data);
306 return true;
307 }
308
309 // If the drawingRegion is empty, we have something like <g filter=".."/>.
310 // Even if the target objectBoundingBox() is empty, we still have to draw th e last effect result image in postApplyResource.
311 if (filterData->drawingRegion.isEmpty()) {
312 ASSERT(!m_filter.contains(object));
313 filterData->savedContext = context;
314 m_filter.set(object, filterData.release());
315 return false;
316 }
317
318 OwnPtr<ImageBuffer> sourceGraphic;
319 if (!createImageBuffer(filterData->filter.get(), sourceGraphic)) {
320 ASSERT(!m_filter.contains(object));
321 filterData->savedContext = context;
322 m_filter.set(object, filterData.release());
323 return false;
324 }
325
326 GraphicsContext* sourceGraphicContext = sourceGraphic->context();
327 ASSERT(sourceGraphicContext);
328
329 filterData->sourceGraphicBuffer = sourceGraphic.release();
330 filterData->savedContext = context;
331
332 context = sourceGraphicContext;
333
334 ASSERT(!m_filter.contains(object));
335 m_filter.set(object, filterData.release()); 229 m_filter.set(object, filterData.release());
336 230 beginDeferredFilter(context, data);
337 return true; 231 return true;
338 } 232 }
339 233
340 void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo ntext*& context) 234 void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo ntext*& context)
341 { 235 {
342 ASSERT(object); 236 ASSERT(object);
343 ASSERT(context); 237 ASSERT(context);
344 238
345 FilterData* filterData = m_filter.get(object); 239 FilterData* filterData = m_filter.get(object);
346 if (!filterData) 240 if (!filterData)
347 return; 241 return;
348 242
349 bool deferredFiltersEnabled = object->document().settings()->deferredFilters Enabled();
350
351 switch (filterData->state) { 243 switch (filterData->state) {
352 case FilterData::MarkedForRemoval:
353 m_filter.remove(object);
354 return;
355
356 case FilterData::CycleDetected: 244 case FilterData::CycleDetected:
357 case FilterData::Applying: 245 case FilterData::Applying:
358 // We have a cycle if we are already applying the data. 246 // We have a cycle if we are already applying the data.
359 // This can occur due to FeImage referencing a source that makes use of the FEImage itself. 247 // This can occur due to FeImage referencing a source that makes use of the FEImage itself.
360 // This is the first place we've hit the cycle, so set the state back to PaintingSource so the return stack 248 // This is the first place we've hit the cycle, so set the state back to PaintingSource so the return stack
361 // will continue correctly. 249 // will continue correctly.
362 filterData->state = FilterData::PaintingSource; 250 filterData->state = FilterData::PaintingSource;
363 return; 251 return;
364 252
365 case FilterData::PaintingSource: 253 case FilterData::PaintingSource:
366 if (deferredFiltersEnabled) { 254 endDeferredFilter(context, filterData);
367 endDeferredFilter(context, filterData);
368 } else {
369 if (!filterData->savedContext) {
370 removeClientFromCache(object);
371 return;
372 }
373
374 context = filterData->savedContext;
375 filterData->savedContext = 0;
376 }
377 break; 255 break;
378 256
379 case FilterData::Built: { } // Empty 257 case FilterData::Built: { } // Empty
380 } 258 }
381 259
382 if (deferredFiltersEnabled) { 260 drawDeferredFilter(context, filterData, toSVGFilterElement(element()));
383 drawDeferredFilter(context, filterData, toSVGFilterElement(element())); 261 filterData->state = FilterData::Built;
384 filterData->state = FilterData::Built;
385 return;
386 }
387
388 FilterEffect* lastEffect = filterData->builder->lastEffect();
389
390 if (lastEffect && !filterData->boundaries.isEmpty() && !lastEffect->filterPr imitiveSubregion().isEmpty()) {
391 // This is the real filtering of the object. It just needs to be called on the
392 // initial filtering process. We just take the stored filter result on a
393 // second drawing.
394 if (filterData->state != FilterData::Built)
395 filterData->filter->setSourceImage(filterData->sourceGraphicBuffer.r elease());
396
397 // Always true if filterData is just built (filterData->state == FilterD ata::Built).
398 if (!lastEffect->hasResult()) {
399 filterData->state = FilterData::Applying;
400 lastEffect->apply();
401 lastEffect->correctFilterResultIfNeeded();
402 lastEffect->transformResultColorSpace(ColorSpaceDeviceRGB);
403 }
404 filterData->state = FilterData::Built;
405
406 ImageBuffer* resultImage = lastEffect->asImageBuffer();
407 if (resultImage) {
408 context->drawImageBuffer(resultImage, filterData->filter->mapAbsolut eRectToLocalRect(lastEffect->absolutePaintRect()));
409 }
410 }
411 filterData->sourceGraphicBuffer.clear();
412 } 262 }
413 263
414 FloatRect RenderSVGResourceFilter::resourceBoundingBox(const RenderObject* objec t) 264 FloatRect RenderSVGResourceFilter::resourceBoundingBox(const RenderObject* objec t)
415 { 265 {
416 if (SVGFilterElement* element = toSVGFilterElement(this->element())) 266 if (SVGFilterElement* element = toSVGFilterElement(this->element()))
417 return SVGLengthContext::resolveRectangle<SVGFilterElement>(element, ele ment->filterUnits()->currentValue()->enumValue(), object->objectBoundingBox()); 267 return SVGLengthContext::resolveRectangle<SVGFilterElement>(element, ele ment->filterUnits()->currentValue()->enumValue(), object->objectBoundingBox());
418 268
419 return FloatRect(); 269 return FloatRect();
420 } 270 }
421 271
(...skipping 24 matching lines...) Expand all
446 markAllClientLayersForInvalidation(); 296 markAllClientLayersForInvalidation();
447 } 297 }
448 298
449 FloatRect RenderSVGResourceFilter::drawingRegion(RenderObject* object) const 299 FloatRect RenderSVGResourceFilter::drawingRegion(RenderObject* object) const
450 { 300 {
451 FilterData* filterData = m_filter.get(object); 301 FilterData* filterData = m_filter.get(object);
452 return filterData ? filterData->drawingRegion : FloatRect(); 302 return filterData ? filterData->drawingRegion : FloatRect();
453 } 303 }
454 304
455 } 305 }
OLDNEW
« no previous file with comments | « Source/core/rendering/svg/RenderSVGResourceFilter.h ('k') | Source/core/rendering/svg/SVGRenderTreeAsText.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698