Line data Source code
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/. */
5 :
6 : #include "ImageBitmapRenderingContext.h"
7 : #include "mozilla/dom/ImageBitmapRenderingContextBinding.h"
8 : #include "ImageContainer.h"
9 : #include "ImageLayers.h"
10 :
11 : namespace mozilla {
12 : namespace dom {
13 :
14 0 : ImageBitmapRenderingContext::ImageBitmapRenderingContext()
15 : : mWidth(0)
16 0 : , mHeight(0)
17 : {
18 0 : }
19 :
20 0 : ImageBitmapRenderingContext::~ImageBitmapRenderingContext()
21 : {
22 0 : RemovePostRefreshObserver();
23 0 : }
24 :
25 : JSObject*
26 0 : ImageBitmapRenderingContext::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
27 : {
28 0 : return ImageBitmapRenderingContextBinding::Wrap(aCx, this, aGivenProto);
29 : }
30 :
31 : already_AddRefed<layers::Image>
32 0 : ImageBitmapRenderingContext::ClipToIntrinsicSize()
33 : {
34 0 : if (!mImage) {
35 0 : return nullptr;
36 : }
37 :
38 : // If image is larger than canvas intrinsic size, clip it to the intrinsic size.
39 0 : RefPtr<gfx::SourceSurface> surface;
40 0 : RefPtr<layers::Image> result;
41 0 : if (mWidth < mImage->GetSize().width ||
42 0 : mHeight < mImage->GetSize().height) {
43 0 : surface = MatchWithIntrinsicSize();
44 : } else {
45 0 : surface = mImage->GetAsSourceSurface();
46 : }
47 0 : if (!surface) {
48 0 : return nullptr;
49 : }
50 0 : result = new layers::SourceSurfaceImage(gfx::IntSize(mWidth, mHeight), surface);
51 0 : return result.forget();
52 : }
53 :
54 : void
55 0 : ImageBitmapRenderingContext::TransferImageBitmap(ImageBitmap& aImageBitmap)
56 : {
57 0 : TransferFromImageBitmap(aImageBitmap);
58 0 : }
59 :
60 : void
61 0 : ImageBitmapRenderingContext::TransferFromImageBitmap(ImageBitmap& aImageBitmap)
62 : {
63 0 : Reset();
64 0 : mImage = aImageBitmap.TransferAsImage();
65 :
66 0 : if (!mImage) {
67 0 : return;
68 : }
69 :
70 0 : Redraw(gfxRect(0, 0, mWidth, mHeight));
71 : }
72 :
73 : int32_t
74 0 : ImageBitmapRenderingContext::GetWidth() const
75 : {
76 0 : return mWidth;
77 : }
78 :
79 : int32_t
80 0 : ImageBitmapRenderingContext::GetHeight() const
81 : {
82 0 : return mHeight;
83 : }
84 :
85 : NS_IMETHODIMP
86 0 : ImageBitmapRenderingContext::SetDimensions(int32_t aWidth, int32_t aHeight)
87 : {
88 0 : mWidth = aWidth;
89 0 : mHeight = aHeight;
90 0 : return NS_OK;
91 : }
92 :
93 : NS_IMETHODIMP
94 0 : ImageBitmapRenderingContext::InitializeWithDrawTarget(nsIDocShell* aDocShell,
95 : NotNull<gfx::DrawTarget*> aTarget)
96 : {
97 0 : return NS_ERROR_NOT_IMPLEMENTED;
98 : }
99 :
100 : already_AddRefed<DataSourceSurface>
101 0 : ImageBitmapRenderingContext::MatchWithIntrinsicSize()
102 : {
103 0 : RefPtr<SourceSurface> surface = mImage->GetAsSourceSurface();
104 : RefPtr<DataSourceSurface> temp =
105 0 : Factory::CreateDataSourceSurface(IntSize(mWidth, mHeight), surface->GetFormat());
106 0 : if (!temp) {
107 0 : return nullptr;
108 : }
109 :
110 0 : DataSourceSurface::ScopedMap map(temp, DataSourceSurface::READ_WRITE);
111 0 : if (!map.IsMapped()) {
112 0 : return nullptr;
113 : }
114 :
115 : RefPtr<DrawTarget> dt =
116 0 : Factory::CreateDrawTargetForData(gfxPlatform::GetPlatform()->GetSoftwareBackend(),
117 : map.GetData(),
118 0 : temp->GetSize(),
119 : map.GetStride(),
120 0 : temp->GetFormat());
121 0 : if (!dt || !dt->IsValid()) {
122 0 : gfxWarning() << "ImageBitmapRenderingContext::MatchWithIntrinsicSize failed";
123 0 : return nullptr;
124 : }
125 :
126 :
127 0 : dt->ClearRect(Rect(0, 0, mWidth, mHeight));
128 0 : dt->CopySurface(surface,
129 0 : IntRect(0, 0, surface->GetSize().width,
130 0 : surface->GetSize().height),
131 0 : IntPoint(0, 0));
132 :
133 0 : return temp.forget();
134 : }
135 :
136 : mozilla::UniquePtr<uint8_t[]>
137 0 : ImageBitmapRenderingContext::GetImageBuffer(int32_t* aFormat)
138 : {
139 0 : *aFormat = 0;
140 :
141 0 : if (!mImage) {
142 0 : return nullptr;
143 : }
144 :
145 0 : RefPtr<SourceSurface> surface = mImage->GetAsSourceSurface();
146 0 : RefPtr<DataSourceSurface> data = surface->GetDataSurface();
147 0 : if (!data) {
148 0 : return nullptr;
149 : }
150 :
151 0 : if (data->GetSize() != IntSize(mWidth, mHeight)) {
152 0 : data = MatchWithIntrinsicSize();
153 0 : if (!data) {
154 0 : return nullptr;
155 : }
156 : }
157 :
158 0 : *aFormat = imgIEncoder::INPUT_FORMAT_HOSTARGB;
159 0 : return SurfaceToPackedBGRA(data);
160 : }
161 :
162 : NS_IMETHODIMP
163 0 : ImageBitmapRenderingContext::GetInputStream(const char* aMimeType,
164 : const char16_t* aEncoderOptions,
165 : nsIInputStream** aStream)
166 : {
167 0 : nsCString enccid("@mozilla.org/image/encoder;2?type=");
168 0 : enccid += aMimeType;
169 0 : nsCOMPtr<imgIEncoder> encoder = do_CreateInstance(enccid.get());
170 0 : if (!encoder) {
171 0 : return NS_ERROR_FAILURE;
172 : }
173 :
174 0 : int32_t format = 0;
175 0 : UniquePtr<uint8_t[]> imageBuffer = GetImageBuffer(&format);
176 0 : if (!imageBuffer) {
177 0 : return NS_ERROR_FAILURE;
178 : }
179 :
180 0 : return ImageEncoder::GetInputStream(mWidth, mHeight, imageBuffer.get(), format,
181 0 : encoder, aEncoderOptions, aStream);
182 : }
183 :
184 : already_AddRefed<mozilla::gfx::SourceSurface>
185 0 : ImageBitmapRenderingContext::GetSurfaceSnapshot(gfxAlphaType* const aOutAlphaType)
186 : {
187 0 : if (!mImage) {
188 0 : return nullptr;
189 : }
190 :
191 0 : if (aOutAlphaType) {
192 0 : *aOutAlphaType = (GetIsOpaque() ? gfxAlphaType::Opaque : gfxAlphaType::Premult);
193 : }
194 :
195 0 : RefPtr<SourceSurface> surface = mImage->GetAsSourceSurface();
196 0 : if (surface->GetSize() != IntSize(mWidth, mHeight)) {
197 0 : return MatchWithIntrinsicSize();
198 : }
199 :
200 0 : return surface.forget();
201 : }
202 :
203 : void
204 0 : ImageBitmapRenderingContext::SetIsOpaque(bool aIsOpaque)
205 : {
206 0 : }
207 :
208 : bool
209 0 : ImageBitmapRenderingContext::GetIsOpaque()
210 : {
211 0 : return false;
212 : }
213 :
214 : NS_IMETHODIMP
215 0 : ImageBitmapRenderingContext::Reset()
216 : {
217 0 : if (mCanvasElement) {
218 0 : mCanvasElement->InvalidateCanvas();
219 : }
220 :
221 0 : mImage = nullptr;
222 :
223 0 : return NS_OK;
224 : }
225 :
226 : already_AddRefed<Layer>
227 0 : ImageBitmapRenderingContext::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
228 : Layer* aOldLayer,
229 : LayerManager* aManager,
230 : bool aMirror /* = false */)
231 : {
232 0 : if (aMirror) {
233 : // Not supported for ImageBitmapRenderingContext
234 0 : return nullptr;
235 : }
236 :
237 0 : if (!mImage) {
238 : // No DidTransactionCallback will be received, so mark the context clean
239 : // now so future invalidations will be dispatched.
240 0 : MarkContextClean();
241 0 : return nullptr;
242 : }
243 :
244 0 : RefPtr<ImageLayer> imageLayer;
245 :
246 0 : if (aOldLayer) {
247 0 : imageLayer = static_cast<ImageLayer*>(aOldLayer);
248 : } else {
249 0 : imageLayer = aManager->CreateImageLayer();
250 : }
251 :
252 0 : RefPtr<ImageContainer> imageContainer = imageLayer->GetContainer();
253 0 : if (!imageContainer) {
254 0 : imageContainer = aManager->CreateImageContainer();
255 0 : imageLayer->SetContainer(imageContainer);
256 : }
257 :
258 0 : AutoTArray<ImageContainer::NonOwningImage, 1> imageList;
259 0 : RefPtr<layers::Image> image = ClipToIntrinsicSize();
260 0 : if (!image) {
261 0 : return nullptr;
262 : }
263 0 : imageList.AppendElement(ImageContainer::NonOwningImage(image));
264 0 : imageContainer->SetCurrentImages(imageList);
265 :
266 0 : return imageLayer.forget();
267 : }
268 :
269 : void
270 0 : ImageBitmapRenderingContext::MarkContextClean()
271 : {
272 0 : }
273 :
274 : NS_IMETHODIMP
275 0 : ImageBitmapRenderingContext::Redraw(const gfxRect& aDirty)
276 : {
277 0 : if (!mCanvasElement) {
278 0 : return NS_OK;
279 : }
280 :
281 0 : mozilla::gfx::Rect rect = ToRect(aDirty);
282 0 : mCanvasElement->InvalidateCanvasContent(&rect);
283 0 : return NS_OK;
284 : }
285 :
286 : NS_IMETHODIMP
287 0 : ImageBitmapRenderingContext::SetIsIPC(bool aIsIPC)
288 : {
289 0 : return NS_OK;
290 : }
291 :
292 : void
293 0 : ImageBitmapRenderingContext::DidRefresh()
294 : {
295 0 : }
296 :
297 : void
298 0 : ImageBitmapRenderingContext::MarkContextCleanForFrameCapture()
299 : {
300 0 : }
301 :
302 : bool
303 0 : ImageBitmapRenderingContext::IsContextCleanForFrameCapture()
304 : {
305 0 : return true;
306 : }
307 :
308 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(ImageBitmapRenderingContext)
309 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(ImageBitmapRenderingContext)
310 :
311 0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ImageBitmapRenderingContext,
312 : mCanvasElement,
313 : mOffscreenCanvas)
314 :
315 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ImageBitmapRenderingContext)
316 0 : NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
317 0 : NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal)
318 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
319 0 : NS_INTERFACE_MAP_END
320 :
321 : }
322 : }
|