Bug 1491864 - Fix preserve-3d in presence of anon boxes. r=mattwoodrow

In the button case we have a ::-moz-button-content pseudo-element, but this is
also an issue for tables and such.

These are supposed to be implementation details, so avoid looking at them for
preserve-3d.

I don't know how I didn't think of this on the regressing bug.

Differential Revision: https://phabricator.services.mozilla.com/D6131
This commit is contained in:
Emilio Cobos Álvarez 2018-09-19 21:21:18 +00:00
Родитель 6f15c7154f
Коммит 8f058ab54c
7 изменённых файлов: 164 добавлений и 11 удалений

Просмотреть файл

@ -1604,7 +1604,7 @@ bool
nsIFrame::Combines3DTransformWithAncestors(const nsStyleDisplay* aStyleDisplay) const
{
MOZ_ASSERT(aStyleDisplay == StyleDisplay());
nsIFrame* parent = GetInFlowParent();
nsIFrame* parent = GetClosestFlattenedTreeAncestorPrimaryFrame();
if (!parent || !parent->Extend3DContext()) {
return false;
}
@ -2625,9 +2625,9 @@ FrameParticipatesIn3DContext(nsIFrame* aAncestor, nsIFrame* aDescendant) {
MOZ_ASSERT(aAncestor != aDescendant);
MOZ_ASSERT(aAncestor->Extend3DContext());
nsIFrame* frame;
for (frame = aDescendant->GetInFlowParent();
for (frame = aDescendant->GetClosestFlattenedTreeAncestorPrimaryFrame();
frame && aAncestor != frame;
frame = frame->GetInFlowParent()) {
frame = frame->GetClosestFlattenedTreeAncestorPrimaryFrame()) {
if (!frame->Extend3DContext()) {
return false;
}

Просмотреть файл

@ -867,13 +867,16 @@ public:
/**
* Gets the parent of a frame, using the parent of the placeholder for
* out-of-flow frames.
*
* This is effectively the primary frame (or one of the continuations) of the
* closest flattened tree ancestor that has a frame (flattened tree ancestors
* may not have frames in presence of display: contents).
*/
inline nsContainerFrame* GetInFlowParent() const;
/**
* Gets the primary frame of the closest flattened tree ancestor that has a
* frame (flattened tree ancestors may not have frames in presence of display:
* contents).
*/
inline nsIFrame* GetClosestFlattenedTreeAncestorPrimaryFrame() const;
/**
* Return the placeholder for this frame (which must be out-of-flow).
* @note this will only return non-null if |this| is the first-in-flow

Просмотреть файл

@ -7,6 +7,7 @@
#ifndef nsIFrameInlines_h___
#define nsIFrameInlines_h___
#include "mozilla/dom/ElementInlines.h"
#include "nsContainerFrame.h"
#include "nsPlaceholderFrame.h"
#include "nsStyleStructInlines.h"
@ -180,4 +181,42 @@ nsIFrame::GetInFlowParent() const
return GetParent();
}
// We generally want to follow the style tree for preserve-3d, jumping through
// display: contents.
//
// There are various fun mismatches between the flattened tree and the frame
// tree which makes this non-trivial to do looking at the frame tree state:
//
// - Anon boxes. You'd have to step through them, because you generally want to
// ignore them.
//
// - IB-splits, which produce a frame tree where frames for the block inside
// the inline are not children of any frame from the inline.
//
// - display: contents, which makes DOM ancestors not have frames even when a
// descendant does.
//
// See GetFlattenedTreeParentElementForStyle for the difference between it and
// plain GetFlattenedTreeParentElement.
nsIFrame*
nsIFrame::GetClosestFlattenedTreeAncestorPrimaryFrame() const
{
if (!mContent) {
return nullptr;
}
Element* parent = mContent->GetFlattenedTreeParentElementForStyle();
while (parent) {
if (nsIFrame* frame = parent->GetPrimaryFrame()) {
return frame;
}
// NOTE(emilio): This should be an assert except we have code in tree which
// violates invariants like the <frameset> frame construction code.
if (MOZ_UNLIKELY(!parent->IsDisplayContents())) {
return nullptr;
}
parent = parent->GetFlattenedTreeParentElementForStyle();
}
return nullptr;
}
#endif

Просмотреть файл

@ -8377,7 +8377,7 @@ nsDisplayTransform::GetResultingTransformMatrixInternal(
if ((aFlags & INCLUDE_PRESERVE3D_ANCESTORS) && frame &&
frame->Combines3DTransformWithAncestors()) {
// Include the transform set on our parent
nsIFrame* parentFrame = frame->GetInFlowParent();
nsIFrame* parentFrame = frame->GetClosestFlattenedTreeAncestorPrimaryFrame();
NS_ASSERTION(parentFrame && parentFrame->IsTransformed() &&
parentFrame->Extend3DContext(),
"Preserve3D mismatch!");
@ -8656,7 +8656,7 @@ nsDisplayTransform::GetAccumulatedPreserved3DTransform(
const nsIFrame* establisher; // Establisher of the 3D rendering context.
for (establisher = mFrame;
establisher && establisher->Combines3DTransformWithAncestors();
establisher = establisher->GetInFlowParent()) {
establisher = establisher->GetClosestFlattenedTreeAncestorPrimaryFrame()) {
}
const nsIFrame* establisherReference = aBuilder->FindReferenceFrameFor(
nsLayoutUtils::GetCrossDocParentFrame(establisher));

Просмотреть файл

@ -143185,6 +143185,18 @@
{}
]
],
"css/css-transforms/preserve3d-button.html": [
[
"/css/css-transforms/preserve3d-button.html",
[
[
"/css/css-transforms/preserve3d-button-ref.html",
"=="
]
],
{}
]
],
"css/css-transforms/rotate/svg-rotate-3args-001.html": [
[
"/css/css-transforms/rotate/svg-rotate-3args-001.html",
@ -265202,6 +265214,11 @@
{}
]
],
"css/css-transforms/preserve3d-button-ref.html": [
[
{}
]
],
"css/css-transforms/reference/backface-visibility-hidden-ref.html": [
[
{}
@ -561880,6 +561897,14 @@
"752888eaf76630ae9835dd444c4941793ecf53cc",
"reftest"
],
"css/css-transforms/preserve3d-button-ref.html": [
"e5e3c1ebfcdd7c832a211d17ac2f1ed6f4116252",
"support"
],
"css/css-transforms/preserve3d-button.html": [
"544bb2496638a52915f7c97a238ccb053b4e884e",
"reftest"
],
"css/css-transforms/reference/backface-visibility-hidden-ref.html": [
"6a3e305e5c0c7fca6c8d53574b7a09eb21afb6cc",
"support"
@ -578401,7 +578426,7 @@
"testharness"
],
"css/cssom/overflow-serialization.html": [
"2911c8da3e3ae47af4fd764170fd7439cda56685",
"136b8aba117eb64403700d8c4348db085cede9c8",
"testharness"
],
"css/cssom/preferred-stylesheet-order.html": [
@ -578793,7 +578818,7 @@
"reftest"
],
"css/filter-effects/filter-cb-abspos-inline-001-ref.html": [
"6ebe4635511242cd0f5965a778a5a491cc406436",
"b4beae8004155c30dad4f48db3e2087f66c42c4f",
"support"
],
"css/filter-effects/filter-cb-abspos-inline-001.html": [

Просмотреть файл

@ -0,0 +1,42 @@
<!doctype html>
<title>CSS Test Reference</title>
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
<link rel="author" title="Mozilla" href="https://mozilla.org">
<style>
.scene {
width: 200px;
height: 200px;
perspective: 5000px;
}
.card {
width: 100%;
height: 100%;
transform-style: preserve-3d;
position: relative;
background: none;
border: 0;
padding: 0;
transform: rotateY(180deg);
}
.face {
position: absolute;
top: 0;
width: 100%;
height: 100%;
backface-visibility: hidden;
background: red;
}
.backface {
background: green;
transform: rotateY(180deg);
}
</style>
<div class="scene">
<div class="card">
<div class="face"></div>
<div class="face backface"></div>
</div>
</div>

Просмотреть файл

@ -0,0 +1,44 @@
<!doctype html>
<title>CSS Test: preserve-3d on buttons</title>
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
<link rel="author" title="Mozilla" href="https://mozilla.org">
<link rel="match" href="preserve3d-button-ref.html">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1491864">
<style>
.scene {
width: 200px;
height: 200px;
perspective: 5000px;
}
.card {
width: 100%;
height: 100%;
transform-style: preserve-3d;
position: relative;
background: none;
border: 0;
padding: 0;
transform: rotateY(180deg);
}
.face {
position: absolute;
top: 0;
width: 100%;
height: 100%;
backface-visibility: hidden;
background: red;
}
.backface {
background: green;
transform: rotateY(180deg);
}
</style>
<div class="scene">
<button class="card">
<div class="face"></div>
<div class="face backface"></div>
</button>
</div>