Bug 1102175 Part 1 - Propagate used writing-mode from body element to its ancestors. r=jfkthame

Differential Revision: https://phabricator.services.mozilla.com/D45481
This commit is contained in:
Ting-Yu Lin
2019-10-09 22:11:02 +00:00
parent 8e5aa19fea
commit 07000ca10b
7 changed files with 94 additions and 33 deletions

View File

@@ -2314,6 +2314,33 @@ nsIFrame* nsCSSFrameConstructor::ConstructDocElementFrame(
return nullptr;
}
if (aDocElement->IsHTMLElement() &&
mDocElementContainingBlock->IsCanvasFrame()) {
// This implements "The Principal Writing Mode".
// https://drafts.csswg.org/css-writing-modes-3/#principal-flow
//
// If there's a <body> element, its writing-mode, direction, and
// text-orientation override the root element's used value.
//
// We need to copy <body>'s WritingMode to mDocElementContainingBlock before
// construct mRootElementFrame so that anonymous internal frames such as
// <html> with table style can copy their parent frame's mWritingMode in
// nsFrame::Init().
MOZ_ASSERT(!mRootElementFrame,
"We need to copy <body>'s principal writing-mode before "
"constructing mRootElementFrame.");
Element* body = mDocument->GetBodyElement();
if (body) {
RefPtr<ComputedStyle> bodyStyle = ResolveComputedStyle(body);
mDocElementContainingBlock->PropagateWritingModeToSelfAndAncestors(
WritingMode(bodyStyle));
} else {
mDocElementContainingBlock->PropagateWritingModeToSelfAndAncestors(
mDocElementContainingBlock->GetWritingMode());
}
}
nsFrameConstructorSaveState docElementContainingBlockAbsoluteSaveState;
if (mHasRootAbsPosContainingBlock) {
// Push the absolute containing block now so we can absolutely position
@@ -6813,7 +6840,7 @@ void nsCSSFrameConstructor::ContentAppended(nsIContent* aFirstNewContent,
}
LAYOUT_PHASE_TEMP_EXIT();
if (WipeInsertionParent(parentFrame)) {
if (WipeInsertionParent(parentFrame, aFirstNewContent, nullptr)) {
LAYOUT_PHASE_TEMP_REENTER();
return;
}
@@ -7214,7 +7241,7 @@ void nsCSSFrameConstructor::ContentRangeInserted(
}
LAYOUT_PHASE_TEMP_EXIT();
if (WipeInsertionParent(insertion.mParentFrame)) {
if (WipeInsertionParent(insertion.mParentFrame, aStartChild, aEndChild)) {
LAYOUT_PHASE_TEMP_REENTER();
return;
}
@@ -8414,6 +8441,17 @@ bool nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(
"placeholder for primary frame has previous continuations?");
nsIFrame* parent = inFlowFrame->GetParent();
if (aFrame->GetContent() == mDocument->GetBodyElement()) {
// If the frame of the canonical body element is removed (either because of
// removing of the element, or removing for frame construction like
// writing-mode changed), we need to reframe the root element so that the
// root element's frames has the correct writing-mode propagated from body
// element. (See nsCSSFrameConstructor::ConstructDocElementFrame.)
TRACE("Root");
RecreateFramesForContent(mDocument->GetRootElement(), InsertionKind::Async);
return true;
}
if (inFlowFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
nsIFrame* grandparent = parent->GetParent();
MOZ_ASSERT(grandparent);
@@ -11344,13 +11382,34 @@ static bool IsSafeToAppendToIBSplitInline(nsIFrame* aParentFrame,
return true;
}
bool nsCSSFrameConstructor::WipeInsertionParent(nsContainerFrame* aFrame) {
bool nsCSSFrameConstructor::WipeInsertionParent(nsContainerFrame* aFrame,
nsIContent* aStartChild,
nsIContent* aEndChild) {
#define TRACE(reason) \
PROFILER_TRACING("Layout", "WipeInsertionParent: " reason, LAYOUT, \
TRACING_EVENT)
MOZ_ASSERT(aStartChild, "Must always pass aStartChild!");
const LayoutFrameType frameType = aFrame->Type();
if (aFrame->GetContent() == mDocument->GetRootElement()) {
// If we insert a content that becomes the canonical body element, we need
// to reframe the root element so that the root element's frames has the
// correct writing-mode propagated from body element. (See
// nsCSSFrameConstructor::ConstructDocElementFrame.)
nsIContent* bodyElement = mDocument->GetBodyElement();
for (nsIContent* child = aStartChild; child != aEndChild;
child = child->GetNextSibling()) {
if (child == bodyElement) {
TRACE("Root");
RecreateFramesForContent(mDocument->GetRootElement(),
InsertionKind::Async);
return true;
}
}
}
// FIXME(emilio): This looks terribly inefficient if you insert elements deep
// in a MathML subtree.
if (aFrame->IsFrameOfType(nsIFrame::eMathML)) {