зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1250718 - Don't flatten opacity to an intermediate surface when used in the middle of preserve-3d. r=thinker
--HG-- extra : rebase_source : 867bab1b5369c88db3a845478f73d3a58845938c
This commit is contained in:
Родитель
8d2b64d662
Коммит
dbe7f4888a
|
@ -1387,10 +1387,17 @@ ContainerLayer::DefaultComputeEffectiveTransforms(const Matrix4x4& aTransformToS
|
||||||
useIntermediateSurface = true;
|
useIntermediateSurface = true;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
|
/* Don't use an intermediate surface for opacity when it's within a 3d
|
||||||
|
* context, since we'd rather keep the 3d effects. This matches the
|
||||||
|
* WebKit/blink behaviour, but is changing in the latest spec.
|
||||||
|
*/
|
||||||
float opacity = GetEffectiveOpacity();
|
float opacity = GetEffectiveOpacity();
|
||||||
CompositionOp blendMode = GetEffectiveMixBlendMode();
|
CompositionOp blendMode = GetEffectiveMixBlendMode();
|
||||||
if (((opacity != 1.0f || blendMode != CompositionOp::OP_OVER) && (HasMultipleChildren() || Creates3DContextWithExtendingChildren())) ||
|
if ((HasMultipleChildren() || Creates3DContextWithExtendingChildren()) &&
|
||||||
(!idealTransform.Is2D() && Creates3DContextWithExtendingChildren())) {
|
((opacity != 1.0f && !Extend3DContext()) ||
|
||||||
|
(blendMode != CompositionOp::OP_OVER))) {
|
||||||
|
useIntermediateSurface = true;
|
||||||
|
} else if (!idealTransform.Is2D() && Creates3DContextWithExtendingChildren()) {
|
||||||
useIntermediateSurface = true;
|
useIntermediateSurface = true;
|
||||||
} else {
|
} else {
|
||||||
useIntermediateSurface = false;
|
useIntermediateSurface = false;
|
||||||
|
|
|
@ -83,7 +83,7 @@ BasicContainerLayer::ComputeEffectiveTransforms(const Matrix4x4& aTransformToSur
|
||||||
GetMaskLayer() ||
|
GetMaskLayer() ||
|
||||||
GetForceIsolatedGroup() ||
|
GetForceIsolatedGroup() ||
|
||||||
(GetMixBlendMode() != CompositionOp::OP_OVER && HasMultipleChildren()) ||
|
(GetMixBlendMode() != CompositionOp::OP_OVER && HasMultipleChildren()) ||
|
||||||
(GetEffectiveOpacity() != 1.0 && (HasMultipleChildren() || hasSingleBlendingChild));
|
(GetEffectiveOpacity() != 1.0 && ((HasMultipleChildren() && !Extend3DContext()) || hasSingleBlendingChild));
|
||||||
|
|
||||||
if (!Extend3DContext()) {
|
if (!Extend3DContext()) {
|
||||||
idealTransform.ProjectTo2D();
|
idealTransform.ProjectTo2D();
|
||||||
|
|
|
@ -2003,7 +2003,8 @@ void nsDisplayList::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
|
||||||
bool same3DContext =
|
bool same3DContext =
|
||||||
(itemType == nsDisplayItem::TYPE_TRANSFORM &&
|
(itemType == nsDisplayItem::TYPE_TRANSFORM &&
|
||||||
static_cast<nsDisplayTransform*>(item)->IsParticipating3DContext()) ||
|
static_cast<nsDisplayTransform*>(item)->IsParticipating3DContext()) ||
|
||||||
(itemType == nsDisplayItem::TYPE_PERSPECTIVE &&
|
((itemType == nsDisplayItem::TYPE_PERSPECTIVE ||
|
||||||
|
itemType == nsDisplayItem::TYPE_OPACITY) &&
|
||||||
static_cast<nsDisplayPerspective*>(item)->Frame()->Extend3DContext());
|
static_cast<nsDisplayPerspective*>(item)->Frame()->Extend3DContext());
|
||||||
if (same3DContext &&
|
if (same3DContext &&
|
||||||
!static_cast<nsDisplayTransform*>(item)->IsLeafOf3DContext()) {
|
!static_cast<nsDisplayTransform*>(item)->IsLeafOf3DContext()) {
|
||||||
|
@ -4152,6 +4153,7 @@ nsDisplayOpacity::nsDisplayOpacity(nsDisplayListBuilder* aBuilder,
|
||||||
: nsDisplayWrapList(aBuilder, aFrame, aList, aScrollClip)
|
: nsDisplayWrapList(aBuilder, aFrame, aList, aScrollClip)
|
||||||
, mOpacity(aFrame->StyleDisplay()->mOpacity)
|
, mOpacity(aFrame->StyleDisplay()->mOpacity)
|
||||||
, mForEventsOnly(aForEventsOnly)
|
, mForEventsOnly(aForEventsOnly)
|
||||||
|
, mParticipatesInPreserve3D(false)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(nsDisplayOpacity);
|
MOZ_COUNT_CTOR(nsDisplayOpacity);
|
||||||
}
|
}
|
||||||
|
@ -4189,6 +4191,12 @@ nsDisplayOpacity::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||||
nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(container, aBuilder,
|
nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(container, aBuilder,
|
||||||
this, mFrame,
|
this, mFrame,
|
||||||
eCSSProperty_opacity);
|
eCSSProperty_opacity);
|
||||||
|
|
||||||
|
if (mParticipatesInPreserve3D) {
|
||||||
|
container->SetContentFlags(container->GetContentFlags() | Layer::CONTENT_EXTEND_3D_CONTEXT);
|
||||||
|
} else {
|
||||||
|
container->SetContentFlags(container->GetContentFlags() & ~Layer::CONTENT_EXTEND_3D_CONTEXT);
|
||||||
|
}
|
||||||
return container.forget();
|
return container.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3375,9 +3375,14 @@ public:
|
||||||
|
|
||||||
bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) override;
|
bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) override;
|
||||||
|
|
||||||
|
void SetParticipatesInPreserve3D(bool aParticipatesInPreserve3D)
|
||||||
|
{
|
||||||
|
mParticipatesInPreserve3D = aParticipatesInPreserve3D;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
float mOpacity;
|
float mOpacity;
|
||||||
bool mForEventsOnly;
|
bool mForEventsOnly;
|
||||||
|
bool mParticipatesInPreserve3D;
|
||||||
};
|
};
|
||||||
|
|
||||||
class nsDisplayBlendMode : public nsDisplayWrapList {
|
class nsDisplayBlendMode : public nsDisplayWrapList {
|
||||||
|
|
|
@ -1159,12 +1159,6 @@ nsIFrame::Extend3DContext() const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opacity can only be only the root or leaves of a preserve-3d context
|
|
||||||
// as it requires flattening.
|
|
||||||
if (HasOpacity() && Combines3DTransformWithAncestors()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsRect temp;
|
nsRect temp;
|
||||||
return !nsFrame::ShouldApplyOverflowClipping(this, disp) &&
|
return !nsFrame::ShouldApplyOverflowClipping(this, disp) &&
|
||||||
!GetClipPropClipRect(disp, &temp, GetSize()) &&
|
!GetClipPropClipRect(disp, &temp, GetSize()) &&
|
||||||
|
@ -1881,7 +1875,8 @@ static bool
|
||||||
ItemParticipatesIn3DContext(nsIFrame* aAncestor, nsDisplayItem* aItem)
|
ItemParticipatesIn3DContext(nsIFrame* aAncestor, nsDisplayItem* aItem)
|
||||||
{
|
{
|
||||||
nsIFrame* transformFrame;
|
nsIFrame* transformFrame;
|
||||||
if (aItem->GetType() == nsDisplayItem::TYPE_TRANSFORM) {
|
if (aItem->GetType() == nsDisplayItem::TYPE_TRANSFORM ||
|
||||||
|
aItem->GetType() == nsDisplayItem::TYPE_OPACITY) {
|
||||||
transformFrame = aItem->Frame();
|
transformFrame = aItem->Frame();
|
||||||
} else if (aItem->GetType() == nsDisplayItem::TYPE_PERSPECTIVE) {
|
} else if (aItem->GetType() == nsDisplayItem::TYPE_PERSPECTIVE) {
|
||||||
transformFrame = static_cast<nsDisplayPerspective*>(aItem)->TransformFrame();
|
transformFrame = static_cast<nsDisplayPerspective*>(aItem)->TransformFrame();
|
||||||
|
@ -1911,16 +1906,21 @@ WrapSeparatorTransform(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||||
static void
|
static void
|
||||||
CreateOpacityItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
CreateOpacityItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||||
nsDisplayList& aList, bool aItemForEventsOnly,
|
nsDisplayList& aList, bool aItemForEventsOnly,
|
||||||
const DisplayItemScrollClip* aScrollClip)
|
const DisplayItemScrollClip* aScrollClip,
|
||||||
|
bool aParticipatesInPreserve3D)
|
||||||
{
|
{
|
||||||
// Don't clip nsDisplayOpacity items. We clip their descendants instead.
|
// Don't clip nsDisplayOpacity items. We clip their descendants instead.
|
||||||
// The clip we would set on an element with opacity would clip
|
// The clip we would set on an element with opacity would clip
|
||||||
// all descendant content, but some should not be clipped.
|
// all descendant content, but some should not be clipped.
|
||||||
DisplayListClipState::AutoSaveRestore opacityClipState(aBuilder);
|
DisplayListClipState::AutoSaveRestore opacityClipState(aBuilder);
|
||||||
opacityClipState.Clear();
|
opacityClipState.Clear();
|
||||||
aList.AppendNewToTop(
|
nsDisplayOpacity* opacity =
|
||||||
new (aBuilder) nsDisplayOpacity(aBuilder, aFrame, &aList,
|
new (aBuilder) nsDisplayOpacity(aBuilder, aFrame, &aList,
|
||||||
aScrollClip, aItemForEventsOnly));
|
aScrollClip, aItemForEventsOnly);
|
||||||
|
if (opacity) {
|
||||||
|
opacity->SetParticipatesInPreserve3D(aParticipatesInPreserve3D);
|
||||||
|
aList.AppendToTop(opacity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -2021,7 +2021,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
||||||
aBuilder->EnterSVGEffectsContents(&hoistedScrollInfoItemsStorage);
|
aBuilder->EnterSVGEffectsContents(&hoistedScrollInfoItemsStorage);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool useOpacity = HasVisualOpacity() && !nsSVGUtils::CanOptimizeOpacity(this);
|
bool useOpacity = HasVisualOpacity() && !nsSVGUtils::CanOptimizeOpacity(this) && !usingSVGEffects;
|
||||||
bool useBlendMode = disp->mMixBlendMode != NS_STYLE_BLEND_NORMAL;
|
bool useBlendMode = disp->mMixBlendMode != NS_STYLE_BLEND_NORMAL;
|
||||||
bool useStickyPosition = disp->mPosition == NS_STYLE_POSITION_STICKY &&
|
bool useStickyPosition = disp->mPosition == NS_STYLE_POSITION_STICKY &&
|
||||||
IsScrollFrameActive(aBuilder,
|
IsScrollFrameActive(aBuilder,
|
||||||
|
@ -2172,8 +2172,6 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
||||||
clipState.ExitStackingContextContents(&containerItemScrollClip);
|
clipState.ExitStackingContextContents(&containerItemScrollClip);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is3DContextRoot = Extend3DContext() && !Combines3DTransformWithAncestors();
|
|
||||||
|
|
||||||
/* If there are any SVG effects, wrap the list up in an SVG effects item
|
/* If there are any SVG effects, wrap the list up in an SVG effects item
|
||||||
* (which also handles CSS group opacity). Note that we create an SVG effects
|
* (which also handles CSS group opacity). Note that we create an SVG effects
|
||||||
* item even if resultList is empty, since a filter can produce graphical
|
* item even if resultList is empty, since a filter can produce graphical
|
||||||
|
@ -2190,18 +2188,6 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
||||||
aBuilder->ExitSVGEffectsContents();
|
aBuilder->ExitSVGEffectsContents();
|
||||||
resultList.AppendToTop(&hoistedScrollInfoItemsStorage);
|
resultList.AppendToTop(&hoistedScrollInfoItemsStorage);
|
||||||
}
|
}
|
||||||
else if (useOpacity && !resultList.IsEmpty() && !is3DContextRoot) {
|
|
||||||
/* If this element is the root of a preserve-3d context, then we want
|
|
||||||
* to make sure any opacity items are on the outside of the transform
|
|
||||||
* so that they don't interfere with the chain of nsDisplayTransforms.
|
|
||||||
* Opacity on preserve-3d leaves need to be inside the transform for the
|
|
||||||
* same reason, and we do this in the general case as well to preserve
|
|
||||||
* existing behaviour.
|
|
||||||
*/
|
|
||||||
CreateOpacityItem(aBuilder, this, resultList, opacityItemForEventsOnly,
|
|
||||||
containerItemScrollClip);
|
|
||||||
useOpacity = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we're going to apply a transformation and don't have preserve-3d set, wrap
|
/* If we're going to apply a transformation and don't have preserve-3d set, wrap
|
||||||
* everything in an nsDisplayTransform. If there's nothing in the list, don't add
|
* everything in an nsDisplayTransform. If there's nothing in the list, don't add
|
||||||
|
@ -2214,8 +2200,8 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
||||||
* We also traverse into sublists created by nsDisplayWrapList or nsDisplayOpacity, so that
|
* We also traverse into sublists created by nsDisplayWrapList or nsDisplayOpacity, so that
|
||||||
* we find all the correct children.
|
* we find all the correct children.
|
||||||
*/
|
*/
|
||||||
if (isTransformed && !resultList.IsEmpty()) {
|
bool hasPreserve3DChildren = false;
|
||||||
if (!resultList.IsEmpty() && Extend3DContext()) {
|
if (isTransformed && !resultList.IsEmpty() && Extend3DContext()) {
|
||||||
// Install dummy nsDisplayTransform as a leaf containing
|
// Install dummy nsDisplayTransform as a leaf containing
|
||||||
// descendants not participating this 3D rendering context.
|
// descendants not participating this 3D rendering context.
|
||||||
nsDisplayList nonparticipants;
|
nsDisplayList nonparticipants;
|
||||||
|
@ -2228,6 +2214,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
||||||
WrapSeparatorTransform(aBuilder, this, dirtyRect,
|
WrapSeparatorTransform(aBuilder, this, dirtyRect,
|
||||||
&nonparticipants, &participants, index++);
|
&nonparticipants, &participants, index++);
|
||||||
participants.AppendToTop(item);
|
participants.AppendToTop(item);
|
||||||
|
hasPreserve3DChildren = true;
|
||||||
} else {
|
} else {
|
||||||
// The frame of the item doesn't participate the current
|
// The frame of the item doesn't participate the current
|
||||||
// context, or has no transform.
|
// context, or has no transform.
|
||||||
|
@ -2244,6 +2231,18 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
||||||
resultList.AppendToTop(&participants);
|
resultList.AppendToTop(&participants);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We create the opacity outside any transform separators we created,
|
||||||
|
* so that the opacity will be applied to them as groups. When we have
|
||||||
|
* opacity and preserve-3d we break the 'group' nature of opacity in order
|
||||||
|
* to maintain preserve-3d. This matches the behaviour of blink and WebKit,
|
||||||
|
* see bug 1250718.
|
||||||
|
*/
|
||||||
|
if (useOpacity && !resultList.IsEmpty()) {
|
||||||
|
CreateOpacityItem(aBuilder, this, resultList,
|
||||||
|
opacityItemForEventsOnly, containerItemScrollClip, hasPreserve3DChildren);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isTransformed && !resultList.IsEmpty()) {
|
||||||
// Restore clip state now so nsDisplayTransform is clipped properly.
|
// Restore clip state now so nsDisplayTransform is clipped properly.
|
||||||
if (!HasPerspective() && !useFixedPosition && !useStickyPosition) {
|
if (!HasPerspective() && !useFixedPosition && !useStickyPosition) {
|
||||||
clipState.ExitStackingContextContents(&containerItemScrollClip);
|
clipState.ExitStackingContextContents(&containerItemScrollClip);
|
||||||
|
@ -2275,14 +2274,6 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
||||||
aBuilder, this,
|
aBuilder, this,
|
||||||
GetContainingBlock()->GetContent()->GetPrimaryFrame(), &resultList));
|
GetContainingBlock()->GetContent()->GetPrimaryFrame(), &resultList));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we need an opacity item, but didn't do it earlier, add it now on the
|
|
||||||
* outside of the transform.
|
|
||||||
*/
|
|
||||||
if (useOpacity && !usingSVGEffects) {
|
|
||||||
CreateOpacityItem(aBuilder, this, resultList, opacityItemForEventsOnly,
|
|
||||||
containerItemScrollClip);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useFixedPosition || useStickyPosition) {
|
if (useFixedPosition || useStickyPosition) {
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html><head>
|
||||||
|
<style>
|
||||||
|
.first {
|
||||||
|
transform: translateZ(10px);
|
||||||
|
background-color: red;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
.second {
|
||||||
|
transform: translateZ(5px);
|
||||||
|
background-color: yellow;
|
||||||
|
top: 28px;
|
||||||
|
}
|
||||||
|
.third {
|
||||||
|
background-color: green;
|
||||||
|
top: 48px;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
.fourth {
|
||||||
|
background-color: blue;
|
||||||
|
top: 68px;
|
||||||
|
}
|
||||||
|
.leaf {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
position:absolute;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head><body>
|
||||||
|
|
||||||
|
<div class="leaf first"></div>
|
||||||
|
<div class="leaf second"></div>
|
||||||
|
<div class="leaf third"></div>
|
||||||
|
<div class="leaf fourth"></div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html><head>
|
||||||
|
<style>
|
||||||
|
.first {
|
||||||
|
transform: translateZ(10px);
|
||||||
|
background-color: blue;
|
||||||
|
top: 60px;
|
||||||
|
}
|
||||||
|
.second {
|
||||||
|
transform: translateZ(5px);
|
||||||
|
background-color: green;
|
||||||
|
top: 40px;
|
||||||
|
}
|
||||||
|
.third {
|
||||||
|
transform: translateZ(-5px);
|
||||||
|
background-color: yellow;
|
||||||
|
top: 20px;
|
||||||
|
}
|
||||||
|
.fourth {
|
||||||
|
transform: translateZ(-10px);
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
.preserve {
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
}
|
||||||
|
.leaf {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
position:absolute;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head><body>
|
||||||
|
|
||||||
|
<div class="preserve">
|
||||||
|
<div class="leaf first"></div>
|
||||||
|
<div class="preserve" style="opacity:0.5">
|
||||||
|
<div class="leaf second"></div>
|
||||||
|
<div class="leaf fourth"></div>
|
||||||
|
</div>
|
||||||
|
<div class="leaf third"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html><head>
|
||||||
|
<style>
|
||||||
|
.first {
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
.second {
|
||||||
|
background-color: blue;
|
||||||
|
top: 58px;
|
||||||
|
}
|
||||||
|
.leaf {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
position:absolute;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head><body>
|
||||||
|
|
||||||
|
<div class="leaf first"></div>
|
||||||
|
<div class="leaf second"></div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html><head>
|
||||||
|
<style>
|
||||||
|
.first {
|
||||||
|
transform: translateZ(10px);
|
||||||
|
background-color: blue;
|
||||||
|
top: 50px;
|
||||||
|
}
|
||||||
|
.second {
|
||||||
|
transform: translateZ(5px);
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
.preserve {
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
}
|
||||||
|
.leaf {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
position:absolute;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head><body>
|
||||||
|
|
||||||
|
<div class="preserve" style="opacity:0.5">
|
||||||
|
<div class="leaf first"></div>
|
||||||
|
<div class="leaf second"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html><head>
|
||||||
|
<style>
|
||||||
|
.first {
|
||||||
|
background-color: green;
|
||||||
|
top: 48px;
|
||||||
|
}
|
||||||
|
.second {
|
||||||
|
top: 88px;
|
||||||
|
}
|
||||||
|
.third {
|
||||||
|
background-color: blue;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
.group {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
.leaf {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
position:absolute;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head><body>
|
||||||
|
|
||||||
|
<div class="group">
|
||||||
|
<div class="leaf first"></div>
|
||||||
|
<canvas class="leaf second" width="100px" height="100px" id="canvas"></canvas>
|
||||||
|
</div>
|
||||||
|
<div class="leaf third"></div>
|
||||||
|
<script>
|
||||||
|
var canvas = document.getElementById("canvas");
|
||||||
|
var ctx = canvas.getContext("2d");
|
||||||
|
ctx.fillStyle = "red";
|
||||||
|
ctx.fillRect(0, 0, 100, 100);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html><head>
|
||||||
|
<style>
|
||||||
|
.first {
|
||||||
|
transform: translateZ(10px);
|
||||||
|
background-color: blue;
|
||||||
|
top: 0px;
|
||||||
|
}
|
||||||
|
.second {
|
||||||
|
background-color: green;
|
||||||
|
top: 40px;
|
||||||
|
}
|
||||||
|
.third {
|
||||||
|
top: 80px;
|
||||||
|
}
|
||||||
|
.preserve {
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
}
|
||||||
|
.leaf {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
position:absolute;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head><body>
|
||||||
|
|
||||||
|
<div class="preserve">
|
||||||
|
<div class="preserve" style="opacity:0.5">
|
||||||
|
<div class="leaf first"></div>
|
||||||
|
<div class="leaf second"></div>
|
||||||
|
<canvas class="leaf third" width="100px" height="100px" id="canvas"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
var canvas = document.getElementById("canvas");
|
||||||
|
var ctx = canvas.getContext("2d");
|
||||||
|
ctx.fillStyle = "red";
|
||||||
|
ctx.fillRect(0, 0, 100, 100);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html><head>
|
||||||
|
<style>
|
||||||
|
.first {
|
||||||
|
background-color: blue;
|
||||||
|
}
|
||||||
|
.second {
|
||||||
|
background-color: green;
|
||||||
|
top: 48px;
|
||||||
|
}
|
||||||
|
.leaf {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
position:absolute;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head><body>
|
||||||
|
|
||||||
|
<canvas class="leaf second" width="100px" height="100px" id="canvas"></canvas>
|
||||||
|
<div class="leaf first"></div>
|
||||||
|
<script>
|
||||||
|
var canvas = document.getElementById("canvas");
|
||||||
|
var ctx = canvas.getContext("2d");
|
||||||
|
ctx.fillStyle = "red";
|
||||||
|
ctx.fillRect(0, 0, 100, 100);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html><head>
|
||||||
|
<style>
|
||||||
|
.first {
|
||||||
|
transform: translateZ(10px);
|
||||||
|
background-color: blue;
|
||||||
|
top: 0px;
|
||||||
|
}
|
||||||
|
.second {
|
||||||
|
background-color: green;
|
||||||
|
top: 40px;
|
||||||
|
}
|
||||||
|
.preserve {
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
}
|
||||||
|
.leaf {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
position:absolute;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head><body>
|
||||||
|
|
||||||
|
<div class="preserve">
|
||||||
|
<div class="preserve" style="opacity:0.5">
|
||||||
|
<div class="leaf first"></div>
|
||||||
|
<canvas class="leaf second" width="100px" height="100px" id="canvas"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
var canvas = document.getElementById("canvas");
|
||||||
|
var ctx = canvas.getContext("2d");
|
||||||
|
ctx.fillStyle = "red";
|
||||||
|
ctx.fillRect(0, 0, 100, 100);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -72,3 +72,7 @@ fuzzy-if(cocoaWidget,128,9) == animate-preserve3d-parent.html animate-preserve3d
|
||||||
fuzzy-if(cocoaWidget,128,9) == animate-preserve3d-child.html animate-preserve3d-ref.html # intermittently fuzzy on Mac
|
fuzzy-if(cocoaWidget,128,9) == animate-preserve3d-child.html animate-preserve3d-ref.html # intermittently fuzzy on Mac
|
||||||
== animate-backface-hidden.html about:blank
|
== animate-backface-hidden.html about:blank
|
||||||
== 1245450-1.html green-rect.html
|
== 1245450-1.html green-rect.html
|
||||||
|
fuzzy(1,2000) == opacity-preserve3d-1.html opacity-preserve3d-1-ref.html
|
||||||
|
fuzzy(1,15000) == opacity-preserve3d-2.html opacity-preserve3d-2-ref.html
|
||||||
|
fuzzy(1,10000) == opacity-preserve3d-3.html opacity-preserve3d-3-ref.html
|
||||||
|
fuzzy(1,10000) == opacity-preserve3d-4.html opacity-preserve3d-4-ref.html
|
||||||
|
|
Загрузка…
Ссылка в новой задаче