Commit a1b7878e authored by Robert Longson's avatar Robert Longson
Browse files

Bug 1833616 - Use RAII to manage Push/Pop of gfxContext Clip r=emilio,gfx-reviewers,lsalzman

Take care to restore only the parts of the gfxContext that we need to because saving and restoring the complete gfxContext is expensive.

Differential Revision: https://phabricator.services.mozilla.com/D178304
parent 546970ef
Loading
Loading
Loading
Loading
+36 −0
Original line number Original line Diff line number Diff line
@@ -740,6 +740,42 @@ class MOZ_STACK_CLASS gfxGroupForBlendAutoSaveRestore final {
  bool mPushedGroup = false;
  bool mPushedGroup = false;
};
};


class MOZ_STACK_CLASS gfxClipAutoSaveRestore final {
 public:
  using Rect = mozilla::gfx::Rect;

  explicit gfxClipAutoSaveRestore(gfxContext* aContext) : mContext(aContext) {}

  void Clip(const gfxRect& aRect) { Clip(ToRect(aRect)); }

  void Clip(const Rect& aRect) {
    MOZ_ASSERT(!mClipped, "Already called Clip once");
    mContext->Clip(aRect);
    mClipped = true;
  }

  void TransformedClip(const gfxMatrix& aTransform, const gfxRect& aRect) {
    MOZ_ASSERT(!mClipped, "Already called Clip once");
    if (aTransform.IsSingular()) {
      return;
    }
    gfxContextMatrixAutoSaveRestore matrixAutoSaveRestore(mContext);
    mContext->Multiply(aTransform);
    mContext->Clip(aRect);
    mClipped = true;
  }

  ~gfxClipAutoSaveRestore() {
    if (mClipped) {
      mContext->PopClip();
    }
  }

 private:
  gfxContext* mContext;
  bool mClipped = false;
};

class MOZ_STACK_CLASS DrawTargetAutoDisableSubpixelAntialiasing final {
class MOZ_STACK_CLASS DrawTargetAutoDisableSubpixelAntialiasing final {
 public:
 public:
  typedef mozilla::gfx::DrawTarget DrawTarget;
  typedef mozilla::gfx::DrawTarget DrawTarget;
+2 −2
Original line number Original line Diff line number Diff line
@@ -475,6 +475,7 @@ void gfxTextRun::DrawPartialLigature(gfxFont* aFont, Range aRange,
    ClipPartialLigature(this, &start, &end, aPt->x, &data);
    ClipPartialLigature(this, &start, &end, aPt->x, &data);
  }
  }


  gfxClipAutoSaveRestore autoSaveClip(aParams.context);
  {
  {
    // use division here to ensure that when the rect is aligned on multiples
    // use division here to ensure that when the rect is aligned on multiples
    // of mAppUnitsPerDevUnit, we clip to true device unit boundaries.
    // of mAppUnitsPerDevUnit, we clip to true device unit boundaries.
@@ -487,7 +488,7 @@ void gfxTextRun::DrawPartialLigature(gfxFont* aFont, Range aRange,
                   (end - start) / mAppUnitsPerDevUnit, clipExtents.Height());
                   (end - start) / mAppUnitsPerDevUnit, clipExtents.Height());
    MaybeSnapToDevicePixels(clipRect, *aParams.dt, true);
    MaybeSnapToDevicePixels(clipRect, *aParams.dt, true);


    aParams.context->Clip(clipRect);
    autoSaveClip.Clip(clipRect);
  }
  }


  gfx::Point pt;
  gfx::Point pt;
