Coverage Report

Created: 2018-09-25 14:53

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