コード例 #1
0
ファイル: gfxBlur.cpp プロジェクト: yrliou/gecko-dev
static already_AddRefed<SourceSurface>
GetBlur(gfxContext* aDestinationCtx,
        const IntSize& aRectSize,
        const IntSize& aBlurRadius,
        const RectCornerRadii* aCornerRadii,
        const Color& aShadowColor,
        bool aMirrorCorners,
        IntMargin& aOutBlurMargin,
        IntMargin& aOutSlice,
        IntSize& aOutMinSize)
{
  if (!gBlurCache) {
    gBlurCache = new BlurCache();
  }

  IntSize minSize =
    ComputeMinSizeForShadowShape(aCornerRadii, aBlurRadius, aOutSlice, aRectSize);

  // We can get seams using the min size rect when drawing to the destination rect
  // if we have a non-pixel aligned destination transformation. In those cases,
  // fallback to just rendering the destination rect.
  // During printing, we record all the Moz 2d commands and replay them on the parent side
  // with Cairo. Cairo printing uses StretchDIBits to stretch the surface. However,
  // since our source image is only 1px for some parts, we make thousands of calls.
  // Instead just render the blur ourself here as one image and send it over for printing.
  // TODO: May need to change this with the blob renderer in WR since it also records.
  Matrix destMatrix = ToMatrix(aDestinationCtx->CurrentMatrix());
  bool useDestRect = !destMatrix.IsRectilinear() || destMatrix.HasNonIntegerTranslation() ||
                     aDestinationCtx->GetDrawTarget()->IsRecording();
  if (useDestRect) {
    minSize = aRectSize;
  }
  aOutMinSize = minSize;

  DrawTarget* destDT = aDestinationCtx->GetDrawTarget();

  if (!useDestRect) {
    BlurCacheData* cached = gBlurCache->Lookup(minSize, aBlurRadius,
                                               aCornerRadii, aShadowColor,
                                               destDT->GetBackendType());
    if (cached) {
      // See CreateBoxShadow() for these values
      aOutBlurMargin = cached->mBlurMargin;
      RefPtr<SourceSurface> blur = cached->mBlur;
      return blur.forget();
    }
  }

  RefPtr<SourceSurface> boxShadow =
    CreateBoxShadow(destDT, minSize, aCornerRadii, aBlurRadius,
                    aShadowColor, aMirrorCorners, aOutBlurMargin);
  if (!boxShadow) {
    return nullptr;
  }

  if (RefPtr<SourceSurface> opt = destDT->OptimizeSourceSurface(boxShadow)) {
    boxShadow = opt;
  }

  if (!useDestRect) {
    CacheBlur(destDT, minSize, aBlurRadius, aCornerRadii, aShadowColor,
              aOutBlurMargin, boxShadow);
  }
  return boxShadow.forget();
}