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