/src/mozilla-central/layout/painting/DisplayListClipState.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 | | #include "DisplayListClipState.h" |
8 | | |
9 | | #include "nsDisplayList.h" |
10 | | |
11 | | namespace mozilla { |
12 | | |
13 | | const DisplayItemClipChain* |
14 | | DisplayListClipState::GetCurrentCombinedClipChain( |
15 | | nsDisplayListBuilder* aBuilder) |
16 | 0 | { |
17 | 0 | if (mCurrentCombinedClipChainIsValid) { |
18 | 0 | return mCurrentCombinedClipChain; |
19 | 0 | } |
20 | 0 | if (!mClipChainContentDescendants && !mClipChainContainingBlockDescendants) { |
21 | 0 | mCurrentCombinedClipChain = nullptr; |
22 | 0 | mCurrentCombinedClipChainIsValid = true; |
23 | 0 | return nullptr; |
24 | 0 | } |
25 | 0 | |
26 | 0 | mCurrentCombinedClipChain = |
27 | 0 | aBuilder->CreateClipChainIntersection(mCurrentCombinedClipChain, |
28 | 0 | mClipChainContentDescendants, |
29 | 0 | mClipChainContainingBlockDescendants); |
30 | 0 | mCurrentCombinedClipChainIsValid = true; |
31 | 0 | return mCurrentCombinedClipChain; |
32 | 0 | } |
33 | | |
34 | | static void |
35 | | ApplyClip(nsDisplayListBuilder* aBuilder, |
36 | | const DisplayItemClipChain*& aClipToModify, |
37 | | const ActiveScrolledRoot* aASR, |
38 | | DisplayItemClipChain& aClipChainOnStack) |
39 | 0 | { |
40 | 0 | aClipChainOnStack.mASR = aASR; |
41 | 0 | if (aClipToModify && aClipToModify->mASR == aASR) { |
42 | 0 | // Intersect with aClipToModify and replace the clip chain item. |
43 | 0 | aClipChainOnStack.mClip.IntersectWith(aClipToModify->mClip); |
44 | 0 | aClipChainOnStack.mParent = aClipToModify->mParent; |
45 | 0 | aClipToModify = &aClipChainOnStack; |
46 | 0 | } else if (!aClipToModify || |
47 | 0 | ActiveScrolledRoot::IsAncestor(aClipToModify->mASR, aASR)) { |
48 | 0 | // Add a new clip chain item at the bottom. |
49 | 0 | aClipChainOnStack.mParent = aClipToModify; |
50 | 0 | aClipToModify = &aClipChainOnStack; |
51 | 0 | } else { |
52 | 0 | // We need to insert / intersect a DisplayItemClipChain in the middle of the |
53 | 0 | // aClipToModify chain. This is a very rare case. |
54 | 0 | // Find the common ancestor and have the builder create the |
55 | 0 | // DisplayItemClipChain intersection. This will create new |
56 | 0 | // DisplayItemClipChain objects for all descendants of ancestorSC and we |
57 | 0 | // will not hold on to a pointer to aClipChainOnStack. |
58 | 0 | const DisplayItemClipChain* ancestorSC = aClipToModify; |
59 | 0 | while (ancestorSC && |
60 | 0 | ActiveScrolledRoot::IsAncestor(aASR, ancestorSC->mASR)) { |
61 | 0 | ancestorSC = ancestorSC->mParent; |
62 | 0 | } |
63 | 0 | ancestorSC = aBuilder->CopyWholeChain(ancestorSC); |
64 | 0 | aClipChainOnStack.mParent = nullptr; |
65 | 0 | aClipToModify = aBuilder->CreateClipChainIntersection( |
66 | 0 | ancestorSC, aClipToModify, &aClipChainOnStack); |
67 | 0 | } |
68 | 0 | } |
69 | | |
70 | | void |
71 | | DisplayListClipState::ClipContainingBlockDescendants( |
72 | | nsDisplayListBuilder* aBuilder, |
73 | | const nsRect& aRect, |
74 | | const nscoord* aRadii, |
75 | | DisplayItemClipChain& aClipChainOnStack) |
76 | 0 | { |
77 | 0 | if (aRadii) { |
78 | 0 | aClipChainOnStack.mClip.SetTo(aRect, aRadii); |
79 | 0 | } else { |
80 | 0 | aClipChainOnStack.mClip.SetTo(aRect); |
81 | 0 | } |
82 | 0 | const ActiveScrolledRoot* asr = aBuilder->CurrentActiveScrolledRoot(); |
83 | 0 | ApplyClip( |
84 | 0 | aBuilder, mClipChainContainingBlockDescendants, asr, aClipChainOnStack); |
85 | 0 | InvalidateCurrentCombinedClipChain(asr); |
86 | 0 | } |
87 | | |
88 | | void |
89 | | DisplayListClipState::ClipContentDescendants( |
90 | | nsDisplayListBuilder* aBuilder, |
91 | | const nsRect& aRect, |
92 | | const nscoord* aRadii, |
93 | | DisplayItemClipChain& aClipChainOnStack) |
94 | 0 | { |
95 | 0 | if (aRadii) { |
96 | 0 | aClipChainOnStack.mClip.SetTo(aRect, aRadii); |
97 | 0 | } else { |
98 | 0 | aClipChainOnStack.mClip.SetTo(aRect); |
99 | 0 | } |
100 | 0 | const ActiveScrolledRoot* asr = aBuilder->CurrentActiveScrolledRoot(); |
101 | 0 | ApplyClip(aBuilder, mClipChainContentDescendants, asr, aClipChainOnStack); |
102 | 0 | InvalidateCurrentCombinedClipChain(asr); |
103 | 0 | } |
104 | | |
105 | | void |
106 | | DisplayListClipState::ClipContentDescendants( |
107 | | nsDisplayListBuilder* aBuilder, |
108 | | const nsRect& aRect, |
109 | | const nsRect& aRoundedRect, |
110 | | const nscoord* aRadii, |
111 | | DisplayItemClipChain& aClipChainOnStack) |
112 | 0 | { |
113 | 0 | if (aRadii) { |
114 | 0 | aClipChainOnStack.mClip.SetTo(aRect, aRoundedRect, aRadii); |
115 | 0 | } else { |
116 | 0 | nsRect intersect = aRect.Intersect(aRoundedRect); |
117 | 0 | aClipChainOnStack.mClip.SetTo(intersect); |
118 | 0 | } |
119 | 0 | const ActiveScrolledRoot* asr = aBuilder->CurrentActiveScrolledRoot(); |
120 | 0 | ApplyClip(aBuilder, mClipChainContentDescendants, asr, aClipChainOnStack); |
121 | 0 | InvalidateCurrentCombinedClipChain(asr); |
122 | 0 | } |
123 | | |
124 | | void |
125 | | DisplayListClipState::InvalidateCurrentCombinedClipChain( |
126 | | const ActiveScrolledRoot* aInvalidateUpTo) |
127 | 0 | { |
128 | 0 | mCurrentCombinedClipChainIsValid = false; |
129 | 0 | while (mCurrentCombinedClipChain && |
130 | 0 | ActiveScrolledRoot::IsAncestor(aInvalidateUpTo, |
131 | 0 | mCurrentCombinedClipChain->mASR)) { |
132 | 0 | mCurrentCombinedClipChain = mCurrentCombinedClipChain->mParent; |
133 | 0 | } |
134 | 0 | } |
135 | | |
136 | | void |
137 | | DisplayListClipState::ClipContainingBlockDescendantsToContentBox( |
138 | | nsDisplayListBuilder* aBuilder, |
139 | | nsIFrame* aFrame, |
140 | | DisplayItemClipChain& aClipChainOnStack, |
141 | | uint32_t aFlags) |
142 | 0 | { |
143 | 0 | nscoord radii[8]; |
144 | 0 | bool hasBorderRadius = aFrame->GetContentBoxBorderRadii(radii); |
145 | 0 | if (!hasBorderRadius && |
146 | 0 | (aFlags & ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT)) { |
147 | 0 | return; |
148 | 0 | } |
149 | 0 | |
150 | 0 | nsRect clipRect = |
151 | 0 | aFrame->GetContentRectRelativeToSelf() + aBuilder->ToReferenceFrame(aFrame); |
152 | 0 | // If we have a border-radius, we have to clip our content to that |
153 | 0 | // radius. |
154 | 0 | ClipContainingBlockDescendants( |
155 | 0 | aBuilder, clipRect, hasBorderRadius ? radii : nullptr, aClipChainOnStack); |
156 | 0 | } |
157 | | |
158 | | DisplayListClipState::AutoSaveRestore::AutoSaveRestore( |
159 | | nsDisplayListBuilder* aBuilder) |
160 | | : mBuilder(aBuilder) |
161 | | , mState(aBuilder->ClipState()) |
162 | | , mSavedState(aBuilder->ClipState()) |
163 | | #ifdef DEBUG |
164 | | , mClipUsed(false) |
165 | | , mRestored(false) |
166 | | #endif |
167 | 0 | { |
168 | 0 | } |
169 | | |
170 | | } // namespace mozilla |