void TexturedLayerMLGPU::AssignBigImage(FrameBuilder* aBuilder, RenderViewMLGPU* aView, BigImageIterator* aIter, const Maybe<Polygon>& aGeometry) { const Matrix4x4& transform = GetLayer()->GetEffectiveTransformForBuffer(); // Note that we don't need to assign these in any particular order, since // they do not overlap. do { IntRect tileRect = aIter->GetTileRect(); IntRect rect = tileRect.Intersect(mPictureRect); if (rect.IsEmpty()) { continue; } { Rect screenRect = transform.TransformBounds(Rect(rect)); screenRect.MoveBy(-aView->GetTargetOffset()); screenRect = screenRect.Intersect(Rect(mComputedClipRect.ToUnknownRect())); if (screenRect.IsEmpty()) { // This tile is not in the clip region, so skip it. continue; } } RefPtr<TextureSource> tile = mBigImageTexture->ExtractCurrentTile(); if (!tile) { continue; } // Create a temporary item. RefPtr<TempImageLayerMLGPU> item = new TempImageLayerMLGPU(aBuilder->GetManager()); item->Init(this, tile, rect); Maybe<Polygon> geometry = aGeometry; item->AddBoundsToView(aBuilder, aView, std::move(geometry)); // Since the layer tree is not holding this alive, we have to ask the // FrameBuilder to do it for us. aBuilder->RetainTemporaryLayer(item); } while (aIter->NextTile()); }
IntRect nsSVGFilterInstance::ComputeFilterPrimitiveSubregion(nsSVGFE* aFilterElement, const nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs, const nsTArray<int32_t>& aInputIndices) { nsSVGFE* fE = aFilterElement; IntRect defaultFilterSubregion(0,0,0,0); if (fE->SubregionIsUnionOfRegions()) { for (uint32_t i = 0; i < aInputIndices.Length(); ++i) { int32_t inputIndex = aInputIndices[i]; bool isStandardInput = inputIndex < 0 || inputIndex == mSourceGraphicIndex; IntRect inputSubregion = isStandardInput ? ToIntRect(mFilterSpaceBounds) : aPrimitiveDescrs[inputIndex].PrimitiveSubregion(); defaultFilterSubregion = defaultFilterSubregion.Union(inputSubregion); } } else { defaultFilterSubregion = ToIntRect(mFilterSpaceBounds); } gfxRect feArea = nsSVGUtils::GetRelativeRect(mPrimitiveUnits, &fE->mLengthAttributes[nsSVGFE::ATTR_X], mTargetBBox, mTargetFrame); Rect region = ToRect(UserSpaceToFilterSpace(feArea)); if (!fE->mLengthAttributes[nsSVGFE::ATTR_X].IsExplicitlySet()) region.x = defaultFilterSubregion.X(); if (!fE->mLengthAttributes[nsSVGFE::ATTR_Y].IsExplicitlySet()) region.y = defaultFilterSubregion.Y(); if (!fE->mLengthAttributes[nsSVGFE::ATTR_WIDTH].IsExplicitlySet()) region.width = defaultFilterSubregion.Width(); if (!fE->mLengthAttributes[nsSVGFE::ATTR_HEIGHT].IsExplicitlySet()) region.height = defaultFilterSubregion.Height(); // We currently require filter primitive subregions to be pixel-aligned. // Following the spec, any pixel partially in the region is included // in the region. region.RoundOut(); IntRect regionInt = RoundedToInt(region); // Clip the primitive subregion to this filter's filter region. return regionInt.Intersect(ToIntRect(mFilterSpaceBounds)); }
bool RectIsSolidColor(SourceSurface* aSurface, const IntRect& aRect, BGRAColor aColor, uint8_t aFuzz /* = 0 */) { IntSize surfaceSize = aSurface->GetSize(); IntRect rect = aRect.Intersect(IntRect(0, 0, surfaceSize.width, surfaceSize.height)); RefPtr<DataSourceSurface> dataSurface = aSurface->GetDataSurface(); ASSERT_TRUE_OR_RETURN(dataSurface != nullptr, false); ASSERT_EQ_OR_RETURN(dataSurface->Stride(), surfaceSize.width * 4, false); DataSourceSurface::ScopedMap mapping(dataSurface, DataSourceSurface::MapType::READ); ASSERT_TRUE_OR_RETURN(mapping.IsMapped(), false); uint8_t* data = dataSurface->GetData(); ASSERT_TRUE_OR_RETURN(data != nullptr, false); int32_t rowLength = dataSurface->Stride(); for (int32_t row = rect.y; row < rect.YMost(); ++row) { for (int32_t col = rect.x; col < rect.XMost(); ++col) { int32_t i = row * rowLength + col * 4; if (aFuzz != 0) { ASSERT_LE_OR_RETURN(abs(aColor.mBlue - data[i + 0]), aFuzz, false); ASSERT_LE_OR_RETURN(abs(aColor.mGreen - data[i + 1]), aFuzz, false); ASSERT_LE_OR_RETURN(abs(aColor.mRed - data[i + 2]), aFuzz, false); ASSERT_LE_OR_RETURN(abs(aColor.mAlpha - data[i + 3]), aFuzz, false); } else { ASSERT_EQ_OR_RETURN(aColor.mBlue, data[i + 0], false); ASSERT_EQ_OR_RETURN(aColor.mGreen, data[i + 1], false); ASSERT_EQ_OR_RETURN(aColor.mRed, data[i + 2], false); ASSERT_EQ_OR_RETURN(aColor.mAlpha, data[i + 3], false); } } } return true; }
//****************************************************************************** void FrameAnimator::ClearFrame(uint8_t* aFrameData, const IntRect& aFrameRect, const IntRect& aRectToClear) { if (!aFrameData || aFrameRect.width <= 0 || aFrameRect.height <= 0 || aRectToClear.width <= 0 || aRectToClear.height <= 0) { return; } IntRect toClear = aFrameRect.Intersect(aRectToClear); if (toClear.IsEmpty()) { return; } uint32_t bytesPerRow = aFrameRect.width * 4; for (int row = toClear.y; row < toClear.y + toClear.height; ++row) { memset(aFrameData + toClear.x * 4 + row * bytesPerRow, 0, toClear.width * 4); } }
bool PalettedRectIsSolidColor(Decoder* aDecoder, const IntRect& aRect, uint8_t aColor) { RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); uint8_t* imageData; uint32_t imageLength; currentFrame->GetImageData(&imageData, &imageLength); ASSERT_TRUE_OR_RETURN(imageData, false); // Clamp to the frame rect. If any pixels outside the frame rect are included, // we immediately fail, because such pixels don't have any "color" in the // sense this function measures - they're transparent, and that doesn't // necessarily correspond to any color palette index at all. IntRect frameRect = currentFrame->GetRect(); ASSERT_EQ_OR_RETURN(imageLength, uint32_t(frameRect.Area()), false); IntRect rect = aRect.Intersect(frameRect); ASSERT_EQ_OR_RETURN(rect.Area(), aRect.Area(), false); // Translate |rect| by |frameRect.TopLeft()| to reflect the fact that the // frame rect's offset doesn't actually mean anything in terms of the // in-memory representation of the surface. The image data starts at the upper // left corner of the frame rect, in other words. rect -= frameRect.TopLeft(); // Walk through the image data and make sure that the entire rect has the // palette index |aColor|. int32_t rowLength = frameRect.width; for (int32_t row = rect.y; row < rect.YMost(); ++row) { for (int32_t col = rect.x; col < rect.XMost(); ++col) { int32_t i = row * rowLength + col; ASSERT_EQ_OR_RETURN(aColor, imageData[i], false); } } return true; }
nsresult nsSVGFilterInstance::BuildPrimitives(nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs, nsTArray<RefPtr<SourceSurface>>& aInputImages, bool aInputIsTainted) { mSourceGraphicIndex = GetLastResultIndex(aPrimitiveDescrs); // Clip previous filter's output to this filter's filter region. if (mSourceGraphicIndex >= 0) { FilterPrimitiveDescription& sourceDescr = aPrimitiveDescrs[mSourceGraphicIndex]; sourceDescr.SetPrimitiveSubregion(sourceDescr.PrimitiveSubregion().Intersect(mFilterSpaceBounds)); } // Get the filter primitive elements. nsTArray<RefPtr<nsSVGFE> > primitives; for (nsIContent* child = mFilterElement->nsINode::GetFirstChild(); child; child = child->GetNextSibling()) { RefPtr<nsSVGFE> primitive; CallQueryInterface(child, (nsSVGFE**)getter_AddRefs(primitive)); if (primitive) { primitives.AppendElement(primitive); } } // Maps source image name to source index. nsDataHashtable<nsStringHashKey, int32_t> imageTable(8); // The principal that we check principals of any loaded images against. nsCOMPtr<nsIPrincipal> principal = mTargetContent->NodePrincipal(); for (uint32_t primitiveElementIndex = 0; primitiveElementIndex < primitives.Length(); ++primitiveElementIndex) { nsSVGFE* filter = primitives[primitiveElementIndex]; AutoTArray<int32_t,2> sourceIndices; nsresult rv = GetSourceIndices(filter, aPrimitiveDescrs, imageTable, sourceIndices); if (NS_FAILED(rv)) { return rv; } IntRect primitiveSubregion = ComputeFilterPrimitiveSubregion(filter, aPrimitiveDescrs, sourceIndices); nsTArray<bool> sourcesAreTainted; GetInputsAreTainted(aPrimitiveDescrs, sourceIndices, aInputIsTainted, sourcesAreTainted); FilterPrimitiveDescription descr = filter->GetPrimitiveDescription(this, primitiveSubregion, sourcesAreTainted, aInputImages); descr.SetIsTainted(filter->OutputIsTainted(sourcesAreTainted, principal)); descr.SetFilterSpaceBounds(mFilterSpaceBounds); descr.SetPrimitiveSubregion(primitiveSubregion.Intersect(descr.FilterSpaceBounds())); for (uint32_t i = 0; i < sourceIndices.Length(); i++) { int32_t inputIndex = sourceIndices[i]; descr.SetInputPrimitive(i, inputIndex); ColorSpace inputColorSpace = inputIndex >= 0 ? aPrimitiveDescrs[inputIndex].OutputColorSpace() : ColorSpace(ColorSpace::SRGB); ColorSpace desiredInputColorSpace = filter->GetInputColorSpace(i, inputColorSpace); descr.SetInputColorSpace(i, desiredInputColorSpace); if (i == 0) { // the output color space is whatever in1 is if there is an in1 descr.SetOutputColorSpace(desiredInputColorSpace); } } if (sourceIndices.Length() == 0) { descr.SetOutputColorSpace(filter->GetOutputColorSpace()); } aPrimitiveDescrs.AppendElement(descr); uint32_t primitiveDescrIndex = aPrimitiveDescrs.Length() - 1; nsAutoString str; filter->GetResultImageName().GetAnimValue(str, filter); imageTable.Put(str, primitiveDescrIndex); } return NS_OK; }