@@ -498,7 +499,6 @@ void gfxTextRun::DrawPartialLigature(gfxFont* aFont, Range aRange,
  }
  }


  DrawGlyphs(aFont, data.mRange, &pt, aProvider, aRange, aParams, aOrientation);
  DrawGlyphs(aFont, data.mRange, &pt, aProvider, aRange, aParams, aOrientation);
  aParams.context->PopClip();


  if (aParams.isVerticalRun) {
  if (aParams.isVerticalRun) {
    aPt->y += aParams.direction * data.mPartWidth;
    aPt->y += aParams.direction * data.mPartWidth;
+5 −12
Original line number Original line Diff line number Diff line
@@ -7646,9 +7646,9 @@ void nsDisplayText::RenderToContext(gfxContext* aCtx,
  pixelVisible.Inflate(2);
  pixelVisible.Inflate(2);
  pixelVisible.RoundOut();
  pixelVisible.RoundOut();


  bool willClip = !aBuilder->IsForGenerateGlyphMask() && !aIsRecording;
  gfxClipAutoSaveRestore autoSaveClip(aCtx);
  if (willClip) {
  if (!aBuilder->IsForGenerateGlyphMask() && !aIsRecording) {
    aCtx->Clip(pixelVisible);
    autoSaveClip.Clip(pixelVisible);
  }
  }


  NS_ASSERTION(mVisIStartEdge >= 0, "illegal start edge");
  NS_ASSERTION(mVisIStartEdge >= 0, "illegal start edge");
@@ -7689,10 +7689,6 @@ void nsDisplayText::RenderToContext(gfxContext* aCtx,


  f->PaintText(params, mVisIStartEdge, mVisIEndEdge, ToReferenceFrame(),
  f->PaintText(params, mVisIStartEdge, mVisIEndEdge, ToReferenceFrame(),
               f->IsSelected(), aOpacity);
               f->IsSelected(), aOpacity);

  if (willClip) {
    aCtx->PopClip();
  }
}
}


// This could go to nsDisplayListInvalidation.h, but
// This could go to nsDisplayListInvalidation.h, but
@@ -8024,12 +8020,11 @@ void nsDisplayMasksAndClipPaths::PaintWithContentsPaintCallback(
    const std::function<void()>& aPaintChildren) {
    const std::function<void()>& aPaintChildren) {
  // Clip the drawing target by mVisibleRect, which contains the visible
  // Clip the drawing target by mVisibleRect, which contains the visible
  // region of the target frame and its out-of-flow and inflow descendants.
  // region of the target frame and its out-of-flow and inflow descendants.
  gfxContext* context = aCtx;

  Rect bounds = NSRectToRect(GetPaintRect(aBuilder, aCtx),
  Rect bounds = NSRectToRect(GetPaintRect(aBuilder, aCtx),
                             mFrame->PresContext()->AppUnitsPerDevPixel());
                             mFrame->PresContext()->AppUnitsPerDevPixel());
  bounds.RoundOut();
  bounds.RoundOut();
  context->Clip(bounds);
  gfxClipAutoSaveRestore autoSaveClip(aCtx);
  autoSaveClip.Clip(bounds);


  imgDrawingParams imgParams(aBuilder->GetImageDecodeFlags());
  imgDrawingParams imgParams(aBuilder->GetImageDecodeFlags());
  nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
  nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
@@ -8039,8 +8034,6 @@ void nsDisplayMasksAndClipPaths::PaintWithContentsPaintCallback(
  ComputeMaskGeometry(params);
  ComputeMaskGeometry(params);


  SVGIntegrationUtils::PaintMaskAndClipPath(params, aPaintChildren);
  SVGIntegrationUtils::PaintMaskAndClipPath(params, aPaintChildren);

  context->PopClip();
}
}


void nsDisplayMasksAndClipPaths::Paint(nsDisplayListBuilder* aBuilder,
void nsDisplayMasksAndClipPaths::Paint(nsDisplayListBuilder* aBuilder,
+2 −4
Original line number Original line Diff line number Diff line
@@ -173,7 +173,7 @@ void SVGForeignObjectFrame::PaintSVG(gfxContext& aContext,
    return;
    return;
  }
  }


  aContext.Save();
  gfxClipAutoSaveRestore autoSaveClip(&aContext);


  if (StyleDisplay()->IsScrollableOverflow()) {
  if (StyleDisplay()->IsScrollableOverflow()) {
    float x, y, width, height;
    float x, y, width, height;
@@ -183,7 +183,7 @@ void SVGForeignObjectFrame::PaintSVG(gfxContext& aContext,


    gfxRect clipRect =
    gfxRect clipRect =
        SVGUtils::GetClipRectForFrame(this, 0.0f, 0.0f, width, height);
        SVGUtils::GetClipRectForFrame(this, 0.0f, 0.0f, width, height);
    SVGUtils::SetClipRect(&aContext, aTransform, clipRect);
    autoSaveClip.TransformedClip(aTransform, clipRect);
  }
  }


  // SVG paints in CSS px, but normally frames paint in dev pixels. Here we
  // SVG paints in CSS px, but normally frames paint in dev pixels. Here we
@@ -210,8 +210,6 @@ void SVGForeignObjectFrame::PaintSVG(gfxContext& aContext,
  nsLayoutUtils::PaintFrame(&aContext, kid, nsRegion(kid->InkOverflowRect()),
  nsLayoutUtils::PaintFrame(&aContext, kid, nsRegion(kid->InkOverflowRect()),
                            NS_RGBA(0, 0, 0, 0),
                            NS_RGBA(0, 0, 0, 0),
                            nsDisplayListBuilderMode::Painting, flags);
                            nsDisplayListBuilderMode::Painting, flags);

  aContext.Restore();
}
}


nsIFrame* SVGForeignObjectFrame::GetFrameForPoint(const gfxPoint& aPoint) {
nsIFrame* SVGForeignObjectFrame::GetFrameForPoint(const gfxPoint& aPoint) {
+4 −4
Original line number Original line Diff line number Diff line
@@ -342,14 +342,16 @@ void SVGImageFrame::PaintSVG(gfxContext& aContext, const gfxMatrix& aTransform,
  }
  }


  if (mImageContainer) {
  if (mImageContainer) {
    gfxContextAutoSaveRestore autoRestorer(&aContext);
    gfxClipAutoSaveRestore autoSaveClip(&aContext);


    if (StyleDisplay()->IsScrollableOverflow()) {
    if (StyleDisplay()->IsScrollableOverflow()) {
      gfxRect clipRect =
      gfxRect clipRect =
          SVGUtils::GetClipRectForFrame(this, x, y, width, height);
          SVGUtils::GetClipRectForFrame(this, x, y, width, height);
      SVGUtils::SetClipRect(&aContext, aTransform, clipRect);
      autoSaveClip.TransformedClip(aTransform, clipRect);
    }
    }


    gfxContextMatrixAutoSaveRestore autoSaveMatrix(&aContext);

    if (!TransformContextForPainting(&aContext, aTransform)) {
    if (!TransformContextForPainting(&aContext, aTransform)) {
      return;
      return;
    }
    }
@@ -404,8 +406,6 @@ void SVGImageFrame::PaintSVG(gfxContext& aContext, const gfxMatrix& aTransform,
          nsLayoutUtils::GetSamplingFilterForFrame(this), nsPoint(0, 0),
          nsLayoutUtils::GetSamplingFilterForFrame(this), nsPoint(0, 0),
          nullptr, SVGImageContext(), flags);
          nullptr, SVGImageContext(), flags);
    }
    }

    // gfxContextAutoSaveRestore goes out of scope & cleans up our gfxContext
  }
  }
}
}


Loading