Bug 1685822 [wpt PR 27117] - [Import Maps] Add tests for rejecting multiple import...
[gecko.git] / dom / canvas / ImageBitmapRenderingContext.cpp
blob475a37f6a0e78e3373bce2811cc7f1dff1fb3946
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "ImageBitmapRenderingContext.h"
7 #include "mozilla/dom/ImageBitmapRenderingContextBinding.h"
8 #include "nsComponentManagerUtils.h"
9 #include "ImageContainer.h"
10 #include "ImageLayers.h"
12 namespace mozilla::dom {
14 ImageBitmapRenderingContext::ImageBitmapRenderingContext()
15 : mWidth(0), mHeight(0), mIsCapturedFrameInvalid(false) {}
17 ImageBitmapRenderingContext::~ImageBitmapRenderingContext() {
18 RemovePostRefreshObserver();
21 JSObject* ImageBitmapRenderingContext::WrapObject(
22 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
23 return ImageBitmapRenderingContext_Binding::Wrap(aCx, this, aGivenProto);
26 already_AddRefed<layers::Image>
27 ImageBitmapRenderingContext::ClipToIntrinsicSize() {
28 if (!mImage) {
29 return nullptr;
32 // If image is larger than canvas intrinsic size, clip it to the intrinsic
33 // size.
34 RefPtr<gfx::SourceSurface> surface;
35 RefPtr<layers::Image> result;
36 if (mWidth < mImage->GetSize().width || mHeight < mImage->GetSize().height) {
37 surface = MatchWithIntrinsicSize();
38 } else {
39 surface = mImage->GetAsSourceSurface();
41 if (!surface) {
42 return nullptr;
44 result =
45 new layers::SourceSurfaceImage(gfx::IntSize(mWidth, mHeight), surface);
46 return result.forget();
49 void ImageBitmapRenderingContext::TransferImageBitmap(
50 ImageBitmap& aImageBitmap) {
51 TransferFromImageBitmap(aImageBitmap);
54 void ImageBitmapRenderingContext::TransferFromImageBitmap(
55 ImageBitmap& aImageBitmap) {
56 Reset();
57 mImage = aImageBitmap.TransferAsImage();
59 if (!mImage) {
60 return;
63 if (aImageBitmap.IsWriteOnly() && mCanvasElement) {
64 mCanvasElement->SetWriteOnly();
67 Redraw(gfxRect(0, 0, mWidth, mHeight));
70 NS_IMETHODIMP
71 ImageBitmapRenderingContext::SetDimensions(int32_t aWidth, int32_t aHeight) {
72 mWidth = aWidth;
73 mHeight = aHeight;
74 return NS_OK;
77 NS_IMETHODIMP
78 ImageBitmapRenderingContext::InitializeWithDrawTarget(
79 nsIDocShell* aDocShell, NotNull<gfx::DrawTarget*> aTarget) {
80 return NS_ERROR_NOT_IMPLEMENTED;
83 already_AddRefed<gfx::DataSourceSurface>
84 ImageBitmapRenderingContext::MatchWithIntrinsicSize() {
85 RefPtr<gfx::SourceSurface> surface = mImage->GetAsSourceSurface();
86 RefPtr<gfx::DataSourceSurface> temp = gfx::Factory::CreateDataSourceSurface(
87 gfx::IntSize(mWidth, mHeight), surface->GetFormat());
88 if (!temp) {
89 return nullptr;
92 gfx::DataSourceSurface::ScopedMap map(temp,
93 gfx::DataSourceSurface::READ_WRITE);
94 if (!map.IsMapped()) {
95 return nullptr;
98 RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateDrawTargetForData(
99 gfxPlatform::GetPlatform()->GetSoftwareBackend(), map.GetData(),
100 temp->GetSize(), map.GetStride(), temp->GetFormat());
101 if (!dt || !dt->IsValid()) {
102 gfxWarning()
103 << "ImageBitmapRenderingContext::MatchWithIntrinsicSize failed";
104 return nullptr;
107 dt->ClearRect(gfx::Rect(0, 0, mWidth, mHeight));
108 dt->CopySurface(
109 surface,
110 gfx::IntRect(0, 0, surface->GetSize().width, surface->GetSize().height),
111 gfx::IntPoint(0, 0));
113 return temp.forget();
116 mozilla::UniquePtr<uint8_t[]> ImageBitmapRenderingContext::GetImageBuffer(
117 int32_t* aFormat) {
118 *aFormat = 0;
120 if (!mImage) {
121 return nullptr;
124 RefPtr<gfx::SourceSurface> surface = mImage->GetAsSourceSurface();
125 RefPtr<gfx::DataSourceSurface> data = surface->GetDataSurface();
126 if (!data) {
127 return nullptr;
130 if (data->GetSize() != gfx::IntSize(mWidth, mHeight)) {
131 data = MatchWithIntrinsicSize();
132 if (!data) {
133 return nullptr;
137 *aFormat = imgIEncoder::INPUT_FORMAT_HOSTARGB;
138 return gfx::SurfaceToPackedBGRA(data);
141 NS_IMETHODIMP
142 ImageBitmapRenderingContext::GetInputStream(const char* aMimeType,
143 const nsAString& aEncoderOptions,
144 nsIInputStream** aStream) {
145 nsCString enccid("@mozilla.org/image/encoder;2?type=");
146 enccid += aMimeType;
147 nsCOMPtr<imgIEncoder> encoder = do_CreateInstance(enccid.get());
148 if (!encoder) {
149 return NS_ERROR_FAILURE;
152 int32_t format = 0;
153 UniquePtr<uint8_t[]> imageBuffer = GetImageBuffer(&format);
154 if (!imageBuffer) {
155 return NS_ERROR_FAILURE;
158 return ImageEncoder::GetInputStream(mWidth, mHeight, imageBuffer.get(),
159 format, encoder, aEncoderOptions,
160 aStream);
163 already_AddRefed<mozilla::gfx::SourceSurface>
164 ImageBitmapRenderingContext::GetSurfaceSnapshot(
165 gfxAlphaType* const aOutAlphaType) {
166 if (!mImage) {
167 return nullptr;
170 if (aOutAlphaType) {
171 *aOutAlphaType =
172 (GetIsOpaque() ? gfxAlphaType::Opaque : gfxAlphaType::Premult);
175 RefPtr<gfx::SourceSurface> surface = mImage->GetAsSourceSurface();
176 if (surface->GetSize() != gfx::IntSize(mWidth, mHeight)) {
177 return MatchWithIntrinsicSize();
180 return surface.forget();
183 void ImageBitmapRenderingContext::SetOpaqueValueFromOpaqueAttr(
184 bool aOpaqueAttrValue) {
185 // ignored
188 bool ImageBitmapRenderingContext::GetIsOpaque() { return false; }
190 NS_IMETHODIMP
191 ImageBitmapRenderingContext::Reset() {
192 if (mCanvasElement) {
193 mCanvasElement->InvalidateCanvas();
196 mImage = nullptr;
197 mIsCapturedFrameInvalid = false;
198 return NS_OK;
201 already_AddRefed<layers::Layer> ImageBitmapRenderingContext::GetCanvasLayer(
202 nsDisplayListBuilder* aBuilder, Layer* aOldLayer, LayerManager* aManager) {
203 if (!mImage) {
204 // No DidTransactionCallback will be received, so mark the context clean
205 // now so future invalidations will be dispatched.
206 MarkContextClean();
207 return nullptr;
210 RefPtr<layers::ImageLayer> imageLayer;
212 if (aOldLayer) {
213 imageLayer = static_cast<layers::ImageLayer*>(aOldLayer);
214 } else {
215 imageLayer = aManager->CreateImageLayer();
218 RefPtr<layers::ImageContainer> imageContainer = imageLayer->GetContainer();
219 if (!imageContainer) {
220 imageContainer = LayerManager::CreateImageContainer();
221 imageLayer->SetContainer(imageContainer);
224 AutoTArray<layers::ImageContainer::NonOwningImage, 1> imageList;
225 RefPtr<layers::Image> image = ClipToIntrinsicSize();
226 if (!image) {
227 return nullptr;
229 imageList.AppendElement(layers::ImageContainer::NonOwningImage(image));
230 imageContainer->SetCurrentImages(imageList);
232 return imageLayer.forget();
235 bool ImageBitmapRenderingContext::UpdateWebRenderCanvasData(
236 nsDisplayListBuilder* aBuilder, WebRenderCanvasData* aCanvasData) {
237 if (!mImage) {
238 // No DidTransactionCallback will be received, so mark the context clean
239 // now so future invalidations will be dispatched.
240 MarkContextClean();
241 return false;
244 RefPtr<layers::ImageContainer> imageContainer =
245 aCanvasData->GetImageContainer();
246 AutoTArray<layers::ImageContainer::NonOwningImage, 1> imageList;
247 RefPtr<layers::Image> image = ClipToIntrinsicSize();
248 if (!image) {
249 return false;
252 imageList.AppendElement(layers::ImageContainer::NonOwningImage(image));
253 imageContainer->SetCurrentImages(imageList);
254 return true;
257 void ImageBitmapRenderingContext::MarkContextClean() {}
259 NS_IMETHODIMP
260 ImageBitmapRenderingContext::Redraw(const gfxRect& aDirty) {
261 mIsCapturedFrameInvalid = true;
263 if (mOffscreenCanvas) {
264 RefPtr<layers::ImageContainer> imageContainer =
265 mOffscreenCanvas->GetImageContainer();
266 if (imageContainer) {
267 RefPtr<layers::Image> image = ClipToIntrinsicSize();
268 if (image) {
269 AutoTArray<layers::ImageContainer::NonOwningImage, 1> imageList;
270 imageList.AppendElement(layers::ImageContainer::NonOwningImage(image));
271 imageContainer->SetCurrentImages(imageList);
272 } else {
273 imageContainer->ClearAllImages();
276 mOffscreenCanvas->CommitFrameToCompositor();
279 if (!mCanvasElement) {
280 return NS_OK;
283 mozilla::gfx::Rect rect = ToRect(aDirty);
284 mCanvasElement->InvalidateCanvasContent(&rect);
285 return NS_OK;
288 NS_IMETHODIMP
289 ImageBitmapRenderingContext::SetIsIPC(bool aIsIPC) { return NS_OK; }
291 void ImageBitmapRenderingContext::DidRefresh() {}
293 void ImageBitmapRenderingContext::MarkContextCleanForFrameCapture() {
294 mIsCapturedFrameInvalid = false;
297 bool ImageBitmapRenderingContext::IsContextCleanForFrameCapture() {
298 return !mIsCapturedFrameInvalid;
301 NS_IMPL_CYCLE_COLLECTING_ADDREF(ImageBitmapRenderingContext)
302 NS_IMPL_CYCLE_COLLECTING_RELEASE(ImageBitmapRenderingContext)
304 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ImageBitmapRenderingContext,
305 mCanvasElement, mOffscreenCanvas)
307 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ImageBitmapRenderingContext)
308 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
309 NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal)
310 NS_INTERFACE_MAP_ENTRY(nsISupports)
311 NS_INTERFACE_MAP_END
313 } // namespace mozilla::dom