Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | // Main header first: |
michael@0 | 7 | #include "nsSVGFilterInstance.h" |
michael@0 | 8 | |
michael@0 | 9 | // Keep others in (case-insensitive) order: |
michael@0 | 10 | #include "gfxPlatform.h" |
michael@0 | 11 | #include "gfxUtils.h" |
michael@0 | 12 | #include "nsISVGChildFrame.h" |
michael@0 | 13 | #include "nsRenderingContext.h" |
michael@0 | 14 | #include "mozilla/dom/SVGFilterElement.h" |
michael@0 | 15 | #include "nsReferencedElement.h" |
michael@0 | 16 | #include "nsSVGFilterFrame.h" |
michael@0 | 17 | #include "nsSVGFilterPaintCallback.h" |
michael@0 | 18 | #include "nsSVGUtils.h" |
michael@0 | 19 | #include "SVGContentUtils.h" |
michael@0 | 20 | #include "FilterSupport.h" |
michael@0 | 21 | #include "gfx2DGlue.h" |
michael@0 | 22 | |
michael@0 | 23 | using namespace mozilla; |
michael@0 | 24 | using namespace mozilla::dom; |
michael@0 | 25 | using namespace mozilla::gfx; |
michael@0 | 26 | |
michael@0 | 27 | nsSVGFilterInstance::nsSVGFilterInstance(const nsStyleFilter& aFilter, |
michael@0 | 28 | nsIFrame *aTargetFrame, |
michael@0 | 29 | const gfxRect& aTargetBBox, |
michael@0 | 30 | const gfxSize& aUserSpaceToFilterSpaceScale, |
michael@0 | 31 | const gfxSize& aFilterSpaceToUserSpaceScale) : |
michael@0 | 32 | mFilter(aFilter), |
michael@0 | 33 | mTargetFrame(aTargetFrame), |
michael@0 | 34 | mTargetBBox(aTargetBBox), |
michael@0 | 35 | mUserSpaceToFilterSpaceScale(aUserSpaceToFilterSpaceScale), |
michael@0 | 36 | mFilterSpaceToUserSpaceScale(aFilterSpaceToUserSpaceScale), |
michael@0 | 37 | mInitialized(false) { |
michael@0 | 38 | |
michael@0 | 39 | // Get the filter frame. |
michael@0 | 40 | mFilterFrame = GetFilterFrame(); |
michael@0 | 41 | if (!mFilterFrame) { |
michael@0 | 42 | return; |
michael@0 | 43 | } |
michael@0 | 44 | |
michael@0 | 45 | // Get the filter element. |
michael@0 | 46 | mFilterElement = mFilterFrame->GetFilterContent(); |
michael@0 | 47 | if (!mFilterElement) { |
michael@0 | 48 | NS_NOTREACHED("filter frame should have a related element"); |
michael@0 | 49 | return; |
michael@0 | 50 | } |
michael@0 | 51 | |
michael@0 | 52 | mPrimitiveUnits = |
michael@0 | 53 | mFilterFrame->GetEnumValue(SVGFilterElement::PRIMITIVEUNITS); |
michael@0 | 54 | |
michael@0 | 55 | nsresult rv = ComputeBounds(); |
michael@0 | 56 | if (NS_FAILED(rv)) { |
michael@0 | 57 | return; |
michael@0 | 58 | } |
michael@0 | 59 | |
michael@0 | 60 | mInitialized = true; |
michael@0 | 61 | } |
michael@0 | 62 | |
michael@0 | 63 | nsresult |
michael@0 | 64 | nsSVGFilterInstance::ComputeBounds() |
michael@0 | 65 | { |
michael@0 | 66 | // XXX if filterUnits is set (or has defaulted) to objectBoundingBox, we |
michael@0 | 67 | // should send a warning to the error console if the author has used lengths |
michael@0 | 68 | // with units. This is a common mistake and can result in the filter region |
michael@0 | 69 | // being *massive* below (because we ignore the units and interpret the number |
michael@0 | 70 | // as a factor of the bbox width/height). We should also send a warning if the |
michael@0 | 71 | // user uses a number without units (a future SVG spec should really |
michael@0 | 72 | // deprecate that, since it's too confusing for a bare number to be sometimes |
michael@0 | 73 | // interpreted as a fraction of the bounding box and sometimes as user-space |
michael@0 | 74 | // units). So really only percentage values should be used in this case. |
michael@0 | 75 | |
michael@0 | 76 | // Set the user space bounds (i.e. the filter region in user space). |
michael@0 | 77 | nsSVGLength2 XYWH[4]; |
michael@0 | 78 | NS_ABORT_IF_FALSE(sizeof(mFilterElement->mLengthAttributes) == sizeof(XYWH), |
michael@0 | 79 | "XYWH size incorrect"); |
michael@0 | 80 | memcpy(XYWH, mFilterElement->mLengthAttributes, |
michael@0 | 81 | sizeof(mFilterElement->mLengthAttributes)); |
michael@0 | 82 | XYWH[0] = *mFilterFrame->GetLengthValue(SVGFilterElement::ATTR_X); |
michael@0 | 83 | XYWH[1] = *mFilterFrame->GetLengthValue(SVGFilterElement::ATTR_Y); |
michael@0 | 84 | XYWH[2] = *mFilterFrame->GetLengthValue(SVGFilterElement::ATTR_WIDTH); |
michael@0 | 85 | XYWH[3] = *mFilterFrame->GetLengthValue(SVGFilterElement::ATTR_HEIGHT); |
michael@0 | 86 | uint16_t filterUnits = |
michael@0 | 87 | mFilterFrame->GetEnumValue(SVGFilterElement::FILTERUNITS); |
michael@0 | 88 | mUserSpaceBounds = nsSVGUtils::GetRelativeRect(filterUnits, |
michael@0 | 89 | XYWH, mTargetBBox, mTargetFrame); |
michael@0 | 90 | |
michael@0 | 91 | // Temporarily transform the user space bounds to filter space, so we |
michael@0 | 92 | // can align them with the pixel boundries of the offscreen surface. |
michael@0 | 93 | // The offscreen surface has the same scale as filter space. |
michael@0 | 94 | mUserSpaceBounds = UserSpaceToFilterSpace(mUserSpaceBounds); |
michael@0 | 95 | mUserSpaceBounds.RoundOut(); |
michael@0 | 96 | if (mUserSpaceBounds.Width() <= 0 || mUserSpaceBounds.Height() <= 0) { |
michael@0 | 97 | // 0 disables rendering, < 0 is error. dispatch error console warning |
michael@0 | 98 | // or error as appropriate. |
michael@0 | 99 | return NS_ERROR_FAILURE; |
michael@0 | 100 | } |
michael@0 | 101 | |
michael@0 | 102 | // Set the filter space bounds. |
michael@0 | 103 | if (!gfxUtils::GfxRectToIntRect(mUserSpaceBounds, &mFilterSpaceBounds)) { |
michael@0 | 104 | // The filter region is way too big if there is float -> int overflow. |
michael@0 | 105 | return NS_ERROR_FAILURE; |
michael@0 | 106 | } |
michael@0 | 107 | |
michael@0 | 108 | // Undo the temporary transformation of the user space bounds. |
michael@0 | 109 | mUserSpaceBounds = FilterSpaceToUserSpace(mUserSpaceBounds); |
michael@0 | 110 | |
michael@0 | 111 | return NS_OK; |
michael@0 | 112 | } |
michael@0 | 113 | |
michael@0 | 114 | nsSVGFilterFrame* |
michael@0 | 115 | nsSVGFilterInstance::GetFilterFrame() |
michael@0 | 116 | { |
michael@0 | 117 | if (mFilter.GetType() != NS_STYLE_FILTER_URL) { |
michael@0 | 118 | // The filter is not an SVG reference filter. |
michael@0 | 119 | return nullptr; |
michael@0 | 120 | } |
michael@0 | 121 | |
michael@0 | 122 | nsIURI* url = mFilter.GetURL(); |
michael@0 | 123 | if (!url) { |
michael@0 | 124 | NS_NOTREACHED("an nsStyleFilter of type URL should have a non-null URL"); |
michael@0 | 125 | return nullptr; |
michael@0 | 126 | } |
michael@0 | 127 | |
michael@0 | 128 | // Get the target element to use as a point of reference for looking up the |
michael@0 | 129 | // filter element. |
michael@0 | 130 | nsIContent* targetElement = mTargetFrame->GetContent(); |
michael@0 | 131 | if (!targetElement) { |
michael@0 | 132 | // There is no element associated with the target frame. |
michael@0 | 133 | return nullptr; |
michael@0 | 134 | } |
michael@0 | 135 | |
michael@0 | 136 | // Look up the filter element by URL. |
michael@0 | 137 | nsReferencedElement filterElement; |
michael@0 | 138 | bool watch = false; |
michael@0 | 139 | filterElement.Reset(targetElement, url, watch); |
michael@0 | 140 | Element* element = filterElement.get(); |
michael@0 | 141 | if (!element) { |
michael@0 | 142 | // The URL points to no element. |
michael@0 | 143 | return nullptr; |
michael@0 | 144 | } |
michael@0 | 145 | |
michael@0 | 146 | // Get the frame of the filter element. |
michael@0 | 147 | nsIFrame* frame = element->GetPrimaryFrame(); |
michael@0 | 148 | if (frame->GetType() != nsGkAtoms::svgFilterFrame) { |
michael@0 | 149 | // The URL points to an element that's not an SVG filter element. |
michael@0 | 150 | return nullptr; |
michael@0 | 151 | } |
michael@0 | 152 | |
michael@0 | 153 | return static_cast<nsSVGFilterFrame*>(frame); |
michael@0 | 154 | } |
michael@0 | 155 | |
michael@0 | 156 | float |
michael@0 | 157 | nsSVGFilterInstance::GetPrimitiveNumber(uint8_t aCtxType, float aValue) const |
michael@0 | 158 | { |
michael@0 | 159 | nsSVGLength2 val; |
michael@0 | 160 | val.Init(aCtxType, 0xff, aValue, |
michael@0 | 161 | nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER); |
michael@0 | 162 | |
michael@0 | 163 | float value; |
michael@0 | 164 | if (mPrimitiveUnits == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { |
michael@0 | 165 | value = nsSVGUtils::ObjectSpace(mTargetBBox, &val); |
michael@0 | 166 | } else { |
michael@0 | 167 | value = nsSVGUtils::UserSpace(mTargetFrame, &val); |
michael@0 | 168 | } |
michael@0 | 169 | |
michael@0 | 170 | switch (aCtxType) { |
michael@0 | 171 | case SVGContentUtils::X: |
michael@0 | 172 | return value * mUserSpaceToFilterSpaceScale.width; |
michael@0 | 173 | case SVGContentUtils::Y: |
michael@0 | 174 | return value * mUserSpaceToFilterSpaceScale.height; |
michael@0 | 175 | case SVGContentUtils::XY: |
michael@0 | 176 | default: |
michael@0 | 177 | return value * SVGContentUtils::ComputeNormalizedHypotenuse( |
michael@0 | 178 | mUserSpaceToFilterSpaceScale.width, |
michael@0 | 179 | mUserSpaceToFilterSpaceScale.height); |
michael@0 | 180 | } |
michael@0 | 181 | } |
michael@0 | 182 | |
michael@0 | 183 | Point3D |
michael@0 | 184 | nsSVGFilterInstance::ConvertLocation(const Point3D& aPoint) const |
michael@0 | 185 | { |
michael@0 | 186 | nsSVGLength2 val[4]; |
michael@0 | 187 | val[0].Init(SVGContentUtils::X, 0xff, aPoint.x, |
michael@0 | 188 | nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER); |
michael@0 | 189 | val[1].Init(SVGContentUtils::Y, 0xff, aPoint.y, |
michael@0 | 190 | nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER); |
michael@0 | 191 | // Dummy width/height values |
michael@0 | 192 | val[2].Init(SVGContentUtils::X, 0xff, 0, |
michael@0 | 193 | nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER); |
michael@0 | 194 | val[3].Init(SVGContentUtils::Y, 0xff, 0, |
michael@0 | 195 | nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER); |
michael@0 | 196 | |
michael@0 | 197 | gfxRect feArea = nsSVGUtils::GetRelativeRect(mPrimitiveUnits, |
michael@0 | 198 | val, mTargetBBox, mTargetFrame); |
michael@0 | 199 | gfxRect r = UserSpaceToFilterSpace(feArea); |
michael@0 | 200 | return Point3D(r.x, r.y, GetPrimitiveNumber(SVGContentUtils::XY, aPoint.z)); |
michael@0 | 201 | } |
michael@0 | 202 | |
michael@0 | 203 | gfxRect |
michael@0 | 204 | nsSVGFilterInstance::UserSpaceToFilterSpace(const gfxRect& aUserSpaceRect) const |
michael@0 | 205 | { |
michael@0 | 206 | gfxRect filterSpaceRect = aUserSpaceRect; |
michael@0 | 207 | filterSpaceRect.Scale(mUserSpaceToFilterSpaceScale.width, |
michael@0 | 208 | mUserSpaceToFilterSpaceScale.height); |
michael@0 | 209 | return filterSpaceRect; |
michael@0 | 210 | } |
michael@0 | 211 | |
michael@0 | 212 | gfxRect |
michael@0 | 213 | nsSVGFilterInstance::FilterSpaceToUserSpace(const gfxRect& aFilterSpaceRect) const |
michael@0 | 214 | { |
michael@0 | 215 | gfxRect userSpaceRect = aFilterSpaceRect; |
michael@0 | 216 | userSpaceRect.Scale(mFilterSpaceToUserSpaceScale.width, |
michael@0 | 217 | mFilterSpaceToUserSpaceScale.height); |
michael@0 | 218 | return userSpaceRect; |
michael@0 | 219 | } |
michael@0 | 220 | |
michael@0 | 221 | IntRect |
michael@0 | 222 | nsSVGFilterInstance::ComputeFilterPrimitiveSubregion(nsSVGFE* aFilterElement, |
michael@0 | 223 | const nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs, |
michael@0 | 224 | const nsTArray<int32_t>& aInputIndices) |
michael@0 | 225 | { |
michael@0 | 226 | nsSVGFE* fE = aFilterElement; |
michael@0 | 227 | |
michael@0 | 228 | IntRect defaultFilterSubregion(0,0,0,0); |
michael@0 | 229 | if (fE->SubregionIsUnionOfRegions()) { |
michael@0 | 230 | for (uint32_t i = 0; i < aInputIndices.Length(); ++i) { |
michael@0 | 231 | int32_t inputIndex = aInputIndices[i]; |
michael@0 | 232 | IntRect inputSubregion = inputIndex >= 0 ? |
michael@0 | 233 | aPrimitiveDescrs[inputIndex].PrimitiveSubregion() : |
michael@0 | 234 | ToIntRect(mFilterSpaceBounds); |
michael@0 | 235 | |
michael@0 | 236 | defaultFilterSubregion = defaultFilterSubregion.Union(inputSubregion); |
michael@0 | 237 | } |
michael@0 | 238 | } else { |
michael@0 | 239 | defaultFilterSubregion = ToIntRect(mFilterSpaceBounds); |
michael@0 | 240 | } |
michael@0 | 241 | |
michael@0 | 242 | gfxRect feArea = nsSVGUtils::GetRelativeRect(mPrimitiveUnits, |
michael@0 | 243 | &fE->mLengthAttributes[nsSVGFE::ATTR_X], mTargetBBox, mTargetFrame); |
michael@0 | 244 | Rect region = ToRect(UserSpaceToFilterSpace(feArea)); |
michael@0 | 245 | |
michael@0 | 246 | if (!fE->mLengthAttributes[nsSVGFE::ATTR_X].IsExplicitlySet()) |
michael@0 | 247 | region.x = defaultFilterSubregion.X(); |
michael@0 | 248 | if (!fE->mLengthAttributes[nsSVGFE::ATTR_Y].IsExplicitlySet()) |
michael@0 | 249 | region.y = defaultFilterSubregion.Y(); |
michael@0 | 250 | if (!fE->mLengthAttributes[nsSVGFE::ATTR_WIDTH].IsExplicitlySet()) |
michael@0 | 251 | region.width = defaultFilterSubregion.Width(); |
michael@0 | 252 | if (!fE->mLengthAttributes[nsSVGFE::ATTR_HEIGHT].IsExplicitlySet()) |
michael@0 | 253 | region.height = defaultFilterSubregion.Height(); |
michael@0 | 254 | |
michael@0 | 255 | // We currently require filter primitive subregions to be pixel-aligned. |
michael@0 | 256 | // Following the spec, any pixel partially in the region is included |
michael@0 | 257 | // in the region. |
michael@0 | 258 | region.RoundOut(); |
michael@0 | 259 | |
michael@0 | 260 | return RoundedToInt(region); |
michael@0 | 261 | } |
michael@0 | 262 | |
michael@0 | 263 | void |
michael@0 | 264 | nsSVGFilterInstance::GetInputsAreTainted(const nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs, |
michael@0 | 265 | const nsTArray<int32_t>& aInputIndices, |
michael@0 | 266 | nsTArray<bool>& aOutInputsAreTainted) |
michael@0 | 267 | { |
michael@0 | 268 | for (uint32_t i = 0; i < aInputIndices.Length(); i++) { |
michael@0 | 269 | int32_t inputIndex = aInputIndices[i]; |
michael@0 | 270 | if (inputIndex < 0) { |
michael@0 | 271 | // SourceGraphic, SourceAlpha, FillPaint and StrokePaint are tainted. |
michael@0 | 272 | aOutInputsAreTainted.AppendElement(true); |
michael@0 | 273 | } else { |
michael@0 | 274 | aOutInputsAreTainted.AppendElement(aPrimitiveDescrs[inputIndex].IsTainted()); |
michael@0 | 275 | } |
michael@0 | 276 | } |
michael@0 | 277 | } |
michael@0 | 278 | |
michael@0 | 279 | static int32_t |
michael@0 | 280 | GetLastResultIndex(const nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs) |
michael@0 | 281 | { |
michael@0 | 282 | uint32_t numPrimitiveDescrs = aPrimitiveDescrs.Length(); |
michael@0 | 283 | return !numPrimitiveDescrs ? |
michael@0 | 284 | FilterPrimitiveDescription::kPrimitiveIndexSourceGraphic : |
michael@0 | 285 | numPrimitiveDescrs - 1; |
michael@0 | 286 | } |
michael@0 | 287 | |
michael@0 | 288 | nsresult |
michael@0 | 289 | nsSVGFilterInstance::GetSourceIndices(nsSVGFE* aPrimitiveElement, |
michael@0 | 290 | const nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs, |
michael@0 | 291 | const nsDataHashtable<nsStringHashKey, int32_t>& aImageTable, |
michael@0 | 292 | nsTArray<int32_t>& aSourceIndices) |
michael@0 | 293 | { |
michael@0 | 294 | nsAutoTArray<nsSVGStringInfo,2> sources; |
michael@0 | 295 | aPrimitiveElement->GetSourceImageNames(sources); |
michael@0 | 296 | |
michael@0 | 297 | for (uint32_t j = 0; j < sources.Length(); j++) { |
michael@0 | 298 | nsAutoString str; |
michael@0 | 299 | sources[j].mString->GetAnimValue(str, sources[j].mElement); |
michael@0 | 300 | |
michael@0 | 301 | int32_t sourceIndex = 0; |
michael@0 | 302 | if (str.EqualsLiteral("SourceGraphic")) { |
michael@0 | 303 | sourceIndex = mSourceGraphicIndex; |
michael@0 | 304 | } else if (str.EqualsLiteral("SourceAlpha")) { |
michael@0 | 305 | sourceIndex = FilterPrimitiveDescription::kPrimitiveIndexSourceAlpha; |
michael@0 | 306 | } else if (str.EqualsLiteral("FillPaint")) { |
michael@0 | 307 | sourceIndex = FilterPrimitiveDescription::kPrimitiveIndexFillPaint; |
michael@0 | 308 | } else if (str.EqualsLiteral("StrokePaint")) { |
michael@0 | 309 | sourceIndex = FilterPrimitiveDescription::kPrimitiveIndexStrokePaint; |
michael@0 | 310 | } else if (str.EqualsLiteral("BackgroundImage") || |
michael@0 | 311 | str.EqualsLiteral("BackgroundAlpha")) { |
michael@0 | 312 | return NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 313 | } else if (str.EqualsLiteral("")) { |
michael@0 | 314 | sourceIndex = GetLastResultIndex(aPrimitiveDescrs); |
michael@0 | 315 | } else { |
michael@0 | 316 | bool inputExists = aImageTable.Get(str, &sourceIndex); |
michael@0 | 317 | if (!inputExists) |
michael@0 | 318 | return NS_ERROR_FAILURE; |
michael@0 | 319 | } |
michael@0 | 320 | |
michael@0 | 321 | aSourceIndices.AppendElement(sourceIndex); |
michael@0 | 322 | } |
michael@0 | 323 | return NS_OK; |
michael@0 | 324 | } |
michael@0 | 325 | |
michael@0 | 326 | nsresult |
michael@0 | 327 | nsSVGFilterInstance::BuildPrimitives(nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs, |
michael@0 | 328 | nsTArray<mozilla::RefPtr<SourceSurface>>& aInputImages) |
michael@0 | 329 | { |
michael@0 | 330 | mSourceGraphicIndex = GetLastResultIndex(aPrimitiveDescrs); |
michael@0 | 331 | |
michael@0 | 332 | // Get the filter primitive elements. |
michael@0 | 333 | nsTArray<nsRefPtr<nsSVGFE> > primitives; |
michael@0 | 334 | for (nsIContent* child = mFilterElement->nsINode::GetFirstChild(); |
michael@0 | 335 | child; |
michael@0 | 336 | child = child->GetNextSibling()) { |
michael@0 | 337 | nsRefPtr<nsSVGFE> primitive; |
michael@0 | 338 | CallQueryInterface(child, (nsSVGFE**)getter_AddRefs(primitive)); |
michael@0 | 339 | if (primitive) { |
michael@0 | 340 | primitives.AppendElement(primitive); |
michael@0 | 341 | } |
michael@0 | 342 | } |
michael@0 | 343 | |
michael@0 | 344 | // Maps source image name to source index. |
michael@0 | 345 | nsDataHashtable<nsStringHashKey, int32_t> imageTable(10); |
michael@0 | 346 | |
michael@0 | 347 | // The principal that we check principals of any loaded images against. |
michael@0 | 348 | nsCOMPtr<nsIPrincipal> principal = mTargetFrame->GetContent()->NodePrincipal(); |
michael@0 | 349 | |
michael@0 | 350 | for (uint32_t primitiveElementIndex = 0; |
michael@0 | 351 | primitiveElementIndex < primitives.Length(); |
michael@0 | 352 | ++primitiveElementIndex) { |
michael@0 | 353 | nsSVGFE* filter = primitives[primitiveElementIndex]; |
michael@0 | 354 | |
michael@0 | 355 | nsAutoTArray<int32_t,2> sourceIndices; |
michael@0 | 356 | nsresult rv = GetSourceIndices(filter, aPrimitiveDescrs, imageTable, sourceIndices); |
michael@0 | 357 | if (NS_FAILED(rv)) { |
michael@0 | 358 | return rv; |
michael@0 | 359 | } |
michael@0 | 360 | |
michael@0 | 361 | IntRect primitiveSubregion = |
michael@0 | 362 | ComputeFilterPrimitiveSubregion(filter, aPrimitiveDescrs, sourceIndices); |
michael@0 | 363 | |
michael@0 | 364 | nsTArray<bool> sourcesAreTainted; |
michael@0 | 365 | GetInputsAreTainted(aPrimitiveDescrs, sourceIndices, sourcesAreTainted); |
michael@0 | 366 | |
michael@0 | 367 | FilterPrimitiveDescription descr = |
michael@0 | 368 | filter->GetPrimitiveDescription(this, primitiveSubregion, sourcesAreTainted, aInputImages); |
michael@0 | 369 | |
michael@0 | 370 | descr.SetIsTainted(filter->OutputIsTainted(sourcesAreTainted, principal)); |
michael@0 | 371 | descr.SetPrimitiveSubregion(primitiveSubregion); |
michael@0 | 372 | |
michael@0 | 373 | for (uint32_t i = 0; i < sourceIndices.Length(); i++) { |
michael@0 | 374 | int32_t inputIndex = sourceIndices[i]; |
michael@0 | 375 | descr.SetInputPrimitive(i, inputIndex); |
michael@0 | 376 | |
michael@0 | 377 | ColorSpace inputColorSpace = inputIndex >= 0 |
michael@0 | 378 | ? aPrimitiveDescrs[inputIndex].OutputColorSpace() |
michael@0 | 379 | : ColorSpace(ColorSpace::SRGB); |
michael@0 | 380 | |
michael@0 | 381 | ColorSpace desiredInputColorSpace = filter->GetInputColorSpace(i, inputColorSpace); |
michael@0 | 382 | descr.SetInputColorSpace(i, desiredInputColorSpace); |
michael@0 | 383 | if (i == 0) { |
michael@0 | 384 | // the output color space is whatever in1 is if there is an in1 |
michael@0 | 385 | descr.SetOutputColorSpace(desiredInputColorSpace); |
michael@0 | 386 | } |
michael@0 | 387 | } |
michael@0 | 388 | |
michael@0 | 389 | if (sourceIndices.Length() == 0) { |
michael@0 | 390 | descr.SetOutputColorSpace(filter->GetOutputColorSpace()); |
michael@0 | 391 | } |
michael@0 | 392 | |
michael@0 | 393 | aPrimitiveDescrs.AppendElement(descr); |
michael@0 | 394 | uint32_t primitiveDescrIndex = aPrimitiveDescrs.Length() - 1; |
michael@0 | 395 | |
michael@0 | 396 | nsAutoString str; |
michael@0 | 397 | filter->GetResultImageName().GetAnimValue(str, filter); |
michael@0 | 398 | imageTable.Put(str, primitiveDescrIndex); |
michael@0 | 399 | } |
michael@0 | 400 | |
michael@0 | 401 | return NS_OK; |
michael@0 | 402 | } |