Пример #1
0
IntSize
RasterImage::OptimalImageSizeForDest(const gfxSize& aDest, uint32_t aWhichFrame,
                                     SamplingFilter aSamplingFilter, uint32_t aFlags)
{
  MOZ_ASSERT(aDest.width >= 0 || ceil(aDest.width) <= INT32_MAX ||
             aDest.height >= 0 || ceil(aDest.height) <= INT32_MAX,
             "Unexpected destination size");

  if (mSize.IsEmpty() || aDest.IsEmpty()) {
    return IntSize(0, 0);
  }

  IntSize destSize = IntSize::Ceil(aDest.width, aDest.height);

  if (aSamplingFilter == SamplingFilter::GOOD &&
      CanDownscaleDuringDecode(destSize, aFlags)) {
    return destSize;
  }

  // We can't scale to this size. Use our intrinsic size for now.
  return mSize;
}
Пример #2
0
DrawResult
RasterImage::DrawInternal(DrawableSurface&& aSurface,
                          gfxContext* aContext,
                          const IntSize& aSize,
                          const ImageRegion& aRegion,
                          SamplingFilter aSamplingFilter,
                          uint32_t aFlags,
                          float aOpacity)
{
  gfxContextMatrixAutoSaveRestore saveMatrix(aContext);
  ImageRegion region(aRegion);
  bool frameIsFinished = aSurface->IsFinished();

  // By now we may have a frame with the requested size. If not, we need to
  // adjust the drawing parameters accordingly.
  IntSize finalSize = aSurface->GetImageSize();
  bool couldRedecodeForBetterFrame = false;
  if (finalSize != aSize) {
    gfx::Size scale(double(aSize.width) / finalSize.width,
                    double(aSize.height) / finalSize.height);
    aContext->Multiply(gfxMatrix::Scaling(scale.width, scale.height));
    region.Scale(1.0 / scale.width, 1.0 / scale.height);

    couldRedecodeForBetterFrame = CanDownscaleDuringDecode(aSize, aFlags);
  }

  if (!aSurface->Draw(aContext, region, aSamplingFilter, aFlags, aOpacity)) {
    RecoverFromInvalidFrames(aSize, aFlags);
    return DrawResult::TEMPORARY_ERROR;
  }
  if (!frameIsFinished) {
    return DrawResult::INCOMPLETE;
  }
  if (couldRedecodeForBetterFrame) {
    return DrawResult::WRONG_SIZE;
  }
  return DrawResult::SUCCESS;
}
Пример #3
0
DrawableSurface
RasterImage::LookupFrame(const IntSize& aSize,
                         uint32_t aFlags,
                         PlaybackType aPlaybackType)
{
  MOZ_ASSERT(NS_IsMainThread());

  // If we're opaque, we don't need to care about premultiplied alpha, because
  // that can only matter for frames with transparency.
  if (IsOpaque()) {
    aFlags &= ~FLAG_DECODE_NO_PREMULTIPLY_ALPHA;
  }

  IntSize requestedSize = CanDownscaleDuringDecode(aSize, aFlags)
                        ? aSize : mSize;
  if (requestedSize.IsEmpty()) {
    return DrawableSurface();  // Can't decode to a surface of zero size.
  }

  LookupResult result =
    LookupFrameInternal(requestedSize, aFlags, aPlaybackType);

  if (!result && !mHasSize) {
    // We can't request a decode without knowing our intrinsic size. Give up.
    return DrawableSurface();
  }

  if (result.Type() == MatchType::NOT_FOUND ||
      result.Type() == MatchType::SUBSTITUTE_BECAUSE_NOT_FOUND ||
      ((aFlags & FLAG_SYNC_DECODE) && !result)) {
    // We don't have a copy of this frame, and there's no decoder working on
    // one. (Or we're sync decoding and the existing decoder hasn't even started
    // yet.) Trigger decoding so it'll be available next time.
    MOZ_ASSERT(aPlaybackType != PlaybackType::eAnimated ||
               !mAnimationState || mAnimationState->KnownFrameCount() < 1,
               "Animated frames should be locked");

    Decode(requestedSize, aFlags, aPlaybackType);

    // If we can sync decode, we should already have the frame.
    if (aFlags & FLAG_SYNC_DECODE) {
      result = LookupFrameInternal(requestedSize, aFlags, aPlaybackType);
    }
  }

  if (!result) {
    // We still weren't able to get a frame. Give up.
    return DrawableSurface();
  }

  if (result.Surface()->GetCompositingFailed()) {
    return DrawableSurface();
  }

  MOZ_ASSERT(!result.Surface()->GetIsPaletted(),
             "Should not have a paletted frame");

  // Sync decoding guarantees that we got the frame, but if it's owned by an
  // async decoder that's currently running, the contents of the frame may not
  // be available yet. Make sure we get everything.
  if (mHasSourceData && (aFlags & FLAG_SYNC_DECODE)) {
    result.Surface()->WaitUntilFinished();
  }

  // If we could have done some decoding in this function we need to check if
  // that decoding encountered an error and hence aborted the surface. We want
  // to avoid calling IsAborted if we weren't passed any sync decode flag because
  // IsAborted acquires the monitor for the imgFrame.
  if (aFlags & (FLAG_SYNC_DECODE | FLAG_SYNC_DECODE_IF_FAST) &&
    result.Surface()->IsAborted()) {
    return DrawableSurface();
  }

  return Move(result.Surface());
}