Example #1
0
VectorImage::GetFrameAtSize(const IntSize& aSize,
                            uint32_t aWhichFrame,
                            uint32_t aFlags)
{
  MOZ_ASSERT(aWhichFrame <= FRAME_MAX_VALUE);

  if (aSize.IsEmpty()) {
    return nullptr;
  }

  if (aWhichFrame > FRAME_MAX_VALUE) {
    return nullptr;
  }

  if (mError || !mIsFullyLoaded) {
    return nullptr;
  }

  // Make our surface the size of what will ultimately be drawn to it.
  // (either the full image size, or the restricted region)
  RefPtr<DrawTarget> dt = gfxPlatform::GetPlatform()->
    CreateOffscreenContentDrawTarget(aSize, SurfaceFormat::B8G8R8A8);
  if (!dt || !dt->IsValid()) {
    NS_ERROR("Could not create a DrawTarget");
    return nullptr;
  }

  RefPtr<gfxContext> context = gfxContext::ForDrawTarget(dt);
  MOZ_ASSERT(context); // already checked the draw target above

  auto result = Draw(context, aSize, ImageRegion::Create(aSize),
                     aWhichFrame, Filter::POINT, Nothing(), aFlags);

  return result == DrawResult::SUCCESS ? dt->Snapshot() : nullptr;
}
Example #2
0
already_AddRefed<DrawTarget>
gfxAlphaBoxBlur::InitDrawTarget(const DrawTarget* aReferenceDT,
                                const Rect& aRect,
                                const IntSize& aSpreadRadius,
                                const IntSize& aBlurRadius,
                                const Rect* aDirtyRect,
                                const Rect* aSkipRect)
{
  mBlur.Init(aRect, aSpreadRadius, aBlurRadius, aDirtyRect, aSkipRect);
  size_t blurDataSize = mBlur.GetSurfaceAllocationSize();
  if (blurDataSize == 0) {
    return nullptr;
  }

  BackendType backend = aReferenceDT->GetBackendType();

  // Check if the backend has an accelerated DrawSurfaceWithShadow.
  // Currently, only D2D1.1 supports this.
  // Otherwise, DrawSurfaceWithShadow only supports square blurs without spread.
  if (aBlurRadius.IsSquare() && aSpreadRadius.IsEmpty() &&
      backend == BackendType::DIRECT2D1_1) {
    mAccelerated = true;
    mDrawTarget =
      aReferenceDT->CreateShadowDrawTarget(mBlur.GetSize(),
                                           SurfaceFormat::A8,
                                           AlphaBoxBlur::CalculateBlurSigma(aBlurRadius.width));
  } else {
    // Make an alpha-only surface to draw on. We will play with the data after
    // everything is drawn to create a blur effect.
    mData = static_cast<uint8_t*>(calloc(1, blurDataSize));
    if (!mData) {
      return nullptr;
    }
    mDrawTarget =
      Factory::DoesBackendSupportDataDrawtarget(backend) ?
        Factory::CreateDrawTargetForData(backend,
                                         mData,
                                         mBlur.GetSize(),
                                         mBlur.GetStride(),
                                         SurfaceFormat::A8) :
        gfxPlatform::CreateDrawTargetForData(mData,
                                             mBlur.GetSize(),
                                             mBlur.GetStride(),
                                             SurfaceFormat::A8);
  }

  if (!mDrawTarget || !mDrawTarget->IsValid()) {
    return nullptr;
  }
  mDrawTarget->SetTransform(Matrix::Translation(-mBlur.GetRect().TopLeft()));
  return do_AddRef(mDrawTarget);
}
void
WinCompositorWidget::ClearTransparentWindow()
{
  if (!mTransparentSurface) {
    return;
  }

  EnsureTransparentSurface();

  IntSize size = mTransparentSurface->GetSize();
  if (!size.IsEmpty()) {
    RefPtr<DrawTarget> drawTarget = gfxPlatform::GetPlatform()->
      CreateDrawTargetForSurface(mTransparentSurface, size);
    drawTarget->ClearRect(Rect(0, 0, size.width, size.height));
    RedrawTransparentWindow();
  }
}
Example #4
0
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));
}
Example #5
0
already_AddRefed<DrawTarget>
gfxAlphaBoxBlur::InitDrawTarget(const DrawTarget* aReferenceDT,
                                const Rect& aRect,
                                const IntSize& aSpreadRadius,
                                const IntSize& aBlurRadius,
                                const Rect* aDirtyRect,
                                const Rect* aSkipRect,
                                bool aUseHardwareAccel)
{
  mBlur.Init(aRect, aSpreadRadius, aBlurRadius, aDirtyRect, aSkipRect);
  size_t blurDataSize = mBlur.GetSurfaceAllocationSize();
  if (blurDataSize == 0) {
    return nullptr;
  }

  BackendType backend = aReferenceDT->GetBackendType();

  // Check if the backend has an accelerated DrawSurfaceWithShadow.
  // Currently, only D2D1.1 supports this.
  // Otherwise, DrawSurfaceWithShadow only supports square blurs without spread.
  // When blurring small draw targets such as short spans text, the cost of
  // creating and flushing an accelerated draw target may exceed the speedup
  // gained from the faster blur. It's up to the users of this blur
  // to determine whether they want to use hardware acceleration.
  if (aBlurRadius.IsSquare() && aSpreadRadius.IsEmpty() &&
      aUseHardwareAccel &&
      backend == BackendType::DIRECT2D1_1) {
    mAccelerated = true;
    mDrawTarget =
      aReferenceDT->CreateShadowDrawTarget(mBlur.GetSize(),
                                           SurfaceFormat::A8,
                                           AlphaBoxBlur::CalculateBlurSigma(aBlurRadius.width));
  } else {
    // Make an alpha-only surface to draw on. We will play with the data after
    // everything is drawn to create a blur effect.
    // This will be freed when the DrawTarget dies
    mData = static_cast<uint8_t*>(calloc(1, blurDataSize));
    if (!mData) {
      return nullptr;
    }
    mDrawTarget =
      Factory::DoesBackendSupportDataDrawtarget(backend) ?
        Factory::CreateDrawTargetForData(backend,
                                         mData,
                                         mBlur.GetSize(),
                                         mBlur.GetStride(),
                                         SurfaceFormat::A8) :
        gfxPlatform::CreateDrawTargetForData(mData,
                                             mBlur.GetSize(),
                                             mBlur.GetStride(),
                                             SurfaceFormat::A8);
  }

  if (!mDrawTarget || !mDrawTarget->IsValid()) {
    if (mData) {
      free(mData);
    }

    return nullptr;
  }

  if (mData) {
    mDrawTarget->AddUserData(reinterpret_cast<UserDataKey*>(mDrawTarget.get()),
                              mData,
                              free);
  }

  mDrawTarget->SetTransform(Matrix::Translation(-mBlur.GetRect().TopLeft()));
  return do_AddRef(mDrawTarget);
}
Example #6
0
nsresult nsWindowGfx::CreateIcon(imgIContainer *aContainer,
                                  bool aIsCursor,
                                  uint32_t aHotspotX,
                                  uint32_t aHotspotY,
                                  IntSize aScaledSize,
                                  HICON *aIcon) {

  MOZ_ASSERT((aScaledSize.width > 0 && aScaledSize.height > 0) ||
             (aScaledSize.width == 0 && aScaledSize.height == 0));

  // Get the image data
  RefPtr<SourceSurface> surface =
    aContainer->GetFrame(imgIContainer::FRAME_CURRENT,
                         imgIContainer::FLAG_SYNC_DECODE);
  NS_ENSURE_TRUE(surface, NS_ERROR_NOT_AVAILABLE);

  IntSize frameSize = surface->GetSize();
  if (frameSize.IsEmpty()) {
    return NS_ERROR_FAILURE;
  }

  IntSize iconSize(aScaledSize.width, aScaledSize.height);
  if (iconSize == IntSize(0, 0)) { // use frame's intrinsic size
    iconSize = frameSize;
  }

  RefPtr<DataSourceSurface> dataSurface;
  bool mappedOK;
  DataSourceSurface::MappedSurface map;

  if (iconSize != frameSize) {
    // Scale the surface
    dataSurface = Factory::CreateDataSourceSurface(iconSize,
                                                   SurfaceFormat::B8G8R8A8);
    NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
    mappedOK = dataSurface->Map(DataSourceSurface::MapType::READ_WRITE, &map);
    NS_ENSURE_TRUE(mappedOK, NS_ERROR_FAILURE);

    RefPtr<DrawTarget> dt =
      Factory::CreateDrawTargetForData(BackendType::CAIRO,
                                       map.mData,
                                       dataSurface->GetSize(),
                                       map.mStride,
                                       SurfaceFormat::B8G8R8A8);
    if (!dt) {
      gfxWarning() << "nsWindowGfx::CreatesIcon failed in CreateDrawTargetForData";
      return NS_ERROR_OUT_OF_MEMORY;
    }
    dt->DrawSurface(surface,
                    Rect(0, 0, iconSize.width, iconSize.height),
                    Rect(0, 0, frameSize.width, frameSize.height),
                    DrawSurfaceOptions(),
                    DrawOptions(1.0f, CompositionOp::OP_SOURCE));
  } else if (surface->GetFormat() != SurfaceFormat::B8G8R8A8) {
    // Convert format to SurfaceFormat::B8G8R8A8
    dataSurface = gfxUtils::
      CopySurfaceToDataSourceSurfaceWithFormat(surface,
                                               SurfaceFormat::B8G8R8A8);
    NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
    mappedOK = dataSurface->Map(DataSourceSurface::MapType::READ, &map);
  } else {
    dataSurface = surface->GetDataSurface();
    NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
    mappedOK = dataSurface->Map(DataSourceSurface::MapType::READ, &map);
  }
  NS_ENSURE_TRUE(dataSurface && mappedOK, NS_ERROR_FAILURE);
  MOZ_ASSERT(dataSurface->GetFormat() == SurfaceFormat::B8G8R8A8);

  uint8_t* data = nullptr;
  UniquePtr<uint8_t[]> autoDeleteArray;
  if (map.mStride == BytesPerPixel(dataSurface->GetFormat()) * iconSize.width) {
    // Mapped data is already packed
    data = map.mData;
  } else {
    // We can't use map.mData since the pixels are not packed (as required by
    // CreateDIBitmap, which is called under the DataToBitmap call below).
    //
    // We must unmap before calling SurfaceToPackedBGRA because it needs access
    // to the pixel data.
    dataSurface->Unmap();
    map.mData = nullptr;

    autoDeleteArray = SurfaceToPackedBGRA(dataSurface);
    data = autoDeleteArray.get();
    NS_ENSURE_TRUE(data, NS_ERROR_FAILURE);
  }

  HBITMAP bmp = DataToBitmap(data, iconSize.width, -iconSize.height, 32);
  uint8_t* a1data = Data32BitTo1Bit(data, iconSize.width, iconSize.height);
  if (map.mData) {
    dataSurface->Unmap();
  }
  if (!a1data) {
    return NS_ERROR_FAILURE;
  }

  HBITMAP mbmp = DataToBitmap(a1data, iconSize.width, -iconSize.height, 1);
  PR_Free(a1data);

  ICONINFO info = {0};
  info.fIcon = !aIsCursor;
  info.xHotspot = aHotspotX;
  info.yHotspot = aHotspotY;
  info.hbmMask = mbmp;
  info.hbmColor = bmp;

  HCURSOR icon = ::CreateIconIndirect(&info);
  ::DeleteObject(mbmp);
  ::DeleteObject(bmp);
  if (!icon)
    return NS_ERROR_FAILURE;
  *aIcon = icon;
  return NS_OK;
}
Example #7
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());
}