tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

DisplayListClipState.cpp (6546B)


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