Matrix4x4 AdjustAndCombineWithCSSTransform(const Matrix4x4& asyncTransform, Layer* aLayer) { Matrix4x4 result = asyncTransform; // Container layers start at the origin, but they are clipped to where they // actually have content on the screen. The tree transform is meant to apply // to the clipped area. If the tree transform includes a scale component, // then applying it to container as-is will produce incorrect results. To // avoid this, translate the layer so that the clip rect starts at the origin, // apply the tree transform, and translate back. if (const nsIntRect* shadowClipRect = aLayer->AsLayerComposite()->GetShadowClipRect()) { if (shadowClipRect->TopLeft() != nsIntPoint()) { // avoid a gratuitous change of basis result.ChangeBasis(shadowClipRect->x, shadowClipRect->y, 0); } } // Combine the async transform with the layer's CSS transform. result = aLayer->GetTransform() * result; return result; }
bool LayerTransactionParent::RecvGetAnimationTransform(PLayerParent* aParent, MaybeTransform* aTransform) { if (mDestroyed || !layer_manager() || layer_manager()->IsDestroyed()) { return false; } Layer* layer = cast(aParent)->AsLayer(); if (!layer) { return false; } // This method is specific to transforms applied by animation. // This is because this method uses the information stored with an animation // such as the origin of the reference frame corresponding to the layer, to // recover the untranslated transform from the shadow transform. For // transforms that are not set by animation we don't have this information // available. if (!layer->AsLayerComposite()->GetShadowTransformSetByAnimation()) { *aTransform = mozilla::void_t(); return true; } // The following code recovers the untranslated transform // from the shadow transform by undoing the translations in // AsyncCompositionManager::SampleValue. Matrix4x4 transform = layer->AsLayerComposite()->GetShadowTransform(); if (ContainerLayer* c = layer->AsContainerLayer()) { // Undo the scale transform applied by AsyncCompositionManager::SampleValue transform.ScalePost(1.0f/c->GetInheritedXScale(), 1.0f/c->GetInheritedYScale(), 1.0f); } float scale = 1; gfxPoint3D scaledOrigin; gfxPoint3D transformOrigin; for (uint32_t i=0; i < layer->GetAnimations().Length(); i++) { if (layer->GetAnimations()[i].data().type() == AnimationData::TTransformData) { const TransformData& data = layer->GetAnimations()[i].data().get_TransformData(); scale = data.appUnitsPerDevPixel(); scaledOrigin = gfxPoint3D(NS_round(NSAppUnitsToFloatPixels(data.origin().x, scale)), NS_round(NSAppUnitsToFloatPixels(data.origin().y, scale)), 0.0f); double cssPerDev = double(nsDeviceContext::AppUnitsPerCSSPixel()) / double(scale); transformOrigin = data.transformOrigin() * cssPerDev; break; } } // Undo the translation to the origin of the reference frame applied by // AsyncCompositionManager::SampleValue transform.Translate(-scaledOrigin.x, -scaledOrigin.y, -scaledOrigin.z); // Undo the rebasing applied by // nsDisplayTransform::GetResultingTransformMatrixInternal gfxPoint3D basis = -scaledOrigin - transformOrigin; transform.ChangeBasis(basis.x, basis.y, basis.z); // Convert to CSS pixels (this undoes the operations performed by // nsStyleTransformMatrix::ProcessTranslatePart which is called from // nsDisplayTransform::GetResultingTransformMatrix) double devPerCss = double(scale) / double(nsDeviceContext::AppUnitsPerCSSPixel()); transform._41 *= devPerCss; transform._42 *= devPerCss; transform._43 *= devPerCss; *aTransform = transform; return true; }