Coverage Report

Created: 2018-09-25 14:53

/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