void ContainerLayer::DefaultComputeEffectiveTransforms(const Matrix4x4& aTransformToSurface) { Matrix residual; Matrix4x4 idealTransform = GetLocalTransform() * aTransformToSurface; idealTransform.ProjectTo2D(); mEffectiveTransform = SnapTransformTranslation(idealTransform, &residual); bool useIntermediateSurface; if (GetMaskLayer() || GetForceIsolatedGroup()) { useIntermediateSurface = true; #ifdef MOZ_DUMP_PAINTING } else if (gfxUtils::sDumpPainting) { useIntermediateSurface = true; #endif } else { float opacity = GetEffectiveOpacity(); CompositionOp blendMode = GetEffectiveMixBlendMode(); if ((opacity != 1.0f || blendMode != CompositionOp::OP_OVER) && HasMultipleChildren()) { useIntermediateSurface = true; } else { useIntermediateSurface = false; gfx::Matrix contTransform; if (!mEffectiveTransform.Is2D(&contTransform) || #ifdef MOZ_GFX_OPTIMIZE_MOBILE !contTransform.PreservesAxisAlignedRectangles()) { #else gfx::ThebesMatrix(contTransform).HasNonIntegerTranslation()) { #endif for (Layer* child = GetFirstChild(); child; child = child->GetNextSibling()) { const nsIntRect *clipRect = child->GetEffectiveClipRect(); /* We can't (easily) forward our transform to children with a non-empty clip * rect since it would need to be adjusted for the transform. See * the calculations performed by CalculateScissorRect above. * Nor for a child with a mask layer. */ if ((clipRect && !clipRect->IsEmpty() && !child->GetVisibleRegion().IsEmpty()) || child->GetMaskLayer()) { useIntermediateSurface = true; break; } } } } } mUseIntermediateSurface = useIntermediateSurface; if (useIntermediateSurface) { ComputeEffectiveTransformsForChildren(Matrix4x4::From2D(residual)); } else { ComputeEffectiveTransformsForChildren(idealTransform); } if (idealTransform.CanDraw2D()) { ComputeEffectiveTransformForMaskLayer(aTransformToSurface); } else { ComputeEffectiveTransformForMaskLayer(Matrix4x4()); } }
void ContainerLayer::DefaultComputeSupportsComponentAlphaChildren(bool* aNeedsSurfaceCopy) { bool supportsComponentAlphaChildren = false; bool needsSurfaceCopy = false; CompositionOp blendMode = GetEffectiveMixBlendMode(); if (UseIntermediateSurface()) { if (GetEffectiveVisibleRegion().GetNumRects() == 1 && (GetContentFlags() & Layer::CONTENT_OPAQUE)) { supportsComponentAlphaChildren = true; } else { gfx::Matrix transform; if (HasOpaqueAncestorLayer(this) && GetEffectiveTransform().Is2D(&transform) && !gfx::ThebesMatrix(transform).HasNonIntegerTranslation() && blendMode == gfx::CompositionOp::OP_OVER) { supportsComponentAlphaChildren = true; needsSurfaceCopy = true; } } } else if (blendMode == gfx::CompositionOp::OP_OVER) { supportsComponentAlphaChildren = (GetContentFlags() & Layer::CONTENT_OPAQUE) || (GetParent() && GetParent()->SupportsComponentAlphaChildren()); } mSupportsComponentAlphaChildren = supportsComponentAlphaChildren && gfxPrefs::ComponentAlphaEnabled(); if (aNeedsSurfaceCopy) { *aNeedsSurfaceCopy = mSupportsComponentAlphaChildren && needsSurfaceCopy; } }
void BasicCanvasLayer::Paint(DrawTarget* aTarget, SourceSurface* aMaskSurface) { if (IsHidden()) return; FirePreTransactionCallback(); UpdateTarget(); FireDidTransactionCallback(); CompositionOp mixBlendMode = GetEffectiveMixBlendMode(); PaintWithOpacity(aTarget, GetEffectiveOpacity(), aMaskSurface, mixBlendMode != CompositionOp::OP_OVER ? mixBlendMode : GetOperator()); }
already_AddRefed<gfxPattern> BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext, float aOpacity, Layer* aMaskLayer) { if (!mContainer) return nullptr; mContainer->SetImageFactory(mManager->IsCompositingCheap() ? nullptr : BasicManager()->GetImageFactory()); nsRefPtr<gfxASurface> surface; AutoLockImage autoLock(mContainer, getter_AddRefs(surface)); Image *image = autoLock.GetImage(); gfxIntSize size = mSize = autoLock.GetSize(); if (!surface || surface->CairoStatus()) { return nullptr; } nsRefPtr<gfxPattern> pat = new gfxPattern(surface); if (!pat) { return nullptr; } pat->SetFilter(mFilter); // The visible region can extend outside the image, so just draw // within the image bounds. if (aContext) { gfxContext::GraphicsOperator mixBlendMode = GetEffectiveMixBlendMode(); AutoSetOperator setOptimizedOperator(aContext, mixBlendMode != gfxContext::OPERATOR_OVER ? mixBlendMode : GetOperator()); PaintContext(pat, nsIntRegion(nsIntRect(0, 0, size.width, size.height)), aOpacity, aContext, aMaskLayer); GetContainer()->NotifyPaintedImage(image); } return pat.forget(); }
gfxContext::GraphicsOperator Layer::DeprecatedGetEffectiveMixBlendMode() { return ThebesOp(GetEffectiveMixBlendMode()); }