Example #1
0
void
DrawBlur(gfxContext* aDestinationCtx,
         SourceSurface* aBlur,
         const IntPoint& aTopLeft,
         const Rect* aDirtyRect)
{
    DrawTarget *dest = aDestinationCtx->GetDrawTarget();

    nsRefPtr<gfxPattern> thebesPat = aDestinationCtx->GetPattern();
    Pattern* pat = thebesPat->GetPattern(dest, nullptr);

    Matrix oldTransform = dest->GetTransform();
    Matrix newTransform = oldTransform;
    newTransform.Translate(aTopLeft.x, aTopLeft.y);

    // Avoid a semi-expensive clip operation if we can, otherwise
    // clip to the dirty rect
    if (aDirtyRect) {
        dest->PushClipRect(*aDirtyRect);
    }

    dest->SetTransform(newTransform);
    dest->MaskSurface(*pat, aBlur, Point(0, 0));
    dest->SetTransform(oldTransform);

    if (aDirtyRect) {
        dest->PopClip();
    }
}
Example #2
0
void
gfxAlphaBoxBlur::Paint(gfxContext* aDestinationCtx)
{
    if (!mContext)
        return;

    mBlur->Blur(mData);

    mozilla::gfx::Rect* dirtyRect = mBlur->GetDirtyRect();

    DrawTarget *dest = aDestinationCtx->GetDrawTarget();
    if (!dest) {
      NS_ERROR("Blurring not supported for Thebes contexts!");
      return;
    }

    mozilla::RefPtr<SourceSurface> mask
      = dest->CreateSourceSurfaceFromData(mData,
                                          mBlur->GetSize(),
                                          mBlur->GetStride(),
                                          FORMAT_A8);
    if (!mask) {
      NS_ERROR("Failed to create mask!");
      return;
    }

    nsRefPtr<gfxPattern> thebesPat = aDestinationCtx->GetPattern();
    Pattern* pat = thebesPat->GetPattern(dest, nullptr);

    Matrix oldTransform = dest->GetTransform();
    Matrix newTransform = oldTransform;
    newTransform.Translate(mBlur->GetRect().x, mBlur->GetRect().y);

    // Avoid a semi-expensive clip operation if we can, otherwise
    // clip to the dirty rect
    if (dirtyRect) {
        dest->PushClipRect(*dirtyRect);
    }

    dest->SetTransform(newTransform);
    dest->MaskSurface(*pat, mask, Point(0, 0));
    dest->SetTransform(oldTransform);

    if (dirtyRect) {
        dest->PopClip();
    }
}
Example #3
0
void
gfxAlphaBoxBlur::Paint(gfxContext* aDestinationCtx)
{
  if (!mAccelerated && !mData) {
    return;
  }

  DrawTarget *dest = aDestinationCtx->GetDrawTarget();
  if (!dest) {
    NS_WARNING("Blurring not supported for Thebes contexts!");
    return;
  }

  RefPtr<gfxPattern> thebesPat = aDestinationCtx->GetPattern();
  Pattern* pat = thebesPat->GetPattern(dest, nullptr);
  if (!pat) {
    NS_WARNING("Failed to get pattern for blur!");
    return;
  }

  IntPoint topLeft;
  RefPtr<SourceSurface> mask = DoBlur(nullptr, &topLeft);
  if (!mask) {
    NS_ERROR("Failed to create mask!");
    return;
  }

  // Avoid a semi-expensive clip operation if we can, otherwise
  // clip to the dirty rect
  Rect* dirtyRect = mBlur.GetDirtyRect();
  if (dirtyRect) {
    dest->PushClipRect(*dirtyRect);
  }

  Matrix oldTransform = dest->GetTransform();
  Matrix newTransform = oldTransform;
  newTransform.PreTranslate(topLeft);
  dest->SetTransform(newTransform);

  dest->MaskSurface(*pat, mask, Point(0, 0));

  dest->SetTransform(oldTransform);

  if (dirtyRect) {
    dest->PopClip();
  }
}
Example #4
0
/* static */ void
gfxAlphaBoxBlur::BlurRectangle(gfxContext* aDestinationCtx,
                               const gfxRect& aRect,
                               const RectCornerRadii* aCornerRadii,
                               const gfxPoint& aBlurStdDev,
                               const Color& aShadowColor,
                               const gfxRect& aDirtyRect,
                               const gfxRect& aSkipRect)
{
  IntSize blurRadius = CalculateBlurRadius(aBlurStdDev);
  bool mirrorCorners = !aCornerRadii || aCornerRadii->AreRadiiSame();

  IntRect rect = RoundedToInt(ToRect(aRect));
  IntMargin blurMargin;
  IntMargin slice;
  IntSize minSize;
  RefPtr<SourceSurface> boxShadow = GetBlur(aDestinationCtx,
                                            rect.Size(), blurRadius,
                                            aCornerRadii, aShadowColor, mirrorCorners,
                                            blurMargin, slice, minSize);
  if (!boxShadow) {
    return;
  }

  DrawTarget* destDrawTarget = aDestinationCtx->GetDrawTarget();
  destDrawTarget->PushClipRect(ToRect(aDirtyRect));

  // Copy the right parts from boxShadow into destDrawTarget. The middle parts
  // will be stretched, border-image style.

  Rect srcOuter(Point(blurMargin.left, blurMargin.top), Size(minSize));
  Rect srcInner(srcOuter);
  srcOuter.Inflate(Margin(blurMargin));
  srcInner.Deflate(Margin(slice));

  Rect dstOuter(rect);
  Rect dstInner(rect);
  dstOuter.Inflate(Margin(blurMargin));
  dstInner.Deflate(Margin(slice));

  Rect skipRect = ToRect(aSkipRect);

  if (minSize == rect.Size()) {
    // The target rect is smaller than the minimal size so just draw the surface
    if (mirrorCorners) {
      DrawMirroredBoxShadow(destDrawTarget, boxShadow, dstOuter);
    } else {
      destDrawTarget->DrawSurface(boxShadow, dstOuter, srcOuter);
    }
  } else {
    if (mirrorCorners) {
      DrawMirroredMinBoxShadow(destDrawTarget, boxShadow, dstOuter, dstInner,
                               srcOuter, srcInner, skipRect, true);
    } else {
      DrawMinBoxShadow(destDrawTarget, boxShadow, dstOuter, dstInner,
                       srcOuter, srcInner, skipRect, true);
    }
  }

  // A note about anti-aliasing and seems between adjacent parts:
  // We don't explicitly disable anti-aliasing in the DrawSurface calls above,
  // so if there's a transform on destDrawTarget that is not pixel-aligned,
  // there will be seams between adjacent parts of the box-shadow. It's hard to
  // avoid those without the use of an intermediate surface.
  // You might think that we could avoid those by just turning of AA, but there
  // is a problem with that: Box-shadow rendering needs to clip out the
  // element's border box, and we'd like that clip to have anti-aliasing -
  // especially if the element has rounded corners! So we can't do that unless
  // we have a way to say "Please anti-alias the clip, but don't antialias the
  // destination rect of the DrawSurface call".
  // On OS X there is an additional problem with turning off AA: CoreGraphics
  // will not just fill the pixels that have their pixel center inside the
  // filled shape. Instead, it will fill all the pixels which are partially
  // covered by the shape. So for pixels on the edge between two adjacent parts,
  // all those pixels will be painted to by both parts, which looks very bad.

  destDrawTarget->PopClip();
}