/src/mozilla-central/layout/style/ComputedStyle.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | /* the interface (to internal code) for retrieving computed style data */ |
8 | | |
9 | | #include "mozilla/ComputedStyle.h" |
10 | | #include "mozilla/DebugOnly.h" |
11 | | #include "mozilla/Maybe.h" |
12 | | |
13 | | #include "nsCSSAnonBoxes.h" |
14 | | #include "nsCSSPseudoElements.h" |
15 | | #include "nsFontMetrics.h" |
16 | | #include "nsStyleConsts.h" |
17 | | #include "nsStyleStruct.h" |
18 | | #include "nsStyleStructInlines.h" |
19 | | #include "nsString.h" |
20 | | #include "nsPresContext.h" |
21 | | #include "nsWindowSizes.h" |
22 | | |
23 | | #include "nsCOMPtr.h" |
24 | | #include "nsIPresShell.h" |
25 | | |
26 | | #include "GeckoProfiler.h" |
27 | | #include "nsIDocument.h" |
28 | | #include "nsPrintfCString.h" |
29 | | #include "RubyUtils.h" |
30 | | #include "mozilla/ArenaObjectID.h" |
31 | | #include "mozilla/ComputedStyleInlines.h" |
32 | | #include "mozilla/Preferences.h" |
33 | | |
34 | | #include "mozilla/ReflowInput.h" |
35 | | #include "nsLayoutUtils.h" |
36 | | #include "nsCoord.h" |
37 | | |
38 | | // Ensure the binding function declarations in ComputedStyle.h matches |
39 | | // those in ServoBindings.h. |
40 | | #include "mozilla/ServoBindings.h" |
41 | | |
42 | | namespace mozilla { |
43 | | |
44 | | //---------------------------------------------------------------------- |
45 | | |
46 | | ComputedStyle::ComputedStyle(nsPresContext* aPresContext, |
47 | | nsAtom* aPseudoTag, |
48 | | CSSPseudoElementType aPseudoType, |
49 | | ServoComputedDataForgotten aComputedValues) |
50 | | : mPresContext(aPresContext) |
51 | | , mSource(aComputedValues) |
52 | | , mPseudoTag(aPseudoTag) |
53 | | , mBits(static_cast<Bit>(Servo_ComputedValues_GetStyleBits(this))) |
54 | | , mPseudoType(aPseudoType) |
55 | 0 | { |
56 | 0 | MOZ_ASSERT(ComputedData()); |
57 | 0 | } |
58 | | |
59 | | nsChangeHint |
60 | | ComputedStyle::CalcStyleDifference(ComputedStyle* aNewContext, |
61 | | uint32_t* aEqualStructs) |
62 | 0 | { |
63 | 0 | MOZ_ASSERT(aNewContext); |
64 | 0 | AUTO_PROFILER_LABEL("ComputedStyle::CalcStyleDifference", LAYOUT); |
65 | 0 | static_assert(StyleStructConstants::kStyleStructCount <= 32, |
66 | 0 | "aEqualStructs is not big enough"); |
67 | 0 |
|
68 | 0 | *aEqualStructs = 0; |
69 | 0 |
|
70 | 0 | nsChangeHint hint = nsChangeHint(0); |
71 | 0 | // We must always ensure that we populate the structs on the new style |
72 | 0 | // context that are filled in on the old context, so that if we get |
73 | 0 | // two style changes in succession, the second of which causes a real |
74 | 0 | // style change, the PeekStyleData doesn't return null (implying that |
75 | 0 | // nobody ever looked at that struct's data). In other words, we |
76 | 0 | // can't skip later structs if we get a big change up front, because |
77 | 0 | // we could later get a small change in one of those structs that we |
78 | 0 | // don't want to miss. |
79 | 0 |
|
80 | 0 | DebugOnly<uint32_t> structsFound = 0; |
81 | 0 |
|
82 | 0 | DebugOnly<int> styleStructCount = 0; |
83 | 0 |
|
84 | 0 | // Servo's optimization to stop the cascade when there are no style changes |
85 | 0 | // that children need to be recascade for relies on comparing all of the |
86 | 0 | // structs, not just those that are returned from PeekStyleData, although |
87 | 0 | // if PeekStyleData does return null we could avoid to accumulate any change |
88 | 0 | // hints for those structs. |
89 | 0 | // |
90 | 0 | // FIXME(emilio): Reintroduce that optimization either for all kind of structs |
91 | 0 | // after bug 1368290 with a weak parent pointer from text, or just for reset |
92 | 0 | // structs. |
93 | 0 | #define STYLE_STRUCT_BIT(name_) \ |
94 | 0 | StyleStructConstants::BitFor(StyleStructID::name_) |
95 | 0 | #define PEEK(struct_) \ |
96 | 0 | ComputedData()->GetStyle##struct_() |
97 | 0 |
|
98 | 0 | #define EXPAND(...) __VA_ARGS__ |
99 | 0 | #define DO_STRUCT_DIFFERENCE_WITH_ARGS(struct_, extra_args_) \ |
100 | 0 | PR_BEGIN_MACRO \ |
101 | 0 | const nsStyle##struct_* this##struct_ = PEEK(struct_); \ |
102 | 0 | if (this##struct_) { \ |
103 | 0 | structsFound |= STYLE_STRUCT_BIT(struct_); \ |
104 | 0 | \ |
105 | 0 | const nsStyle##struct_* other##struct_ = \ |
106 | 0 | aNewContext->ThreadsafeStyle##struct_(); \ |
107 | 0 | if (this##struct_ == other##struct_) { \ |
108 | 0 | /* The very same struct, so we know that there will be no */ \ |
109 | 0 | /* differences. */ \ |
110 | 0 | *aEqualStructs |= STYLE_STRUCT_BIT(struct_); \ |
111 | 0 | } else { \ |
112 | 0 | nsChangeHint difference = \ |
113 | 0 | this##struct_->CalcDifference(*other##struct_ EXPAND extra_args_); \ |
114 | 0 | hint |= difference; \ |
115 | 0 | if (!difference) { \ |
116 | 0 | *aEqualStructs |= STYLE_STRUCT_BIT(struct_); \ |
117 | 0 | } \ |
118 | 0 | } \ |
119 | 0 | } else { \ |
120 | 0 | *aEqualStructs |= STYLE_STRUCT_BIT(struct_); \ |
121 | 0 | } \ |
122 | 0 | styleStructCount++; \ |
123 | 0 | PR_END_MACRO |
124 | 0 | #define DO_STRUCT_DIFFERENCE(struct_) \ |
125 | 0 | DO_STRUCT_DIFFERENCE_WITH_ARGS(struct_, ()) |
126 | 0 |
|
127 | 0 | // FIXME: The order of these DO_STRUCT_DIFFERENCE calls is no longer |
128 | 0 | // significant. With a small amount of effort, we could replace them with a |
129 | 0 | // #include "nsStyleStructList.h". |
130 | 0 | DO_STRUCT_DIFFERENCE(Display); |
131 | 0 | DO_STRUCT_DIFFERENCE(XUL); |
132 | 0 | DO_STRUCT_DIFFERENCE(Column); |
133 | 0 | DO_STRUCT_DIFFERENCE(Content); |
134 | 0 | DO_STRUCT_DIFFERENCE(UI); |
135 | 0 | DO_STRUCT_DIFFERENCE(Visibility); |
136 | 0 | DO_STRUCT_DIFFERENCE(Outline); |
137 | 0 | DO_STRUCT_DIFFERENCE(TableBorder); |
138 | 0 | DO_STRUCT_DIFFERENCE(Table); |
139 | 0 | DO_STRUCT_DIFFERENCE(UIReset); |
140 | 0 | DO_STRUCT_DIFFERENCE(Text); |
141 | 0 | DO_STRUCT_DIFFERENCE_WITH_ARGS(List, (, PEEK(Display))); |
142 | 0 | DO_STRUCT_DIFFERENCE(SVGReset); |
143 | 0 | DO_STRUCT_DIFFERENCE(SVG); |
144 | 0 | DO_STRUCT_DIFFERENCE_WITH_ARGS(Position, (, PEEK(Visibility))); |
145 | 0 | DO_STRUCT_DIFFERENCE(Font); |
146 | 0 | DO_STRUCT_DIFFERENCE(Margin); |
147 | 0 | DO_STRUCT_DIFFERENCE(Padding); |
148 | 0 | DO_STRUCT_DIFFERENCE(Border); |
149 | 0 | DO_STRUCT_DIFFERENCE(TextReset); |
150 | 0 | DO_STRUCT_DIFFERENCE(Effects); |
151 | 0 | DO_STRUCT_DIFFERENCE(Background); |
152 | 0 | DO_STRUCT_DIFFERENCE(Color); |
153 | 0 |
|
154 | 0 | #undef DO_STRUCT_DIFFERENCE |
155 | 0 | #undef DO_STRUCT_DIFFERENCE_WITH_ARGS |
156 | 0 | #undef EXPAND |
157 | 0 |
|
158 | 0 | MOZ_ASSERT(styleStructCount == StyleStructConstants::kStyleStructCount, |
159 | 0 | "missing a call to DO_STRUCT_DIFFERENCE"); |
160 | 0 |
|
161 | | #ifdef DEBUG |
162 | | #define STYLE_STRUCT(name_) \ |
163 | | MOZ_ASSERT(!!(structsFound & STYLE_STRUCT_BIT(name_)) == \ |
164 | | (PEEK(name_) != nullptr), \ |
165 | | "PeekStyleData results must not change in the middle of " \ |
166 | | "difference calculation."); |
167 | | #include "nsStyleStructList.h" |
168 | | #undef STYLE_STRUCT |
169 | | #endif |
170 | |
|
171 | 0 | // Note that we do not check whether this->RelevantLinkVisited() != |
172 | 0 | // aNewContext->RelevantLinkVisited(); we don't need to since |
173 | 0 | // nsCSSFrameConstructor::DoContentStateChanged always adds |
174 | 0 | // nsChangeHint_RepaintFrame for NS_EVENT_STATE_VISITED changes (and |
175 | 0 | // needs to, since HasStateDependentStyle probably doesn't work right |
176 | 0 | // for NS_EVENT_STATE_VISITED). Hopefully this doesn't actually |
177 | 0 | // expose whether links are visited to performance tests since all |
178 | 0 | // link coloring happens asynchronously at a time when it's hard for |
179 | 0 | // the page to measure. |
180 | 0 | // However, we do need to compute the larger of the changes that can |
181 | 0 | // happen depending on whether the link is visited or unvisited, since |
182 | 0 | // doing only the one that's currently appropriate would expose which |
183 | 0 | // links are in history to easy performance measurement. Therefore, |
184 | 0 | // here, we add nsChangeHint_RepaintFrame hints (the maximum for |
185 | 0 | // things that can depend on :visited) for the properties on which we |
186 | 0 | // call GetVisitedDependentColor. |
187 | 0 | ComputedStyle* thisVis = GetStyleIfVisited(); |
188 | 0 | ComputedStyle* otherVis = aNewContext->GetStyleIfVisited(); |
189 | 0 | if (!thisVis != !otherVis) { |
190 | 0 | // One style has a style-if-visited and the other doesn't. |
191 | 0 | // Presume a difference. |
192 | 0 | #define STYLE_STRUCT(name_, fields_) \ |
193 | 0 | *aEqualStructs &= ~STYLE_STRUCT_BIT(name_); |
194 | 0 | #include "nsCSSVisitedDependentPropList.h" |
195 | 0 | #undef STYLE_STRUCT |
196 | 0 | hint |= nsChangeHint_RepaintFrame; |
197 | 0 | } else if (thisVis) { |
198 | 0 | // Both styles have a style-if-visited. |
199 | 0 | bool change = false; |
200 | 0 |
|
201 | 0 | // NB: Calling Peek on |this|, not |thisVis|, since callers may look |
202 | 0 | // at a struct on |this| without looking at the same struct on |
203 | 0 | // |thisVis| (including this function if we skip one of these checks |
204 | 0 | // due to change being true already or due to the old style not having a |
205 | 0 | // style-if-visited), but not the other way around. |
206 | 0 | #define STYLE_FIELD(name_) thisVisStruct->name_ != otherVisStruct->name_ |
207 | 0 | #define STYLE_STRUCT(name_, fields_) \ |
208 | 0 | if (PEEK(name_)) { \ |
209 | 0 | const nsStyle##name_* thisVisStruct = \ |
210 | 0 | thisVis->ThreadsafeStyle##name_(); \ |
211 | 0 | const nsStyle##name_* otherVisStruct = \ |
212 | 0 | otherVis->ThreadsafeStyle##name_(); \ |
213 | 0 | if (MOZ_FOR_EACH_SEPARATED(STYLE_FIELD, (||), (), fields_)) { \ |
214 | 0 | *aEqualStructs &= ~STYLE_STRUCT_BIT(name_); \ |
215 | 0 | change = true; \ |
216 | 0 | } \ |
217 | 0 | } |
218 | 0 | #include "nsCSSVisitedDependentPropList.h" |
219 | 0 | #undef STYLE_STRUCT |
220 | 0 | #undef STYLE_FIELD |
221 | 0 | #undef STYLE_STRUCT_BIT |
222 | 0 |
|
223 | 0 | if (change) { |
224 | 0 | hint |= nsChangeHint_RepaintFrame; |
225 | 0 | } |
226 | 0 | } |
227 | 0 |
|
228 | 0 | if (hint & nsChangeHint_UpdateContainingBlock) { |
229 | 0 | // If a struct returned nsChangeHint_UpdateContainingBlock, that |
230 | 0 | // means that one property's influence on whether we're a containing |
231 | 0 | // block for abs-pos or fixed-pos elements has changed. However, we |
232 | 0 | // only need to return the hint if the overall computation of |
233 | 0 | // whether we establish a containing block has changed. |
234 | 0 |
|
235 | 0 | // This depends on data in nsStyleDisplay and nsStyleEffects, so we do it |
236 | 0 | // here |
237 | 0 |
|
238 | 0 | // Note that it's perhaps good for this test to be last because it |
239 | 0 | // doesn't use Peek* functions to get the structs on the old |
240 | 0 | // context. But this isn't a big concern because these struct |
241 | 0 | // getters should be called during frame construction anyway. |
242 | 0 | const nsStyleDisplay* oldDisp = ThreadsafeStyleDisplay(); |
243 | 0 | const nsStyleDisplay* newDisp = aNewContext->ThreadsafeStyleDisplay(); |
244 | 0 | bool isFixedCB; |
245 | 0 | if (oldDisp->IsAbsPosContainingBlockForNonSVGTextFrames() == |
246 | 0 | newDisp->IsAbsPosContainingBlockForNonSVGTextFrames() && |
247 | 0 | (isFixedCB = |
248 | 0 | oldDisp->IsFixedPosContainingBlockForNonSVGTextFrames(*this)) == |
249 | 0 | newDisp->IsFixedPosContainingBlockForNonSVGTextFrames(*aNewContext) && |
250 | 0 | // transform-supporting frames are a subcategory of non-SVG-text |
251 | 0 | // frames, so no need to test this if isFixedCB is true (both |
252 | 0 | // before and after the change) |
253 | 0 | (isFixedCB || |
254 | 0 | oldDisp->IsFixedPosContainingBlockForTransformSupportingFrames() == |
255 | 0 | newDisp->IsFixedPosContainingBlockForTransformSupportingFrames()) && |
256 | 0 | // contain-layout-and-paint-supporting frames are a subset of |
257 | 0 | // non-SVG-text frames, so no need to test this if isFixedCB is true |
258 | 0 | // (both before and after the change). |
259 | 0 | // |
260 | 0 | // Note, however, that neither of these last two sets is a |
261 | 0 | // subset of the other, because table frames support contain: |
262 | 0 | // layout/paint but not transforms (which are instead inherited |
263 | 0 | // to the table wrapper), and quite a few frame types support |
264 | 0 | // transforms but not contain: layout/paint (e.g., table rows |
265 | 0 | // and row groups, many SVG frames). |
266 | 0 | (isFixedCB || |
267 | 0 | oldDisp->IsFixedPosContainingBlockForContainLayoutAndPaintSupportingFrames() == |
268 | 0 | newDisp->IsFixedPosContainingBlockForContainLayoutAndPaintSupportingFrames())) { |
269 | 0 | // While some styles that cause the frame to be a containing block |
270 | 0 | // has changed, the overall result cannot have changed (no matter |
271 | 0 | // what the frame type is). |
272 | 0 | hint &= ~nsChangeHint_UpdateContainingBlock; |
273 | 0 | } |
274 | 0 | } |
275 | 0 |
|
276 | 0 | MOZ_ASSERT(NS_IsHintSubset(hint, nsChangeHint_AllHints), |
277 | 0 | "Added a new hint without bumping AllHints?"); |
278 | 0 | return hint & ~nsChangeHint_NeutralChange; |
279 | 0 | } |
280 | | |
281 | | #ifdef DEBUG |
282 | | void ComputedStyle::List(FILE* out, int32_t aIndent) |
283 | | { |
284 | | nsAutoCString str; |
285 | | // Indent |
286 | | int32_t ix; |
287 | | for (ix = aIndent; --ix >= 0; ) { |
288 | | str.AppendLiteral(" "); |
289 | | } |
290 | | str.Append(nsPrintfCString("%p(%d) parent=%p ", |
291 | | (void*)this, |
292 | | 0, nullptr |
293 | | )); |
294 | | if (mPseudoTag) { |
295 | | nsAutoString buffer; |
296 | | mPseudoTag->ToString(buffer); |
297 | | AppendUTF16toUTF8(buffer, str); |
298 | | str.Append(' '); |
299 | | } |
300 | | |
301 | | fprintf_stderr(out, "%s{ServoComputedData}\n", str.get()); |
302 | | } |
303 | | #endif |
304 | | |
305 | | |
306 | | nsIPresShell* |
307 | | ComputedStyle::Arena() |
308 | 0 | { |
309 | 0 | return mPresContext->PresShell(); |
310 | 0 | } |
311 | | |
312 | | template<typename Func> |
313 | | static nscolor |
314 | | GetVisitedDependentColorInternal(ComputedStyle* aSc, Func aColorFunc) |
315 | 0 | { |
316 | 0 | nscolor colors[2]; |
317 | 0 | colors[0] = aColorFunc(aSc); |
318 | 0 | if (ComputedStyle* visitedStyle = aSc->GetStyleIfVisited()) { |
319 | 0 | colors[1] = aColorFunc(visitedStyle); |
320 | 0 | return ComputedStyle:: |
321 | 0 | CombineVisitedColors(colors, aSc->RelevantLinkVisited()); |
322 | 0 | } |
323 | 0 | return colors[0]; |
324 | 0 | } Unexecuted instantiation: Unified_cpp_layout_style1.cpp:unsigned int mozilla::GetVisitedDependentColorInternal<unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<unsigned int, nsStyleColor>(unsigned int nsStyleColor::*)::$_0>(mozilla::ComputedStyle*, unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<unsigned int, nsStyleColor>(unsigned int nsStyleColor::*)::$_0) Unexecuted instantiation: Unified_cpp_layout_style1.cpp:unsigned int mozilla::GetVisitedDependentColorInternal<unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleBackground>(mozilla::StyleComplexColor nsStyleBackground::*)::$_1>(mozilla::ComputedStyle*, unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleBackground>(mozilla::StyleComplexColor nsStyleBackground::*)::$_1) Unexecuted instantiation: Unified_cpp_layout_style1.cpp:unsigned int mozilla::GetVisitedDependentColorInternal<unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleBorder>(mozilla::StyleComplexColor nsStyleBorder::*)::$_2>(mozilla::ComputedStyle*, unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleBorder>(mozilla::StyleComplexColor nsStyleBorder::*)::$_2) Unexecuted instantiation: Unified_cpp_layout_style1.cpp:unsigned int mozilla::GetVisitedDependentColorInternal<unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleOutline>(mozilla::StyleComplexColor nsStyleOutline::*)::$_3>(mozilla::ComputedStyle*, unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleOutline>(mozilla::StyleComplexColor nsStyleOutline::*)::$_3) Unexecuted instantiation: Unified_cpp_layout_style1.cpp:unsigned int mozilla::GetVisitedDependentColorInternal<unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleColumn>(mozilla::StyleComplexColor nsStyleColumn::*)::$_4>(mozilla::ComputedStyle*, unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleColumn>(mozilla::StyleComplexColor nsStyleColumn::*)::$_4) Unexecuted instantiation: Unified_cpp_layout_style1.cpp:unsigned int mozilla::GetVisitedDependentColorInternal<unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleText>(mozilla::StyleComplexColor nsStyleText::*)::$_5>(mozilla::ComputedStyle*, unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleText>(mozilla::StyleComplexColor nsStyleText::*)::$_5) Unexecuted instantiation: Unified_cpp_layout_style1.cpp:unsigned int mozilla::GetVisitedDependentColorInternal<unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleTextReset>(mozilla::StyleComplexColor nsStyleTextReset::*)::$_6>(mozilla::ComputedStyle*, unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleTextReset>(mozilla::StyleComplexColor nsStyleTextReset::*)::$_6) Unexecuted instantiation: Unified_cpp_layout_style1.cpp:unsigned int mozilla::GetVisitedDependentColorInternal<unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<nsStyleSVGPaint, nsStyleSVG>(nsStyleSVGPaint nsStyleSVG::*)::$_7>(mozilla::ComputedStyle*, unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<nsStyleSVGPaint, nsStyleSVG>(nsStyleSVGPaint nsStyleSVG::*)::$_7) Unexecuted instantiation: Unified_cpp_layout_style1.cpp:unsigned int mozilla::GetVisitedDependentColorInternal<unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleUI>(mozilla::StyleComplexColor nsStyleUI::*)::$_8>(mozilla::ComputedStyle*, unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleUI>(mozilla::StyleComplexColor nsStyleUI::*)::$_8) |
325 | | |
326 | | static nscolor |
327 | | ExtractColor(ComputedStyle* aStyle, const nscolor& aColor) |
328 | 0 | { |
329 | 0 | return aColor; |
330 | 0 | } |
331 | | |
332 | | static nscolor |
333 | | ExtractColor(ComputedStyle* aStyle, const StyleComplexColor& aColor) |
334 | 0 | { |
335 | 0 | return aColor.CalcColor(aStyle); |
336 | 0 | } |
337 | | |
338 | | static nscolor |
339 | | ExtractColor(ComputedStyle* aStyle, const nsStyleSVGPaint& aPaintServer) |
340 | 0 | { |
341 | 0 | return aPaintServer.Type() == eStyleSVGPaintType_Color |
342 | 0 | ? aPaintServer.GetColor(aStyle) : NS_RGBA(0, 0, 0, 0); |
343 | 0 | } |
344 | | |
345 | | #define STYLE_FIELD(struct_, field_) aField == &struct_::field_ || |
346 | | #define STYLE_STRUCT(name_, fields_) \ |
347 | | template<> nscolor \ |
348 | | ComputedStyle::GetVisitedDependentColor( \ |
349 | | decltype(nsStyle##name_::MOZ_ARG_1 fields_) nsStyle##name_::* aField) \ |
350 | 0 | { \ |
351 | 0 | MOZ_ASSERT(MOZ_FOR_EACH(STYLE_FIELD, (nsStyle##name_,), fields_) false, \ |
352 | 0 | "Getting visited-dependent color for a field in nsStyle"#name_ \ |
353 | 0 | " which is not listed in nsCSSVisitedDependentPropList.h"); \ |
354 | 0 | return GetVisitedDependentColorInternal(this, \ |
355 | 0 | [aField](ComputedStyle* sc) { \ |
356 | 0 | return ExtractColor(sc, sc->Style##name_()->*aField); \ |
357 | 0 | }); \ Unexecuted instantiation: Unified_cpp_layout_style1.cpp:unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<unsigned int, nsStyleColor>(unsigned int nsStyleColor::*)::$_0::operator()(mozilla::ComputedStyle*) const Unexecuted instantiation: Unified_cpp_layout_style1.cpp:unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleBackground>(mozilla::StyleComplexColor nsStyleBackground::*)::$_1::operator()(mozilla::ComputedStyle*) const Unexecuted instantiation: Unified_cpp_layout_style1.cpp:unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleBorder>(mozilla::StyleComplexColor nsStyleBorder::*)::$_2::operator()(mozilla::ComputedStyle*) const Unexecuted instantiation: Unified_cpp_layout_style1.cpp:unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleOutline>(mozilla::StyleComplexColor nsStyleOutline::*)::$_3::operator()(mozilla::ComputedStyle*) const Unexecuted instantiation: Unified_cpp_layout_style1.cpp:unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleColumn>(mozilla::StyleComplexColor nsStyleColumn::*)::$_4::operator()(mozilla::ComputedStyle*) const Unexecuted instantiation: Unified_cpp_layout_style1.cpp:unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleText>(mozilla::StyleComplexColor nsStyleText::*)::$_5::operator()(mozilla::ComputedStyle*) const Unexecuted instantiation: Unified_cpp_layout_style1.cpp:unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleTextReset>(mozilla::StyleComplexColor nsStyleTextReset::*)::$_6::operator()(mozilla::ComputedStyle*) const Unexecuted instantiation: Unified_cpp_layout_style1.cpp:unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<nsStyleSVGPaint, nsStyleSVG>(nsStyleSVGPaint nsStyleSVG::*)::$_7::operator()(mozilla::ComputedStyle*) const Unexecuted instantiation: Unified_cpp_layout_style1.cpp:unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleUI>(mozilla::StyleComplexColor nsStyleUI::*)::$_8::operator()(mozilla::ComputedStyle*) const |
358 | 0 | } Unexecuted instantiation: unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<unsigned int, nsStyleColor>(unsigned int nsStyleColor::*) Unexecuted instantiation: unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleBackground>(mozilla::StyleComplexColor nsStyleBackground::*) Unexecuted instantiation: unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleBorder>(mozilla::StyleComplexColor nsStyleBorder::*) Unexecuted instantiation: unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleOutline>(mozilla::StyleComplexColor nsStyleOutline::*) Unexecuted instantiation: unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleColumn>(mozilla::StyleComplexColor nsStyleColumn::*) Unexecuted instantiation: unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleText>(mozilla::StyleComplexColor nsStyleText::*) Unexecuted instantiation: unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleTextReset>(mozilla::StyleComplexColor nsStyleTextReset::*) Unexecuted instantiation: unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<nsStyleSVGPaint, nsStyleSVG>(nsStyleSVGPaint nsStyleSVG::*) Unexecuted instantiation: unsigned int mozilla::ComputedStyle::GetVisitedDependentColor<mozilla::StyleComplexColor, nsStyleUI>(mozilla::StyleComplexColor nsStyleUI::*) |
359 | | #include "nsCSSVisitedDependentPropList.h" |
360 | | #undef STYLE_STRUCT |
361 | | #undef STYLE_FIELD |
362 | | |
363 | | struct ColorIndexSet { |
364 | | uint8_t colorIndex, alphaIndex; |
365 | | }; |
366 | | |
367 | | static const ColorIndexSet gVisitedIndices[2] = { { 0, 0 }, { 1, 0 } }; |
368 | | |
369 | | /* static */ nscolor |
370 | | ComputedStyle::CombineVisitedColors(nscolor *aColors, bool aLinkIsVisited) |
371 | 0 | { |
372 | 0 | if (NS_GET_A(aColors[1]) == 0) { |
373 | 0 | // If the style-if-visited is transparent, then just use the |
374 | 0 | // unvisited style rather than using the (meaningless) color |
375 | 0 | // components of the visited style along with a potentially |
376 | 0 | // non-transparent alpha value. |
377 | 0 | aLinkIsVisited = false; |
378 | 0 | } |
379 | 0 |
|
380 | 0 | // NOTE: We want this code to have as little timing dependence as |
381 | 0 | // possible on whether this->RelevantLinkVisited() is true. |
382 | 0 | const ColorIndexSet &set = |
383 | 0 | gVisitedIndices[aLinkIsVisited ? 1 : 0]; |
384 | 0 |
|
385 | 0 | nscolor colorColor = aColors[set.colorIndex]; |
386 | 0 | nscolor alphaColor = aColors[set.alphaIndex]; |
387 | 0 | return NS_RGBA(NS_GET_R(colorColor), NS_GET_G(colorColor), |
388 | 0 | NS_GET_B(colorColor), NS_GET_A(alphaColor)); |
389 | 0 | } |
390 | | |
391 | | #ifdef DEBUG |
392 | | /* static */ const char* |
393 | | ComputedStyle::StructName(StyleStructID aSID) |
394 | | { |
395 | | switch (aSID) { |
396 | | #define STYLE_STRUCT(name_) \ |
397 | | case StyleStructID::name_: \ |
398 | | return #name_; |
399 | | #include "nsStyleStructList.h" |
400 | | #undef STYLE_STRUCT |
401 | | default: |
402 | | return "Unknown"; |
403 | | } |
404 | | } |
405 | | |
406 | | /* static */ Maybe<StyleStructID> |
407 | | ComputedStyle::LookupStruct(const nsACString& aName) |
408 | | { |
409 | | #define STYLE_STRUCT(name_) \ |
410 | | if (aName.EqualsLiteral(#name_)) \ |
411 | | return Some(StyleStructID::name_); |
412 | | #include "nsStyleStructList.h" |
413 | | #undef STYLE_STRUCT |
414 | | return Nothing(); |
415 | | } |
416 | | #endif // DEBUG |
417 | | |
418 | | ComputedStyle* |
419 | | ComputedStyle::GetCachedLazyPseudoStyle(CSSPseudoElementType aPseudo) const |
420 | 0 | { |
421 | 0 | MOZ_ASSERT(aPseudo != CSSPseudoElementType::NotPseudo && |
422 | 0 | aPseudo != CSSPseudoElementType::InheritingAnonBox && |
423 | 0 | aPseudo != CSSPseudoElementType::NonInheritingAnonBox); |
424 | 0 | MOZ_ASSERT(!IsLazilyCascadedPseudoElement(), "Lazy pseudos can't inherit lazy pseudos"); |
425 | 0 |
|
426 | 0 | if (nsCSSPseudoElements::PseudoElementSupportsUserActionState(aPseudo)) { |
427 | 0 | return nullptr; |
428 | 0 | } |
429 | 0 | |
430 | 0 | return mCachedInheritingStyles.Lookup(nsCSSPseudoElements::GetPseudoAtom(aPseudo)); |
431 | 0 | } |
432 | | |
433 | | MOZ_DEFINE_MALLOC_ENCLOSING_SIZE_OF(ServoComputedValuesMallocEnclosingSizeOf) |
434 | | |
435 | | void |
436 | | ComputedStyle::AddSizeOfIncludingThis(nsWindowSizes& aSizes, |
437 | | size_t* aCVsSize) const |
438 | 0 | { |
439 | 0 | // Note: |this| sits within a servo_arc::Arc, i.e. it is preceded by a |
440 | 0 | // refcount. So we need to measure it with a function that can handle an |
441 | 0 | // interior pointer. We use ServoComputedValuesMallocEnclosingSizeOf to |
442 | 0 | // clearly identify in DMD's output the memory measured here. |
443 | 0 | *aCVsSize += ServoComputedValuesMallocEnclosingSizeOf(this); |
444 | 0 | mSource.AddSizeOfExcludingThis(aSizes); |
445 | 0 | mCachedInheritingStyles.AddSizeOfIncludingThis(aSizes, aCVsSize); |
446 | 0 | } |
447 | | |
448 | | } // namespace mozilla |