1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
|
From 4dcbca8b3c26b451e1376cd1b7c88ab984a45b39 Mon Sep 17 00:00:00 2001
From: Mats Palmgren <mats@mozilla.com>
Date: Tue, 14 Apr 2015 22:12:39 -0400
Subject: [PATCH] Bug 1143299 - Make frame insertion methods deal with
aPrevFrame being on an overflow list. r=roc, a=bkerensa
---
layout/generic/nsBlockFrame.cpp | 18 ++++++++++++---
layout/generic/nsBlockFrame.h | 14 ++++++++----
layout/generic/nsContainerFrame.cpp | 41 +++++++++++++++++++---------------
layout/tables/nsTableFrame.cpp | 2 ++
layout/tables/nsTableRowFrame.cpp | 2 ++
layout/tables/nsTableRowGroupFrame.cpp | 2 ++
6 files changed, 54 insertions(+), 25 deletions(-)
diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp
index a011bcf..70d5297 100644
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -1049,7 +1049,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
state.mOverflowTracker = &tracker;
// Drain & handle pushed floats
- DrainPushedFloats(state);
+ DrainPushedFloats();
nsOverflowAreas fcBounds;
nsReflowStatus fcStatus = NS_FRAME_COMPLETE;
ReflowPushedFloats(state, fcBounds, fcStatus);
@@ -4438,9 +4438,13 @@ nsBlockFrame::DrainSelfOverflowList()
* might push some of them on). Floats with placeholders in this block
* are reflowed by (nsBlockReflowState/nsLineLayout)::AddFloat, which
* also maintains these invariants.
+ *
+ * DrainSelfPushedFloats moves any pushed floats from this block's own
+ * PushedFloats list back into mFloats. DrainPushedFloats additionally
+ * moves frames from its prev-in-flow's PushedFloats list into mFloats.
*/
void
-nsBlockFrame::DrainPushedFloats(nsBlockReflowState& aState)
+nsBlockFrame::DrainSelfPushedFloats()
{
#ifdef DEBUG
// Between when we drain pushed floats and when we complete reflow,
@@ -4503,12 +4507,18 @@ nsBlockFrame::DrainPushedFloats(nsBlockReflowState& aState)
RemovePushedFloats()->Delete(presContext->PresShell());
}
}
+}
+
+void
+nsBlockFrame::DrainPushedFloats()
+{
+ DrainSelfPushedFloats();
// After our prev-in-flow has completed reflow, it may have a pushed
// floats list, containing floats that we need to own. Take these.
nsBlockFrame* prevBlock = static_cast<nsBlockFrame*>(GetPrevInFlow());
if (prevBlock) {
- AutoFrameListPtr list(presContext, prevBlock->RemovePushedFloats());
+ AutoFrameListPtr list(PresContext(), prevBlock->RemovePushedFloats());
if (list && list->NotEmpty()) {
mFloats.InsertFrames(this, nullptr, *list);
}
@@ -4711,6 +4721,7 @@ nsBlockFrame::AppendFrames(ChildListID aListID,
return nsContainerFrame::AppendFrames(aListID, aFrameList);
}
else if (kFloatList == aListID) {
+ DrainSelfPushedFloats(); // ensure the last frame is in mFloats
mFloats.AppendFrames(nullptr, aFrameList);
return NS_OK;
}
@@ -4757,6 +4768,7 @@ nsBlockFrame::InsertFrames(ChildListID aListID,
return nsContainerFrame::InsertFrames(aListID, aPrevFrame, aFrameList);
}
else if (kFloatList == aListID) {
+ DrainSelfPushedFloats(); // ensure aPrevFrame is in mFloats
mFloats.InsertFrames(this, aPrevFrame, aFrameList);
return NS_OK;
}
diff --git a/layout/generic/nsBlockFrame.h b/layout/generic/nsBlockFrame.h
index 1a6bb1e..07f7508 100644
--- a/layout/generic/nsBlockFrame.h
+++ b/layout/generic/nsBlockFrame.h
@@ -533,10 +533,16 @@ protected:
return GetStateBits() & NS_BLOCK_HAS_OVERFLOW_OUT_OF_FLOWS;
}
- /** grab pushed floats from this block's prevInFlow, and splice
- * them into this block's mFloats list.
- */
- void DrainPushedFloats(nsBlockReflowState& aState);
+ /**
+ * Moves frames from our PushedFloats list back into our mFloats list.
+ */
+ void DrainSelfPushedFloats();
+
+ /**
+ * First calls DrainSelfPushedFloats() then grabs pushed floats from this
+ * block's prev-in-flow, and splice them into this block's mFloats list too.
+ */
+ void DrainPushedFloats();
/** Load all our floats into the float manager (without reflowing them).
* Assumes float manager is in our own coordinate system.
diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp
index 76f0748..3ffcba7 100644
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -102,16 +102,18 @@ nsContainerFrame::AppendFrames(ChildListID aListID,
return NS_ERROR_INVALID_ARG;
}
}
- if (aFrameList.NotEmpty()) {
- mFrames.AppendFrames(this, aFrameList);
- // Ask the parent frame to reflow me.
- if (aListID == kPrincipalList)
- {
- PresContext()->PresShell()->
- FrameNeedsReflow(this, nsIPresShell::eTreeChange,
- NS_FRAME_HAS_DIRTY_CHILDREN);
- }
+ if (MOZ_UNLIKELY(aFrameList.IsEmpty())) {
+ return NS_OK;
+ }
+
+ DrainSelfOverflowList(); // ensure the last frame is in mFrames
+ mFrames.AppendFrames(this, aFrameList);
+
+ if (aListID != kNoReflowPrincipalList) {
+ PresContext()->PresShell()->
+ FrameNeedsReflow(this, nsIPresShell::eTreeChange,
+ NS_FRAME_HAS_DIRTY_CHILDREN);
}
return NS_OK;
}
@@ -131,16 +133,19 @@ nsContainerFrame::InsertFrames(ChildListID aListID,
return NS_ERROR_INVALID_ARG;
}
}
- if (aFrameList.NotEmpty()) {
- // Insert frames after aPrevFrame
- mFrames.InsertFrames(this, aPrevFrame, aFrameList);
- if (aListID == kPrincipalList)
- {
- PresContext()->PresShell()->
- FrameNeedsReflow(this, nsIPresShell::eTreeChange,
- NS_FRAME_HAS_DIRTY_CHILDREN);
- }
+ if (MOZ_UNLIKELY(aFrameList.IsEmpty())) {
+ return NS_OK;
+ }
+
+ DrainSelfOverflowList(); // ensure aPrevFrame is in mFrames
+ mFrames.InsertFrames(this, aPrevFrame, aFrameList);
+
+ if (aListID != kNoReflowPrincipalList) {
+ PresContext()->PresShell()->
+ FrameNeedsReflow(this, nsIPresShell::eTreeChange,
+ NS_FRAME_HAS_DIRTY_CHILDREN);
+
}
return NS_OK;
}
diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp
index 60613ba..44088da 100644
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -2232,6 +2232,7 @@ nsTableFrame::AppendFrames(ChildListID aListID,
InsertColGroups(startColIndex,
nsFrameList::Slice(mColGroups, f, f->GetNextSibling()));
} else if (IsRowGroup(display->mDisplay)) {
+ DrainSelfOverflowList(); // ensure the last frame is in mFrames
// Append the new row group frame to the sibling chain
mFrames.AppendFrame(nullptr, f);
@@ -2404,6 +2405,7 @@ nsTableFrame::HomogenousInsertFrames(ChildListID aListID,
InsertColGroups(startColIndex, newColgroups);
} else if (IsRowGroup(display->mDisplay)) {
NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
+ DrainSelfOverflowList(); // ensure aPrevFrame is in mFrames
// Insert the frames in the sibling chain
const nsFrameList::Slice& newRowGroups =
mFrames.InsertFrames(nullptr, aPrevFrame, aFrameList);
diff --git a/layout/tables/nsTableRowFrame.cpp b/layout/tables/nsTableRowFrame.cpp
index d1c493b..2351de3 100644
--- a/layout/tables/nsTableRowFrame.cpp
+++ b/layout/tables/nsTableRowFrame.cpp
@@ -182,6 +182,7 @@ nsTableRowFrame::AppendFrames(ChildListID aListID,
{
NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
+ DrainSelfOverflowList(); // ensure the last frame is in mFrames
const nsFrameList::Slice& newCells = mFrames.AppendFrames(nullptr, aFrameList);
// Add the new cell frames to the table
@@ -208,6 +209,7 @@ nsTableRowFrame::InsertFrames(ChildListID aListID,
NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
"inserting after sibling frame with different parent");
+ DrainSelfOverflowList(); // ensure aPrevFrame is in mFrames
//Insert Frames in the frame list
const nsFrameList::Slice& newCells = mFrames.InsertFrames(nullptr, aPrevFrame, aFrameList);
diff --git a/layout/tables/nsTableRowGroupFrame.cpp b/layout/tables/nsTableRowGroupFrame.cpp
index 34aaf02..40b349b 100644
--- a/layout/tables/nsTableRowGroupFrame.cpp
+++ b/layout/tables/nsTableRowGroupFrame.cpp
@@ -1389,6 +1389,7 @@ nsTableRowGroupFrame::AppendFrames(ChildListID aListID,
{
NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
+ DrainSelfOverflowList(); // ensure the last frame is in mFrames
ClearRowCursor();
// collect the new row frames in an array
@@ -1430,6 +1431,7 @@ nsTableRowGroupFrame::InsertFrames(ChildListID aListID,
NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
"inserting after sibling frame with different parent");
+ DrainSelfOverflowList(); // ensure aPrevFrame is in mFrames
ClearRowCursor();
// collect the new row frames in an array
--
2.2.1
|