Example #1
0
DrawResult
ClippedImage::DrawSingleTile(gfxContext* aContext,
                             const nsIntSize& aSize,
                             const ImageRegion& aRegion,
                             uint32_t aWhichFrame,
                             GraphicsFilter aFilter,
                             const Maybe<SVGImageContext>& aSVGContext,
                             uint32_t aFlags)
{
  MOZ_ASSERT(!MustCreateSurface(aContext, aSize, aRegion, aFlags),
             "Shouldn't need to create a surface");

  gfxRect clip(mClip.x, mClip.y, mClip.width, mClip.height);
  nsIntSize size(aSize), innerSize(aSize);
  if (NS_SUCCEEDED(InnerImage()->GetWidth(&innerSize.width)) &&
      NS_SUCCEEDED(InnerImage()->GetHeight(&innerSize.height))) {
    double scaleX = aSize.width / clip.width;
    double scaleY = aSize.height / clip.height;

    // Map the clip and size to the scale requested by the caller.
    clip.Scale(scaleX, scaleY);
    size = innerSize;
    size.Scale(scaleX, scaleY);
  } else {
    MOZ_ASSERT(false,
               "If ShouldClip() led us to draw then we should never get here");
  }

  // We restrict our drawing to only the clipping region, and translate so that
  // the clipping region is placed at the position the caller expects.
  ImageRegion region(aRegion);
  region.MoveBy(clip.x, clip.y);
  region = region.Intersect(clip);

  gfxContextMatrixAutoSaveRestore saveMatrix(aContext);
  aContext->Multiply(gfxMatrix::Translation(-clip.x, -clip.y));

  return InnerImage()->Draw(aContext, size, region,
                            aWhichFrame, aFilter,
                            aSVGContext.map(UnclipViewport,
                                            make_pair(innerSize, mClip.Size())),
                            aFlags);
}
Example #2
0
ClippedImage::Draw(gfxContext* aContext,
                   const nsIntSize& aSize,
                   const ImageRegion& aRegion,
                   uint32_t aWhichFrame,
                   SamplingFilter aSamplingFilter,
                   const Maybe<SVGImageContext>& aSVGContext,
                   uint32_t aFlags,
                   float aOpacity)
{
  if (!ShouldClip()) {
    return InnerImage()->Draw(aContext, aSize, aRegion, aWhichFrame,
                              aSamplingFilter, aSVGContext, aFlags, aOpacity);
  }

  // Check for tiling. If we need to tile then we need to create a
  // gfxCallbackDrawable to handle drawing for us.
  if (MustCreateSurface(aContext, aSize, aRegion, aFlags)) {
    // Create a temporary surface containing a single tile of this image.
    // GetFrame will call DrawSingleTile internally.
    DrawResult result;
    RefPtr<SourceSurface> surface;
    Tie(result, surface) =
      GetFrameInternal(aSize, aSVGContext, aWhichFrame, aFlags, aOpacity);
    if (!surface) {
      MOZ_ASSERT(result != DrawResult::SUCCESS);
      return result;
    }

    // Create a drawable from that surface.
    RefPtr<gfxSurfaceDrawable> drawable =
      new gfxSurfaceDrawable(surface, aSize);

    // Draw.
    gfxUtils::DrawPixelSnapped(aContext, drawable, aSize, aRegion,
                               SurfaceFormat::B8G8R8A8, aSamplingFilter,
                               aOpacity);

    return result;
  }

  return DrawSingleTile(aContext, aSize, aRegion, aWhichFrame,
                        aSamplingFilter, aSVGContext, aFlags, aOpacity);
}
Example #3
0
DrawResult
ClippedImage::DrawSingleTile(gfxContext* aContext,
                             const nsIntSize& aSize,
                             const ImageRegion& aRegion,
                             uint32_t aWhichFrame,
                             SamplingFilter aSamplingFilter,
                             const Maybe<SVGImageContext>& aSVGContext,
                             uint32_t aFlags)
{
  MOZ_ASSERT(!MustCreateSurface(aContext, aSize, aRegion, aFlags),
             "Shouldn't need to create a surface");

  gfxRect clip(mClip.x, mClip.y, mClip.width, mClip.height);
  nsIntSize size(aSize), innerSize(aSize);
  bool needScale = false;
  if (mSVGViewportSize && !mSVGViewportSize->IsEmpty()) {
    innerSize = *mSVGViewportSize;
    needScale = true;
  } else if (NS_SUCCEEDED(InnerImage()->GetWidth(&innerSize.width)) &&
             NS_SUCCEEDED(InnerImage()->GetHeight(&innerSize.height))) {
    needScale = true;
  } else {
    MOZ_ASSERT_UNREACHABLE(
               "If ShouldClip() led us to draw then we should never get here");
  }

  if (needScale) {
    double scaleX = aSize.width / clip.width;
    double scaleY = aSize.height / clip.height;

    // Map the clip and size to the scale requested by the caller.
    clip.Scale(scaleX, scaleY);
    size = innerSize;
    size.Scale(scaleX, scaleY);
  }

  // We restrict our drawing to only the clipping region, and translate so that
  // the clipping region is placed at the position the caller expects.
  ImageRegion region(aRegion);
  region.MoveBy(clip.x, clip.y);
  region = region.Intersect(clip);

  gfxContextMatrixAutoSaveRestore saveMatrix(aContext);
  aContext->Multiply(gfxMatrix::Translation(-clip.x, -clip.y));

  auto unclipViewport = [&](const SVGImageContext& aOldContext) {
    // Map the viewport to the inner image. Note that we don't take the aSize
    // parameter of imgIContainer::Draw into account, just the clipping region.
    // The size in pixels at which the output will ultimately be drawn is
    // irrelevant here since the purpose of the SVG viewport size is to
    // determine what *region* of the SVG document will be drawn.
    CSSIntSize vSize(aOldContext.GetViewportSize());
    vSize.width = ceil(vSize.width * double(innerSize.width) / mClip.width);
    vSize.height =
      ceil(vSize.height * double(innerSize.height) / mClip.height);

    return SVGImageContext(vSize,
                           aOldContext.GetPreserveAspectRatio());
  };

  return InnerImage()->Draw(aContext, size, region,
                            aWhichFrame, aSamplingFilter,
                            aSVGContext.map(unclipViewport),
                            aFlags);
}