Bug 1145389 - Add gralloc allocation requet size check. r=nical, a=2.1+
[gecko.git] / layout / tables / nsTableColGroupFrame.cpp
blob7a29b52847a189c0b6a8b10ca7123f5740e0fe7c
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "nsTableColGroupFrame.h"
6 #include "nsTableColFrame.h"
7 #include "nsTableFrame.h"
8 #include "nsStyleContext.h"
9 #include "nsStyleConsts.h"
10 #include "nsPresContext.h"
11 #include "nsHTMLParts.h"
12 #include "nsGkAtoms.h"
13 #include "nsCOMPtr.h"
14 #include "nsCSSRendering.h"
15 #include "nsIPresShell.h"
17 using namespace mozilla;
19 #define COL_GROUP_TYPE_BITS (NS_FRAME_STATE_BIT(30) | \
20 NS_FRAME_STATE_BIT(31))
21 #define COL_GROUP_TYPE_OFFSET 30
23 nsTableColGroupType
24 nsTableColGroupFrame::GetColType() const
26 return (nsTableColGroupType)((mState & COL_GROUP_TYPE_BITS) >> COL_GROUP_TYPE_OFFSET);
29 void nsTableColGroupFrame::SetColType(nsTableColGroupType aType)
31 NS_ASSERTION(GetColType() == eColGroupContent,
32 "should only call nsTableColGroupFrame::SetColType with aType "
33 "!= eColGroupContent once");
34 uint32_t type = aType - eColGroupContent;
35 RemoveStateBits(COL_GROUP_TYPE_BITS);
36 AddStateBits(nsFrameState(type << COL_GROUP_TYPE_OFFSET));
39 void nsTableColGroupFrame::ResetColIndices(nsIFrame* aFirstColGroup,
40 int32_t aFirstColIndex,
41 nsIFrame* aStartColFrame)
43 nsTableColGroupFrame* colGroupFrame = (nsTableColGroupFrame*)aFirstColGroup;
44 int32_t colIndex = aFirstColIndex;
45 while (colGroupFrame) {
46 if (nsGkAtoms::tableColGroupFrame == colGroupFrame->GetType()) {
47 // reset the starting col index for the first cg only if we should reset
48 // the whole colgroup (aStartColFrame defaults to nullptr) or if
49 // aFirstColIndex is smaller than the existing starting col index
50 if ((colIndex != aFirstColIndex) ||
51 (colIndex < colGroupFrame->GetStartColumnIndex()) ||
52 !aStartColFrame) {
53 colGroupFrame->SetStartColumnIndex(colIndex);
55 nsIFrame* colFrame = aStartColFrame;
56 if (!colFrame || (colIndex != aFirstColIndex)) {
57 colFrame = colGroupFrame->GetFirstPrincipalChild();
59 while (colFrame) {
60 if (nsGkAtoms::tableColFrame == colFrame->GetType()) {
61 ((nsTableColFrame*)colFrame)->SetColIndex(colIndex);
62 colIndex++;
64 colFrame = colFrame->GetNextSibling();
67 colGroupFrame = static_cast<nsTableColGroupFrame*>
68 (colGroupFrame->GetNextSibling());
73 nsresult
74 nsTableColGroupFrame::AddColsToTable(int32_t aFirstColIndex,
75 bool aResetSubsequentColIndices,
76 const nsFrameList::Slice& aCols)
78 nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
80 tableFrame->InvalidateFrameSubtree();
82 // set the col indices of the col frames and and add col info to the table
83 int32_t colIndex = aFirstColIndex;
84 nsFrameList::Enumerator e(aCols);
85 for (; !e.AtEnd(); e.Next()) {
86 ((nsTableColFrame*)e.get())->SetColIndex(colIndex);
87 mColCount++;
88 tableFrame->InsertCol((nsTableColFrame &)*e.get(), colIndex);
89 colIndex++;
92 for (nsFrameList::Enumerator eTail = e.GetUnlimitedEnumerator();
93 !eTail.AtEnd();
94 eTail.Next()) {
95 ((nsTableColFrame*)eTail.get())->SetColIndex(colIndex);
96 colIndex++;
99 // We have already set the colindex for all the colframes in this
100 // colgroup that come after the first inserted colframe, but there could
101 // be other colgroups following this one and their colframes need
102 // correct colindices too.
103 if (aResetSubsequentColIndices && GetNextSibling()) {
104 ResetColIndices(GetNextSibling(), colIndex);
107 return NS_OK;
111 nsTableColGroupFrame*
112 nsTableColGroupFrame::GetLastRealColGroup(nsTableFrame* aTableFrame)
114 nsFrameList colGroups = aTableFrame->GetColGroups();
116 nsIFrame* nextToLastColGroup = nullptr;
117 nsFrameList::FrameLinkEnumerator link(colGroups);
118 for ( ; !link.AtEnd(); link.Next()) {
119 nextToLastColGroup = link.PrevFrame();
122 if (!link.PrevFrame()) {
123 return nullptr; // there are no col group frames
126 nsTableColGroupType lastColGroupType =
127 static_cast<nsTableColGroupFrame*>(link.PrevFrame())->GetColType();
128 if (eColGroupAnonymousCell == lastColGroupType) {
129 return static_cast<nsTableColGroupFrame*>(nextToLastColGroup);
132 return static_cast<nsTableColGroupFrame*>(link.PrevFrame());
135 // don't set mColCount here, it is done in AddColsToTable
136 void
137 nsTableColGroupFrame::SetInitialChildList(ChildListID aListID,
138 nsFrameList& aChildList)
140 MOZ_ASSERT(mFrames.IsEmpty(),
141 "unexpected second call to SetInitialChildList");
142 MOZ_ASSERT(aListID == kPrincipalList, "unexpected child list");
143 if (aChildList.IsEmpty()) {
144 nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
145 tableFrame->AppendAnonymousColFrames(this, GetSpan(), eColAnonymousColGroup,
146 false);
147 return;
150 mFrames.AppendFrames(this, aChildList);
153 /* virtual */ void
154 nsTableColGroupFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
156 nsContainerFrame::DidSetStyleContext(aOldStyleContext);
158 if (!aOldStyleContext) //avoid this on init
159 return;
161 nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
162 if (tableFrame->IsBorderCollapse() &&
163 tableFrame->BCRecalcNeeded(aOldStyleContext, StyleContext())) {
164 int32_t colCount = GetColCount();
165 if (!colCount)
166 return; // this is a degenerated colgroup
167 nsIntRect damageArea(GetFirstColumn()->GetColIndex(), 0, colCount,
168 tableFrame->GetRowCount());
169 tableFrame->AddBCDamageArea(damageArea);
173 void
174 nsTableColGroupFrame::AppendFrames(ChildListID aListID,
175 nsFrameList& aFrameList)
177 NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
179 nsTableColFrame* col = GetFirstColumn();
180 nsTableColFrame* nextCol;
181 while (col && col->GetColType() == eColAnonymousColGroup) {
182 // this colgroup spans one or more columns but now that there is a
183 // real column below, spanned anonymous columns should be removed,
184 // since the HTML spec says to ignore the span of a colgroup if it
185 // has content columns in it.
186 nextCol = col->GetNextCol();
187 RemoveFrame(kPrincipalList, col);
188 col = nextCol;
191 const nsFrameList::Slice& newFrames =
192 mFrames.AppendFrames(this, aFrameList);
193 InsertColsReflow(GetStartColumnIndex() + mColCount, newFrames);
196 void
197 nsTableColGroupFrame::InsertFrames(ChildListID aListID,
198 nsIFrame* aPrevFrame,
199 nsFrameList& aFrameList)
201 NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
202 NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
203 "inserting after sibling frame with different parent");
205 nsTableColFrame* col = GetFirstColumn();
206 nsTableColFrame* nextCol;
207 while (col && col->GetColType() == eColAnonymousColGroup) {
208 // this colgroup spans one or more columns but now that there is a
209 // real column below, spanned anonymous columns should be removed,
210 // since the HTML spec says to ignore the span of a colgroup if it
211 // has content columns in it.
212 nextCol = col->GetNextCol();
213 if (col == aPrevFrame) {
214 // This can happen when we're being appended to
215 NS_ASSERTION(!nextCol || nextCol->GetColType() != eColAnonymousColGroup,
216 "Inserting in the middle of our anonymous cols?");
217 // We'll want to insert at the beginning
218 aPrevFrame = nullptr;
220 RemoveFrame(kPrincipalList, col);
221 col = nextCol;
224 NS_ASSERTION(!aPrevFrame || aPrevFrame == aPrevFrame->LastContinuation(),
225 "Prev frame should be last in continuation chain");
226 NS_ASSERTION(!aPrevFrame || !GetNextColumn(aPrevFrame) ||
227 GetNextColumn(aPrevFrame)->GetColType() != eColAnonymousCol,
228 "Shouldn't be inserting before a spanned colframe");
230 const nsFrameList::Slice& newFrames =
231 mFrames.InsertFrames(this, aPrevFrame, aFrameList);
232 nsIFrame* prevFrame = nsTableFrame::GetFrameAtOrBefore(this, aPrevFrame,
233 nsGkAtoms::tableColFrame);
235 int32_t colIndex = (prevFrame) ? ((nsTableColFrame*)prevFrame)->GetColIndex() + 1 : GetStartColumnIndex();
236 InsertColsReflow(colIndex, newFrames);
239 void
240 nsTableColGroupFrame::InsertColsReflow(int32_t aColIndex,
241 const nsFrameList::Slice& aCols)
243 AddColsToTable(aColIndex, true, aCols);
245 PresContext()->PresShell()->FrameNeedsReflow(this,
246 nsIPresShell::eTreeChange,
247 NS_FRAME_HAS_DIRTY_CHILDREN);
250 void
251 nsTableColGroupFrame::RemoveChild(nsTableColFrame& aChild,
252 bool aResetSubsequentColIndices)
254 int32_t colIndex = 0;
255 nsIFrame* nextChild = nullptr;
256 if (aResetSubsequentColIndices) {
257 colIndex = aChild.GetColIndex();
258 nextChild = aChild.GetNextSibling();
260 mFrames.DestroyFrame(&aChild);
261 mColCount--;
262 if (aResetSubsequentColIndices) {
263 if (nextChild) { // reset inside this and all following colgroups
264 ResetColIndices(this, colIndex, nextChild);
266 else {
267 nsIFrame* nextGroup = GetNextSibling();
268 if (nextGroup) // reset next and all following colgroups
269 ResetColIndices(nextGroup, colIndex);
273 PresContext()->PresShell()->FrameNeedsReflow(this,
274 nsIPresShell::eTreeChange,
275 NS_FRAME_HAS_DIRTY_CHILDREN);
278 void
279 nsTableColGroupFrame::RemoveFrame(ChildListID aListID,
280 nsIFrame* aOldFrame)
282 NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
284 if (!aOldFrame) {
285 return;
287 bool contentRemoval = false;
289 if (nsGkAtoms::tableColFrame == aOldFrame->GetType()) {
290 nsTableColFrame* colFrame = (nsTableColFrame*)aOldFrame;
291 if (colFrame->GetColType() == eColContent) {
292 contentRemoval = true;
293 // Remove any anonymous column frames this <col> produced via a colspan
294 nsTableColFrame* col = colFrame->GetNextCol();
295 nsTableColFrame* nextCol;
296 while (col && col->GetColType() == eColAnonymousCol) {
297 #ifdef DEBUG
298 nsIFrame* providerFrame = colFrame->GetParentStyleContextFrame();
299 if (colFrame->StyleContext()->GetParent() ==
300 providerFrame->StyleContext()) {
301 NS_ASSERTION(col->StyleContext() == colFrame->StyleContext() &&
302 col->GetContent() == colFrame->GetContent(),
303 "How did that happen??");
305 // else colFrame is being removed because of a frame
306 // reconstruct on it, and its style context is still the old
307 // one, so we can't assert anything about how it compares to
308 // col's style context.
309 #endif
310 nextCol = col->GetNextCol();
311 RemoveFrame(kPrincipalList, col);
312 col = nextCol;
316 int32_t colIndex = colFrame->GetColIndex();
317 // The RemoveChild call handles calling FrameNeedsReflow on us.
318 RemoveChild(*colFrame, true);
320 nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
321 tableFrame->RemoveCol(this, colIndex, true, true);
322 if (mFrames.IsEmpty() && contentRemoval &&
323 GetColType() == eColGroupContent) {
324 tableFrame->AppendAnonymousColFrames(this, GetSpan(),
325 eColAnonymousColGroup, true);
328 else {
329 mFrames.DestroyFrame(aOldFrame);
333 nsIFrame::LogicalSides
334 nsTableColGroupFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
336 if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
337 NS_STYLE_BOX_DECORATION_BREAK_CLONE)) {
338 return LogicalSides();
341 LogicalSides skip;
342 if (nullptr != GetPrevInFlow()) {
343 skip |= eLogicalSideBitsBStart;
345 if (nullptr != GetNextInFlow()) {
346 skip |= eLogicalSideBitsBEnd;
348 return skip;
351 void
352 nsTableColGroupFrame::Reflow(nsPresContext* aPresContext,
353 nsHTMLReflowMetrics& aDesiredSize,
354 const nsHTMLReflowState& aReflowState,
355 nsReflowStatus& aStatus)
357 DO_GLOBAL_REFLOW_COUNT("nsTableColGroupFrame");
358 DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
359 NS_ASSERTION(nullptr!=mContent, "bad state -- null content for frame");
361 const nsStyleVisibility* groupVis = StyleVisibility();
362 bool collapseGroup = (NS_STYLE_VISIBILITY_COLLAPSE == groupVis->mVisible);
363 if (collapseGroup) {
364 nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
365 tableFrame->SetNeedToCollapse(true);
367 // for every content child that (is a column thingy and does not already have a frame)
368 // create a frame and adjust it's style
370 for (nsIFrame *kidFrame = mFrames.FirstChild(); kidFrame;
371 kidFrame = kidFrame->GetNextSibling()) {
372 // Give the child frame a chance to reflow, even though we know it'll have 0 size
373 nsHTMLReflowMetrics kidSize(aReflowState);
374 nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame,
375 LogicalSize(kidFrame->GetWritingMode()));
377 nsReflowStatus status;
378 ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, 0, 0, 0, status);
379 FinishReflowChild(kidFrame, aPresContext, kidSize, nullptr, 0, 0, 0);
382 aDesiredSize.ClearSize();
383 aStatus = NS_FRAME_COMPLETE;
384 NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
387 nsTableColFrame * nsTableColGroupFrame::GetFirstColumn()
389 return GetNextColumn(nullptr);
392 nsTableColFrame * nsTableColGroupFrame::GetNextColumn(nsIFrame *aChildFrame)
394 nsTableColFrame *result = nullptr;
395 nsIFrame *childFrame = aChildFrame;
396 if (!childFrame) {
397 childFrame = mFrames.FirstChild();
399 else {
400 childFrame = childFrame->GetNextSibling();
402 while (childFrame)
404 if (NS_STYLE_DISPLAY_TABLE_COLUMN ==
405 childFrame->StyleDisplay()->mDisplay)
407 result = (nsTableColFrame *)childFrame;
408 break;
410 childFrame = childFrame->GetNextSibling();
412 return result;
415 int32_t nsTableColGroupFrame::GetSpan()
417 return StyleTable()->mSpan;
420 void nsTableColGroupFrame::SetContinuousBCBorderWidth(uint8_t aForSide,
421 BCPixelSize aPixelValue)
423 switch (aForSide) {
424 case NS_SIDE_TOP:
425 mTopContBorderWidth = aPixelValue;
426 return;
427 case NS_SIDE_BOTTOM:
428 mBottomContBorderWidth = aPixelValue;
429 return;
430 default:
431 NS_ERROR("invalid side arg");
435 void nsTableColGroupFrame::GetContinuousBCBorderWidth(nsMargin& aBorder)
437 int32_t aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel();
438 nsTableFrame* table = nsTableFrame::GetTableFrame(this);
439 nsTableColFrame* col = table->GetColFrame(mStartColIndex + mColCount - 1);
440 col->GetContinuousBCBorderWidth(aBorder);
441 aBorder.top = BC_BORDER_BOTTOM_HALF_COORD(aPixelsToTwips,
442 mTopContBorderWidth);
443 aBorder.bottom = BC_BORDER_TOP_HALF_COORD(aPixelsToTwips,
444 mBottomContBorderWidth);
447 /* ----- global methods ----- */
449 nsTableColGroupFrame*
450 NS_NewTableColGroupFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
452 return new (aPresShell) nsTableColGroupFrame(aContext);
455 NS_IMPL_FRAMEARENA_HELPERS(nsTableColGroupFrame)
457 nsIAtom*
458 nsTableColGroupFrame::GetType() const
460 return nsGkAtoms::tableColGroupFrame;
463 void
464 nsTableColGroupFrame::InvalidateFrame(uint32_t aDisplayItemKey)
466 nsIFrame::InvalidateFrame(aDisplayItemKey);
467 GetParent()->InvalidateFrameWithRect(GetVisualOverflowRect() + GetPosition(), aDisplayItemKey);
470 void
471 nsTableColGroupFrame::InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey)
473 nsIFrame::InvalidateFrameWithRect(aRect, aDisplayItemKey);
474 // If we have filters applied that would affects our bounds, then
475 // we get an inactive layer created and this is computed
476 // within FrameLayerBuilder
477 GetParent()->InvalidateFrameWithRect(aRect + GetPosition(), aDisplayItemKey);
480 #ifdef DEBUG_FRAME_DUMP
481 nsresult
482 nsTableColGroupFrame::GetFrameName(nsAString& aResult) const
484 return MakeFrameName(NS_LITERAL_STRING("TableColGroup"), aResult);
487 void nsTableColGroupFrame::Dump(int32_t aIndent)
489 char* indent = new char[aIndent + 1];
490 if (!indent) return;
491 for (int32_t i = 0; i < aIndent + 1; i++) {
492 indent[i] = ' ';
494 indent[aIndent] = 0;
496 printf("%s**START COLGROUP DUMP**\n%s startcolIndex=%d colcount=%d span=%d coltype=",
497 indent, indent, GetStartColumnIndex(), GetColCount(), GetSpan());
498 nsTableColGroupType colType = GetColType();
499 switch (colType) {
500 case eColGroupContent:
501 printf(" content ");
502 break;
503 case eColGroupAnonymousCol:
504 printf(" anonymous-column ");
505 break;
506 case eColGroupAnonymousCell:
507 printf(" anonymous-cell ");
508 break;
510 // verify the colindices
511 int32_t j = GetStartColumnIndex();
512 nsTableColFrame* col = GetFirstColumn();
513 while (col) {
514 NS_ASSERTION(j == col->GetColIndex(), "wrong colindex on col frame");
515 col = col->GetNextCol();
516 j++;
518 NS_ASSERTION((j - GetStartColumnIndex()) == GetColCount(),
519 "number of cols out of sync");
520 printf("\n%s**END COLGROUP DUMP** ", indent);
521 delete [] indent;
523 #endif