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 "nsCOMPtr.h"
6 #include "nsTableColFrame.h"
7 #include "nsTableFrame.h"
8 #include "nsContainerFrame.h"
9 #include "nsStyleContext.h"
aMethod()10 #include "nsStyleConsts.h"
11 #include "nsPresContext.h"
12 #include "nsGkAtoms.h"
13 #include "nsCSSRendering.h"
14 #include "nsIContent.h"
15 
16 using namespace mozilla;
17 
18 #define COL_TYPE_BITS                 (NS_FRAME_STATE_BIT(28) | \
mainnull19                                        NS_FRAME_STATE_BIT(29) | \
20                                        NS_FRAME_STATE_BIT(30) | \
21                                        NS_FRAME_STATE_BIT(31))
22 #define COL_TYPE_OFFSET               28
23 
24 using namespace mozilla;
25 
26 nsTableColFrame::nsTableColFrame(nsStyleContext* aContext) :
27   nsSplittableFrame(aContext)
28 {
29   SetColType(eColContent);
30   ResetIntrinsics();
31   ResetSpanIntrinsics();
32   ResetFinalISize();
33 }
34 
35 nsTableColFrame::~nsTableColFrame()
36 {
37 }
38 
39 nsTableColType
40 nsTableColFrame::GetColType() const
41 {
42   return (nsTableColType)((mState & COL_TYPE_BITS) >> COL_TYPE_OFFSET);
43 }
44 
45 void
46 nsTableColFrame::SetColType(nsTableColType aType)
47 {
48   NS_ASSERTION(aType != eColAnonymousCol ||
49                (GetPrevContinuation() &&
50                 GetPrevContinuation()->GetNextContinuation() == this &&
51                 GetPrevContinuation()->GetNextSibling() == this),
52                "spanned content cols must be continuations");
53   uint32_t type = aType - eColContent;
54   RemoveStateBits(COL_TYPE_BITS);
55   AddStateBits(nsFrameState(type << COL_TYPE_OFFSET));
56 }
57 
58 /* virtual */ void
59 nsTableColFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
60 {
61   nsSplittableFrame::DidSetStyleContext(aOldStyleContext);
62 
63   if (!aOldStyleContext) //avoid this on init
64     return;
65 
66   nsTableFrame* tableFrame = GetTableFrame();
67   if (tableFrame->IsBorderCollapse() &&
68       tableFrame->BCRecalcNeeded(aOldStyleContext, StyleContext())) {
69     TableArea damageArea(GetColIndex(), 0, 1, tableFrame->GetRowCount());
70     tableFrame->AddBCDamageArea(damageArea);
71   }
72 }
73 
74 void nsTableColFrame::SetContinuousBCBorderWidth(LogicalSide aForSide,
75                                                  BCPixelSize aPixelValue)
76 {
77   switch (aForSide) {
78     case eLogicalSideBStart:
79       mBStartContBorderWidth = aPixelValue;
80       return;
81     case eLogicalSideIEnd:
82       mIEndContBorderWidth = aPixelValue;
83       return;
84     case eLogicalSideBEnd:
85       mBEndContBorderWidth = aPixelValue;
86       return;
87     default:
88       NS_ERROR("invalid side arg");
89   }
90 }
91 
92 void
93 nsTableColFrame::Reflow(nsPresContext*          aPresContext,
94                                   ReflowOutput&     aDesiredSize,
95                                   const ReflowInput& aReflowInput,
96                                   nsReflowStatus&          aStatus)
97 {
98   MarkInReflow();
99   DO_GLOBAL_REFLOW_COUNT("nsTableColFrame");
100   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
101   aDesiredSize.ClearSize();
102   const nsStyleVisibility* colVis = StyleVisibility();
103   bool collapseCol = (NS_STYLE_VISIBILITY_COLLAPSE == colVis->mVisible);
104   if (collapseCol) {
105     GetTableFrame()->SetNeedToCollapse(true);
106   }
107   aStatus = NS_FRAME_COMPLETE;
108   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
109 }
110 
111 int32_t nsTableColFrame::GetSpan()
112 {
113   return StyleTable()->mSpan;
114 }
115 
116 #ifdef DEBUG
117 void nsTableColFrame::Dump(int32_t aIndent)
118 {
119   char* indent = new char[aIndent + 1];
120   if (!indent) return;
121   for (int32_t i = 0; i < aIndent + 1; i++) {
122     indent[i] = ' ';
123   }
124   indent[aIndent] = 0;
125 
126   printf("%s**START COL DUMP**\n%s colIndex=%d coltype=",
127     indent, indent, mColIndex);
128   nsTableColType colType = GetColType();
129   switch (colType) {
130   case eColContent:
131     printf(" content ");
132     break;
133   case eColAnonymousCol:
134     printf(" anonymous-column ");
135     break;
136   case eColAnonymousColGroup:
137     printf(" anonymous-colgroup ");
138     break;
139   case eColAnonymousCell:
140     printf(" anonymous-cell ");
141     break;
142   }
143   printf("\nm:%d c:%d(%c) p:%f sm:%d sc:%d sp:%f f:%d",
144          int32_t(mMinCoord), int32_t(mPrefCoord),
145          mHasSpecifiedCoord ? 's' : 'u', mPrefPercent,
146          int32_t(mSpanMinCoord), int32_t(mSpanPrefCoord),
147          mSpanPrefPercent,
148          int32_t(GetFinalISize()));
149   printf("\n%s**END COL DUMP** ", indent);
150   delete [] indent;
151 }
152 #endif
153 /* ----- global methods ----- */
154 
155 nsTableColFrame*
156 NS_NewTableColFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
157 {
158   return new (aPresShell) nsTableColFrame(aContext);
159 }
160 
161 NS_IMPL_FRAMEARENA_HELPERS(nsTableColFrame)
162 
163 nsTableColFrame*
164 nsTableColFrame::GetNextCol() const
165 {
166   nsIFrame* childFrame = GetNextSibling();
167   while (childFrame) {
168     if (nsGkAtoms::tableColFrame == childFrame->GetType()) {
169       return (nsTableColFrame*)childFrame;
170     }
171     childFrame = childFrame->GetNextSibling();
172   }
173   return nullptr;
174 }
175 
176 nsIAtom*
177 nsTableColFrame::GetType() const
178 {
179   return nsGkAtoms::tableColFrame;
180 }
181 
182 #ifdef DEBUG_FRAME_DUMP
183 nsresult
184 nsTableColFrame::GetFrameName(nsAString& aResult) const
185 {
186   return MakeFrameName(NS_LITERAL_STRING("TableCol"), aResult);
187 }
188 #endif
189 
190 nsSplittableType
191 nsTableColFrame::GetSplittableType() const
192 {
193   return NS_FRAME_NOT_SPLITTABLE;
194 }
195 
196 void
197 nsTableColFrame::InvalidateFrame(uint32_t aDisplayItemKey)
198 {
199   nsIFrame::InvalidateFrame(aDisplayItemKey);
200   GetParent()->InvalidateFrameWithRect(GetVisualOverflowRect() + GetPosition(), aDisplayItemKey);
201 }
202 
203 void
204 nsTableColFrame::InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey)
205 {
206   nsIFrame::InvalidateFrameWithRect(aRect, aDisplayItemKey);
207 
208   // If we have filters applied that would affects our bounds, then
209   // we get an inactive layer created and this is computed
210   // within FrameLayerBuilder
211   GetParent()->InvalidateFrameWithRect(aRect + GetPosition(), aDisplayItemKey);
212 }
213 
214