Пример #1
0
static IntSize
ComputeMinSizeForShadowShape(RectCornerRadii* aCornerRadii,
                             gfxIntSize aBlurRadius,
                             IntMargin& aSlice,
                             const IntSize& aRectSize)
{
  float cornerWidth = 0;
  float cornerHeight = 0;
  if (aCornerRadii) {
    RectCornerRadii corners = *aCornerRadii;
    for (size_t i = 0; i < 4; i++) {
      cornerWidth = std::max(cornerWidth, corners[i].width);
      cornerHeight = std::max(cornerHeight, corners[i].height);
    }
  }

  aSlice = IntMargin(ceil(cornerHeight) + aBlurRadius.height,
                     ceil(cornerWidth) + aBlurRadius.width,
                     ceil(cornerHeight) + aBlurRadius.height,
                     ceil(cornerWidth) + aBlurRadius.width);

  IntSize minSize(aSlice.LeftRight() + 1,
                      aSlice.TopBottom() + 1);

  // If aRectSize is smaller than minSize, the border-image approach won't
  // work; there's no way to squeeze parts of the min box-shadow source
  // image such that the result looks correct. So we need to adjust minSize
  // in such a way that we can later draw it without stretching in the affected
  // dimension. We also need to adjust "slice" to ensure that we're not trying
  // to slice away more than we have.
  if (aRectSize.width < minSize.width) {
    minSize.width = aRectSize.width;
    aSlice.left = 0;
    aSlice.right = 0;
  }
  if (aRectSize.height < minSize.height) {
    minSize.height = aRectSize.height;
    aSlice.top = 0;
    aSlice.bottom = 0;
  }

  MOZ_ASSERT(aSlice.LeftRight() <= minSize.width);
  MOZ_ASSERT(aSlice.TopBottom() <= minSize.height);
  return minSize;
}
Пример #2
0
static IntSize
ComputeMinSizeForShadowShape(const RectCornerRadii* aCornerRadii,
                             const IntSize& aBlurRadius,
                             IntMargin& aOutSlice,
                             const IntSize& aRectSize)
{
  Size cornerSize(0, 0);
  if (aCornerRadii) {
    const RectCornerRadii& corners = *aCornerRadii;
    NS_FOR_CSS_FULL_CORNERS(i) {
      cornerSize.width = std::max(cornerSize.width, corners[i].width);
      cornerSize.height = std::max(cornerSize.height, corners[i].height);
    }
  }

  IntSize margin = IntSize::Ceil(cornerSize) + aBlurRadius;
  aOutSlice = IntMargin(margin.height, margin.width,
                        margin.height, margin.width);

  IntSize minSize(aOutSlice.LeftRight() + 1,
                  aOutSlice.TopBottom() + 1);

  // If aRectSize is smaller than minSize, the border-image approach won't
  // work; there's no way to squeeze parts of the min box-shadow source
  // image such that the result looks correct. So we need to adjust minSize
  // in such a way that we can later draw it without stretching in the affected
  // dimension. We also need to adjust "slice" to ensure that we're not trying
  // to slice away more than we have.
  if (aRectSize.width < minSize.width) {
    minSize.width = aRectSize.width;
    aOutSlice.left = 0;
    aOutSlice.right = 0;
  }
  if (aRectSize.height < minSize.height) {
    minSize.height = aRectSize.height;
    aOutSlice.top = 0;
    aOutSlice.bottom = 0;
  }

  MOZ_ASSERT(aOutSlice.LeftRight() <= minSize.width);
  MOZ_ASSERT(aOutSlice.TopBottom() <= minSize.height);
  return minSize;
}
Пример #3
0
// Blurs a small surface and creates the mask.
static already_AddRefed<SourceSurface>
CreateBlurMask(const IntSize& aRectSize,
               RectCornerRadii* aCornerRadii,
               gfxIntSize aBlurRadius,
               IntMargin& aExtendDestBy,
               IntMargin& aSliceBorder,
               DrawTarget& aDestDrawTarget)
{
  IntMargin slice;
  gfxAlphaBoxBlur blur;
  IntSize minSize =
    ComputeMinSizeForShadowShape(aCornerRadii, aBlurRadius, slice, aRectSize);
  IntRect minRect(IntPoint(), minSize);

  gfxContext* blurCtx = blur.Init(ThebesRect(Rect(minRect)), gfxIntSize(),
                                  aBlurRadius, nullptr, nullptr);

  if (!blurCtx) {
    return nullptr;
  }

  DrawTarget* blurDT = blurCtx->GetDrawTarget();
  ColorPattern black(Color(0.f, 0.f, 0.f, 1.f));

  if (aCornerRadii) {
    RefPtr<Path> roundedRect =
      MakePathForRoundedRect(*blurDT, Rect(minRect), *aCornerRadii);
    blurDT->Fill(roundedRect, black);
  } else {
    blurDT->FillRect(Rect(minRect), black);
  }

  IntPoint topLeft;
  RefPtr<SourceSurface> result = blur.DoBlur(&aDestDrawTarget, &topLeft);
  if (!result) {
    return nullptr;
  }

  IntRect expandedMinRect(topLeft, result->GetSize());
  aExtendDestBy = expandedMinRect - minRect;
  aSliceBorder = slice + aExtendDestBy;

  MOZ_ASSERT(aSliceBorder.LeftRight() <= expandedMinRect.width);
  MOZ_ASSERT(aSliceBorder.TopBottom() <= expandedMinRect.height);

  return result.forget();
}
Пример #4
0
static void
ComputeRectsForInsetBoxShadow(IntSize aBlurRadius,
                              IntSize aSpreadRadius,
                              IntRect& aOutOuterRect,
                              IntRect& aOutInnerRect,
                              IntMargin& aOutPathMargins,
                              const Rect& aDestRect,
                              const Rect& aShadowClipRect,
                              bool aHasBorderRadius,
                              const RectCornerRadii& aInnerClipRectRadii)
{
  IntSize rectBufferSize = aBlurRadius + aSpreadRadius;
  float cornerWidth = 0;
  float cornerHeight = 0;
  if (aHasBorderRadius) {
    for (size_t i = 0; i < 4; i++) {
      cornerWidth = std::max(cornerWidth, aInnerClipRectRadii[i].width);
      cornerHeight = std::max(cornerHeight, aInnerClipRectRadii[i].height);
    }
  }

  // Create the inner rect to be the smallest possible size based on
  // blur / spread / corner radii
  IntMargin innerMargin = IntMargin(ceil(cornerHeight) + rectBufferSize.height,
                                    ceil(cornerWidth) + rectBufferSize.width,
                                    ceil(cornerHeight) + rectBufferSize.height,
                                    ceil(cornerWidth) + rectBufferSize.width);
  aOutPathMargins = innerMargin;

  // If we have a negative spread radius, we would not have enough
  // size to actually do the blur. So the min size must be the abs() of the blur
  // and spread radius.
  IntSize minBlurSize(std::abs(aSpreadRadius.width) + std::abs(aBlurRadius.width),
                      std::abs(aSpreadRadius.height) + std::abs(aBlurRadius.height));

  IntMargin minInnerMargins = IntMargin(ceil(cornerHeight) + minBlurSize.height,
                                        ceil(cornerWidth) + minBlurSize.width,
                                        ceil(cornerHeight) + minBlurSize.height,
                                        ceil(cornerWidth) + minBlurSize.width);

  IntSize minInnerSize(minInnerMargins.LeftRight() + 1,
                       minInnerMargins.TopBottom() + 1);

  if (aShadowClipRect.height < minInnerSize.height) {
    minInnerSize.height = aShadowClipRect.height;
  }

  if (aShadowClipRect.width < minInnerSize.width) {
    minInnerSize.width = aShadowClipRect.width;
  }

  // Then expand the outer rect based on the size between the inner/outer rects
  IntSize minOuterSize(minInnerSize);
  IntMargin outerRectMargin(rectBufferSize.height, rectBufferSize.width,
                            rectBufferSize.height, rectBufferSize.width);
  minOuterSize.width += outerRectMargin.LeftRight();
  minOuterSize.height += outerRectMargin.TopBottom();

  aOutOuterRect = IntRect(IntPoint(), minOuterSize);
  aOutInnerRect = IntRect(IntPoint(rectBufferSize.width, rectBufferSize.height), minInnerSize);

  if (aShadowClipRect.IsEmpty()) {
    aOutInnerRect.width = 0;
    aOutInnerRect.height = 0;
  }
}