Pair<DrawResult, RefPtr<SourceSurface>>
RasterImage::GetFrameInternal(const IntSize& aSize,
                              uint32_t aWhichFrame,
                              uint32_t aFlags)
{
  MOZ_ASSERT(aWhichFrame <= FRAME_MAX_VALUE);

  if (aSize.IsEmpty()) {
    return MakePair(DrawResult::BAD_ARGS, RefPtr<SourceSurface>());
  }

  if (aWhichFrame > FRAME_MAX_VALUE) {
    return MakePair(DrawResult::BAD_ARGS, RefPtr<SourceSurface>());
  }

  if (mError) {
    return MakePair(DrawResult::BAD_IMAGE, RefPtr<SourceSurface>());
  }

  // Get the frame. If it's not there, it's probably the caller's fault for
  // not waiting for the data to be loaded from the network or not passing
  // FLAG_SYNC_DECODE.
  DrawableSurface surface =
    LookupFrame(aSize, aFlags, ToPlaybackType(aWhichFrame));
  if (!surface) {
    // The OS threw this frame away and we couldn't redecode it.
    return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<SourceSurface>());
  }

  RefPtr<SourceSurface> sourceSurface = surface->GetSourceSurface();

  if (!surface->IsFinished()) {
    return MakePair(DrawResult::INCOMPLETE, Move(sourceSurface));
  }

  return MakePair(DrawResult::SUCCESS, Move(sourceSurface));
}