|
Lines 39-44
WebCore/rendering/RenderSVGResourceFilter.cpp_sec1
|
| 39 |
#include "SVGFilter.h" |
39 |
#include "SVGFilter.h" |
| 40 |
#include "SVGFilterElement.h" |
40 |
#include "SVGFilterElement.h" |
| 41 |
#include "SVGFilterPrimitiveStandardAttributes.h" |
41 |
#include "SVGFilterPrimitiveStandardAttributes.h" |
|
|
42 |
#include "SVGImageBufferTools.h" |
| 42 |
#include "SVGStyledElement.h" |
43 |
#include "SVGStyledElement.h" |
| 43 |
#include "SVGUnitTypes.h" |
44 |
#include "SVGUnitTypes.h" |
| 44 |
#include <wtf/Vector.h> |
45 |
#include <wtf/Vector.h> |
|
Lines 150-219
bool RenderSVGResourceFilter::applyResou
WebCore/rendering/RenderSVGResourceFilter.cpp_sec2
|
| 150 |
} |
151 |
} |
| 151 |
|
152 |
|
| 152 |
OwnPtr<FilterData> filterData(new FilterData); |
153 |
OwnPtr<FilterData> filterData(new FilterData); |
|
|
154 |
FloatRect targetBoundingBox = object->objectBoundingBox(); |
| 155 |
|
| 156 |
SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node()); |
| 157 |
filterData->boundaries = filterElement->filterBoundingBox(targetBoundingBox); |
| 158 |
if (filterData->boundaries.isEmpty()) |
| 159 |
return false; |
| 160 |
|
| 161 |
// Determine absolute transformation matrix for filter. |
| 162 |
AffineTransform absoluteTransform; |
| 163 |
SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransform); |
| 164 |
if (!absoluteTransform.isInvertible()) |
| 165 |
return false; |
| 166 |
|
| 167 |
// Eliminate shear of the absolute transformation matrix to increase the quality of results in feTile. |
| 168 |
filterData->shearFreeAbsoluteTransform = AffineTransform(absoluteTransform.xScale(), 0, 0, absoluteTransform.yScale(), absoluteTransform.e(), absoluteTransform.f()); |
| 169 |
|
| 170 |
// Determine absolute boundaries of the filter and the drawing region. |
| 171 |
FloatRect absoluteFilterBoundaries = filterData->shearFreeAbsoluteTransform.mapRect(filterData->boundaries); |
| 172 |
FloatRect drawingRegion = object->strokeBoundingBox(); |
| 173 |
drawingRegion.intersect(filterData->boundaries); |
| 174 |
FloatRect absoluteDrawingRegion = filterData->shearFreeAbsoluteTransform.mapRect(drawingRegion); |
| 175 |
|
| 176 |
// Create the SVGFilter object. |
| 177 |
bool primitiveBoundingBoxMode = filterElement->primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX; |
| 178 |
filterData->filter = SVGFilter::create(filterData->shearFreeAbsoluteTransform, absoluteDrawingRegion, targetBoundingBox, filterData->boundaries, primitiveBoundingBoxMode); |
| 179 |
|
| 180 |
// Create all relevant filter primitives. |
| 153 |
filterData->builder = buildPrimitives(); |
181 |
filterData->builder = buildPrimitives(); |
| 154 |
if (!filterData->builder) |
182 |
if (!filterData->builder) |
| 155 |
return false; |
183 |
return false; |
| 156 |
|
184 |
|
| 157 |
FloatRect paintRect = object->strokeBoundingBox(); |
|
|
| 158 |
|
| 159 |
// Calculate the scale factor for the use of filterRes. |
185 |
// Calculate the scale factor for the use of filterRes. |
| 160 |
// Also see http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion |
186 |
// Also see http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion |
| 161 |
SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node()); |
187 |
FloatSize scale(1, 1); |
| 162 |
filterData->boundaries = filterElement->filterBoundingBox(object->objectBoundingBox()); |
|
|
| 163 |
if (filterData->boundaries.isEmpty()) |
| 164 |
return false; |
| 165 |
|
| 166 |
FloatSize scale(1.0f, 1.0f); |
| 167 |
if (filterElement->hasAttribute(SVGNames::filterResAttr)) { |
188 |
if (filterElement->hasAttribute(SVGNames::filterResAttr)) { |
| 168 |
scale.setWidth(filterElement->filterResX() / filterData->boundaries.width()); |
189 |
scale.setWidth(filterElement->filterResX() / absoluteFilterBoundaries.width()); |
| 169 |
scale.setHeight(filterElement->filterResY() / filterData->boundaries.height()); |
190 |
scale.setHeight(filterElement->filterResY() / absoluteFilterBoundaries.height()); |
| 170 |
} |
191 |
} |
| 171 |
|
192 |
|
| 172 |
if (scale.isEmpty()) |
193 |
if (scale.isEmpty()) |
| 173 |
return false; |
194 |
return false; |
| 174 |
|
195 |
|
| 175 |
// clip sourceImage to filterRegion |
196 |
// Determine scale factor for filter. The size of intermediate ImageBuffers shouldn't be bigger than kMaxFilterSize. |
| 176 |
FloatRect clippedSourceRect = paintRect; |
197 |
FloatRect tempSourceRect = absoluteDrawingRegion; |
| 177 |
clippedSourceRect.intersect(filterData->boundaries); |
|
|
| 178 |
|
| 179 |
// scale filter size to filterRes |
| 180 |
FloatRect tempSourceRect = clippedSourceRect; |
| 181 |
|
| 182 |
// scale to big sourceImage size to kMaxFilterSize |
| 183 |
tempSourceRect.scale(scale.width(), scale.height()); |
198 |
tempSourceRect.scale(scale.width(), scale.height()); |
| 184 |
fitsInMaximumImageSize(tempSourceRect.size(), scale); |
199 |
fitsInMaximumImageSize(tempSourceRect.size(), scale); |
| 185 |
|
200 |
|
| 186 |
// prepare Filters |
201 |
// Set the scale level in SVGFilter. |
| 187 |
bool primitiveBoundingBoxMode = filterElement->primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX; |
|
|
| 188 |
filterData->filter = SVGFilter::create(paintRect, filterData->boundaries, primitiveBoundingBoxMode); |
| 189 |
filterData->filter->setFilterResolution(scale); |
202 |
filterData->filter->setFilterResolution(scale); |
| 190 |
|
203 |
|
| 191 |
FilterEffect* lastEffect = filterData->builder->lastEffect(); |
204 |
FilterEffect* lastEffect = filterData->builder->lastEffect(); |
| 192 |
if (!lastEffect) |
205 |
if (!lastEffect) |
| 193 |
return false; |
206 |
return false; |
| 194 |
|
207 |
|
|
|
208 |
// Determine the filter primitive subregions of every effect. |
| 195 |
lastEffect->determineFilterPrimitiveSubregion(filterData->filter.get()); |
209 |
lastEffect->determineFilterPrimitiveSubregion(filterData->filter.get()); |
| 196 |
// At least one FilterEffect has a too big image size, |
|
|
| 197 |
// recalculate the effect sizes with new scale factors. |
| 198 |
if (!fitsInMaximumImageSize(filterData->filter->maxImageSize(), scale)) { |
210 |
if (!fitsInMaximumImageSize(filterData->filter->maxImageSize(), scale)) { |
|
|
211 |
// At least one FilterEffect has a too big image size, |
| 212 |
// recalculate the effect sizes with new scale factor. |
| 199 |
filterData->filter->setFilterResolution(scale); |
213 |
filterData->filter->setFilterResolution(scale); |
| 200 |
lastEffect->determineFilterPrimitiveSubregion(filterData->filter.get()); |
214 |
lastEffect->determineFilterPrimitiveSubregion(filterData->filter.get()); |
| 201 |
} |
215 |
} |
| 202 |
|
216 |
|
| 203 |
clippedSourceRect.scale(scale.width(), scale.height()); |
217 |
// If the drawingRegion is empty, we have something like <g filter=".."/>. |
| 204 |
|
218 |
// Even if the target objectBoundingBox() is empty, we still have to draw something. |
| 205 |
// Draw the content of the current element and it's childs to a imageBuffer to get the SourceGraphic. |
219 |
if (drawingRegion.isEmpty()) { |
| 206 |
// The size of the SourceGraphic is clipped to the size of the filterRegion. |
220 |
ASSERT(!m_filter.contains(object)); |
| 207 |
IntRect bufferRect = enclosingIntRect(clippedSourceRect); |
221 |
filterData->savedContext = context; |
| 208 |
OwnPtr<ImageBuffer> sourceGraphic(ImageBuffer::create(bufferRect.size(), LinearRGB)); |
222 |
m_filter.set(object, filterData.leakPtr()); |
| 209 |
|
|
|
| 210 |
if (!sourceGraphic.get()) |
| 211 |
return false; |
223 |
return false; |
|
|
224 |
} |
| 212 |
|
225 |
|
|
|
226 |
absoluteDrawingRegion.scale(scale.width(), scale.height()); |
| 227 |
|
| 228 |
OwnPtr<ImageBuffer> sourceGraphic; |
| 229 |
if (!SVGImageBufferTools::createImageBuffer(absoluteDrawingRegion, absoluteDrawingRegion, sourceGraphic, LinearRGB)) |
| 230 |
return false; |
| 231 |
|
| 213 |
GraphicsContext* sourceGraphicContext = sourceGraphic->context(); |
232 |
GraphicsContext* sourceGraphicContext = sourceGraphic->context(); |
| 214 |
sourceGraphicContext->translate(-clippedSourceRect.x(), -clippedSourceRect.y()); |
233 |
ASSERT(sourceGraphicContext); |
| 215 |
sourceGraphicContext->scale(scale); |
234 |
|
| 216 |
sourceGraphicContext->clearRect(FloatRect(FloatPoint(), paintRect.size())); |
235 |
sourceGraphicContext->translate(-absoluteDrawingRegion.x(), -absoluteDrawingRegion.y()); |
|
|
236 |
if (scale.width() != 1 || scale.height() != 1) |
| 237 |
sourceGraphicContext->scale(scale); |
| 238 |
|
| 239 |
sourceGraphicContext->concatCTM(filterData->shearFreeAbsoluteTransform); |
| 240 |
sourceGraphicContext->clearRect(FloatRect(FloatPoint(), absoluteDrawingRegion.size())); |
| 217 |
filterData->sourceGraphicBuffer = sourceGraphic.release(); |
241 |
filterData->sourceGraphicBuffer = sourceGraphic.release(); |
| 218 |
filterData->savedContext = context; |
242 |
filterData->savedContext = context; |
| 219 |
|
243 |
|
|
Lines 270-279
void RenderSVGResourceFilter::postApplyR
WebCore/rendering/RenderSVGResourceFilter.cpp_sec3
|
| 270 |
} |
294 |
} |
| 271 |
|
295 |
|
| 272 |
ImageBuffer* resultImage = lastEffect->resultImage(); |
296 |
ImageBuffer* resultImage = lastEffect->resultImage(); |
| 273 |
if (resultImage) |
297 |
if (resultImage) { |
| 274 |
context->drawImageBuffer(resultImage, object->style()->colorSpace(), lastEffect->filterPrimitiveSubregion()); |
298 |
context->concatCTM(filterData->shearFreeAbsoluteTransform.inverse()); |
| 275 |
} |
299 |
|
|
|
300 |
context->scale(FloatSize(1 / filterData->filter->filterResolution().width(), 1 / filterData->filter->filterResolution().height())); |
| 301 |
context->clip(lastEffect->maxEffectRect()); |
| 302 |
context->drawImageBuffer(resultImage, object->style()->colorSpace(), lastEffect->absolutePaintRect()); |
| 303 |
context->scale(filterData->filter->filterResolution()); |
| 276 |
|
304 |
|
|
|
305 |
context->concatCTM(filterData->shearFreeAbsoluteTransform); |
| 306 |
} |
| 307 |
} |
| 277 |
filterData->sourceGraphicBuffer.clear(); |
308 |
filterData->sourceGraphicBuffer.clear(); |
| 278 |
} |
309 |
} |
| 279 |
|
310 |
|