no bug - Import translations from android-l10n r=release a=l10n CLOSED TREE
[gecko.git] / layout / painting / DisplayListClipState.cpp
blob8a87e2906b8572b0c4cb48b55bde0a2a58590189
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/. */
7 #include "DisplayListClipState.h"
9 #include "nsDisplayList.h"
11 namespace mozilla {
13 const DisplayItemClipChain* DisplayListClipState::GetCurrentCombinedClipChain(
14 nsDisplayListBuilder* aBuilder) {
15 if (mCurrentCombinedClipChainIsValid) {
16 return mCurrentCombinedClipChain;
18 if (!mClipChainContentDescendants && !mClipChainContainingBlockDescendants) {
19 mCurrentCombinedClipChain = nullptr;
20 mCurrentCombinedClipChainIsValid = true;
21 return nullptr;
24 mCurrentCombinedClipChain = aBuilder->CreateClipChainIntersection(
25 mCurrentCombinedClipChain, mClipChainContentDescendants,
26 mClipChainContainingBlockDescendants);
27 mCurrentCombinedClipChainIsValid = true;
28 return mCurrentCombinedClipChain;
31 static void ApplyClip(nsDisplayListBuilder* aBuilder,
32 const DisplayItemClipChain*& aClipToModify,
33 const ActiveScrolledRoot* aASR,
34 DisplayItemClipChain& aClipChainOnStack) {
35 aClipChainOnStack.mASR = aASR;
36 if (aClipToModify && aClipToModify->mASR == aASR) {
37 // Intersect with aClipToModify and replace the clip chain item.
38 aClipChainOnStack.mClip.IntersectWith(aClipToModify->mClip);
39 aClipChainOnStack.mParent = aClipToModify->mParent;
40 aClipToModify = &aClipChainOnStack;
41 } else if (!aClipToModify ||
42 ActiveScrolledRoot::IsAncestor(aClipToModify->mASR, aASR)) {
43 // Add a new clip chain item at the bottom.
44 aClipChainOnStack.mParent = aClipToModify;
45 aClipToModify = &aClipChainOnStack;
46 } else {
47 // We need to insert / intersect a DisplayItemClipChain in the middle of the
48 // aClipToModify chain. This is a very rare case.
49 // Find the common ancestor and have the builder create the
50 // DisplayItemClipChain intersection. This will create new
51 // DisplayItemClipChain objects for all descendants of ancestorSC and we
52 // will not hold on to a pointer to aClipChainOnStack.
53 const DisplayItemClipChain* ancestorSC = aClipToModify;
54 while (ancestorSC &&
55 ActiveScrolledRoot::IsAncestor(aASR, ancestorSC->mASR)) {
56 ancestorSC = ancestorSC->mParent;
58 ancestorSC = aBuilder->CopyWholeChain(ancestorSC);
59 aClipChainOnStack.mParent = nullptr;
60 aClipToModify = aBuilder->CreateClipChainIntersection(
61 ancestorSC, aClipToModify, &aClipChainOnStack);
65 void DisplayListClipState::ClipContainingBlockDescendants(
66 nsDisplayListBuilder* aBuilder, const nsRect& aRect, const nscoord* aRadii,
67 DisplayItemClipChain& aClipChainOnStack) {
68 if (aRadii) {
69 aClipChainOnStack.mClip.SetTo(aRect, aRadii);
70 } else {
71 aClipChainOnStack.mClip.SetTo(aRect);
73 const ActiveScrolledRoot* asr = aBuilder->CurrentActiveScrolledRoot();
74 ApplyClip(aBuilder, mClipChainContainingBlockDescendants, asr,
75 aClipChainOnStack);
76 InvalidateCurrentCombinedClipChain(asr);
79 void DisplayListClipState::ClipContentDescendants(
80 nsDisplayListBuilder* aBuilder, const nsRect& aRect, const nscoord* aRadii,
81 DisplayItemClipChain& aClipChainOnStack) {
82 if (aRadii) {
83 aClipChainOnStack.mClip.SetTo(aRect, aRadii);
84 } else {
85 aClipChainOnStack.mClip.SetTo(aRect);
87 const ActiveScrolledRoot* asr = aBuilder->CurrentActiveScrolledRoot();
88 ApplyClip(aBuilder, mClipChainContentDescendants, asr, aClipChainOnStack);
89 InvalidateCurrentCombinedClipChain(asr);
92 void DisplayListClipState::ClipContentDescendants(
93 nsDisplayListBuilder* aBuilder, const nsRect& aRect,
94 const nsRect& aRoundedRect, const nscoord* aRadii,
95 DisplayItemClipChain& aClipChainOnStack) {
96 if (aRadii) {
97 aClipChainOnStack.mClip.SetTo(aRect, aRoundedRect, aRadii);
98 } else {
99 nsRect intersect = aRect.Intersect(aRoundedRect);
100 aClipChainOnStack.mClip.SetTo(intersect);
102 const ActiveScrolledRoot* asr = aBuilder->CurrentActiveScrolledRoot();
103 ApplyClip(aBuilder, mClipChainContentDescendants, asr, aClipChainOnStack);
104 InvalidateCurrentCombinedClipChain(asr);
107 void DisplayListClipState::InvalidateCurrentCombinedClipChain(
108 const ActiveScrolledRoot* aInvalidateUpTo) {
109 mClippedToDisplayPort = false;
110 mCurrentCombinedClipChainIsValid = false;
111 while (mCurrentCombinedClipChain &&
112 ActiveScrolledRoot::IsAncestor(aInvalidateUpTo,
113 mCurrentCombinedClipChain->mASR)) {
114 mCurrentCombinedClipChain = mCurrentCombinedClipChain->mParent;
118 void DisplayListClipState::ClipContainingBlockDescendantsToContentBox(
119 nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
120 DisplayItemClipChain& aClipChainOnStack, uint32_t aFlags) {
121 nscoord radii[8];
122 bool hasBorderRadius = aFrame->GetContentBoxBorderRadii(radii);
123 if (!hasBorderRadius &&
124 (aFlags & ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT)) {
125 return;
128 nsRect clipRect = aFrame->GetContentRectRelativeToSelf() +
129 aBuilder->ToReferenceFrame(aFrame);
130 // If we have a border-radius, we have to clip our content to that
131 // radius.
132 ClipContainingBlockDescendants(
133 aBuilder, clipRect, hasBorderRadius ? radii : nullptr, aClipChainOnStack);
136 DisplayListClipState::AutoSaveRestore::AutoSaveRestore(
137 nsDisplayListBuilder* aBuilder)
138 : mBuilder(aBuilder),
139 mState(aBuilder->ClipState()),
140 mSavedState(aBuilder->ClipState())
141 #ifdef DEBUG
143 mClipUsed(false),
144 mRestored(false)
145 #endif
149 } // namespace mozilla