Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/image/DecoderFactory.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 "DecoderFactory.h"
7
8
#include "nsMimeTypes.h"
9
#include "mozilla/RefPtr.h"
10
11
#include "AnimationSurfaceProvider.h"
12
#include "Decoder.h"
13
#include "DecodedSurfaceProvider.h"
14
#include "IDecodingTask.h"
15
#include "ImageOps.h"
16
#include "nsPNGDecoder.h"
17
#include "nsGIFDecoder2.h"
18
#include "nsJPEGDecoder.h"
19
#include "nsBMPDecoder.h"
20
#include "nsICODecoder.h"
21
#include "nsIconDecoder.h"
22
23
namespace mozilla {
24
25
using namespace gfx;
26
27
namespace image {
28
29
/* static */ DecoderType
30
DecoderFactory::GetDecoderType(const char* aMimeType)
31
0
{
32
0
  // By default we don't know.
33
0
  DecoderType type = DecoderType::UNKNOWN;
34
0
35
0
  // PNG
36
0
  if (!strcmp(aMimeType, IMAGE_PNG)) {
37
0
    type = DecoderType::PNG;
38
0
  } else if (!strcmp(aMimeType, IMAGE_X_PNG)) {
39
0
    type = DecoderType::PNG;
40
0
  } else if (!strcmp(aMimeType, IMAGE_APNG)) {
41
0
    type = DecoderType::PNG;
42
0
43
0
  // GIF
44
0
  } else if (!strcmp(aMimeType, IMAGE_GIF)) {
45
0
    type = DecoderType::GIF;
46
0
47
0
  // JPEG
48
0
  } else if (!strcmp(aMimeType, IMAGE_JPEG)) {
49
0
    type = DecoderType::JPEG;
50
0
  } else if (!strcmp(aMimeType, IMAGE_PJPEG)) {
51
0
    type = DecoderType::JPEG;
52
0
  } else if (!strcmp(aMimeType, IMAGE_JPG)) {
53
0
    type = DecoderType::JPEG;
54
0
55
0
  // BMP
56
0
  } else if (!strcmp(aMimeType, IMAGE_BMP)) {
57
0
    type = DecoderType::BMP;
58
0
  } else if (!strcmp(aMimeType, IMAGE_BMP_MS)) {
59
0
    type = DecoderType::BMP;
60
0
61
0
  // ICO
62
0
  } else if (!strcmp(aMimeType, IMAGE_ICO)) {
63
0
    type = DecoderType::ICO;
64
0
  } else if (!strcmp(aMimeType, IMAGE_ICO_MS)) {
65
0
    type = DecoderType::ICO;
66
0
67
0
  // Icon
68
0
  } else if (!strcmp(aMimeType, IMAGE_ICON_MS)) {
69
0
    type = DecoderType::ICON;
70
0
  }
71
0
72
0
  return type;
73
0
}
74
75
/* static */ already_AddRefed<Decoder>
76
DecoderFactory::GetDecoder(DecoderType aType,
77
                           RasterImage* aImage,
78
                           bool aIsRedecode)
79
0
{
80
0
  RefPtr<Decoder> decoder;
81
0
82
0
  switch (aType) {
83
0
    case DecoderType::PNG:
84
0
      decoder = new nsPNGDecoder(aImage);
85
0
      break;
86
0
    case DecoderType::GIF:
87
0
      decoder = new nsGIFDecoder2(aImage);
88
0
      break;
89
0
    case DecoderType::JPEG:
90
0
      // If we have all the data we don't want to waste cpu time doing
91
0
      // a progressive decode.
92
0
      decoder = new nsJPEGDecoder(aImage,
93
0
                                  aIsRedecode ? Decoder::SEQUENTIAL
94
0
                                              : Decoder::PROGRESSIVE);
95
0
      break;
96
0
    case DecoderType::BMP:
97
0
      decoder = new nsBMPDecoder(aImage);
98
0
      break;
99
0
    case DecoderType::ICO:
100
0
      decoder = new nsICODecoder(aImage);
101
0
      break;
102
0
    case DecoderType::ICON:
103
0
      decoder = new nsIconDecoder(aImage);
104
0
      break;
105
0
    default:
106
0
      MOZ_ASSERT_UNREACHABLE("Unknown decoder type");
107
0
  }
108
0
109
0
  return decoder.forget();
110
0
}
111
112
/* static */ nsresult
113
DecoderFactory::CreateDecoder(DecoderType aType,
114
                              NotNull<RasterImage*> aImage,
115
                              NotNull<SourceBuffer*> aSourceBuffer,
116
                              const IntSize& aIntrinsicSize,
117
                              const IntSize& aOutputSize,
118
                              DecoderFlags aDecoderFlags,
119
                              SurfaceFlags aSurfaceFlags,
120
                              IDecodingTask** aOutTask)
121
0
{
122
0
  if (aType == DecoderType::UNKNOWN) {
123
0
    return NS_ERROR_INVALID_ARG;
124
0
  }
125
0
126
0
  // Create an anonymous decoder. Interaction with the SurfaceCache and the
127
0
  // owning RasterImage will be mediated by DecodedSurfaceProvider.
128
0
  RefPtr<Decoder> decoder =
129
0
    GetDecoder(aType, nullptr, bool(aDecoderFlags & DecoderFlags::IS_REDECODE));
130
0
  MOZ_ASSERT(decoder, "Should have a decoder now");
131
0
132
0
  // Initialize the decoder.
133
0
  decoder->SetMetadataDecode(false);
134
0
  decoder->SetIterator(aSourceBuffer->Iterator());
135
0
  decoder->SetOutputSize(aOutputSize);
136
0
  decoder->SetDecoderFlags(aDecoderFlags | DecoderFlags::FIRST_FRAME_ONLY);
137
0
  decoder->SetSurfaceFlags(aSurfaceFlags);
138
0
139
0
  nsresult rv = decoder->Init();
140
0
  if (NS_FAILED(rv)) {
141
0
    return NS_ERROR_FAILURE;
142
0
  }
143
0
144
0
  // Create a DecodedSurfaceProvider which will manage the decoding process and
145
0
  // make this decoder's output available in the surface cache.
146
0
  SurfaceKey surfaceKey =
147
0
    RasterSurfaceKey(aOutputSize, aSurfaceFlags, PlaybackType::eStatic);
148
0
  auto provider = MakeNotNull<RefPtr<DecodedSurfaceProvider>>(
149
0
    aImage, surfaceKey, WrapNotNull(decoder));
150
0
  if (aDecoderFlags & DecoderFlags::CANNOT_SUBSTITUTE) {
151
0
    provider->Availability().SetCannotSubstitute();
152
0
  }
153
0
154
0
  // Attempt to insert the surface provider into the surface cache right away so
155
0
  // we won't trigger any more decoders with the same parameters.
156
0
  switch (SurfaceCache::Insert(provider)) {
157
0
    case InsertOutcome::SUCCESS:
158
0
      break;
159
0
    case InsertOutcome::FAILURE_ALREADY_PRESENT:
160
0
      return NS_ERROR_ALREADY_INITIALIZED;
161
0
    default:
162
0
      return NS_ERROR_FAILURE;
163
0
  }
164
0
165
0
  // Return the surface provider in its IDecodingTask guise.
166
0
  RefPtr<IDecodingTask> task = provider.get();
167
0
  task.forget(aOutTask);
168
0
  return NS_OK;
169
0
}
170
171
/* static */ nsresult
172
DecoderFactory::CreateAnimationDecoder(DecoderType aType,
173
                                       NotNull<RasterImage*> aImage,
174
                                       NotNull<SourceBuffer*> aSourceBuffer,
175
                                       const IntSize& aIntrinsicSize,
176
                                       DecoderFlags aDecoderFlags,
177
                                       SurfaceFlags aSurfaceFlags,
178
                                       size_t aCurrentFrame,
179
                                       IDecodingTask** aOutTask)
180
0
{
181
0
  if (aType == DecoderType::UNKNOWN) {
182
0
    return NS_ERROR_INVALID_ARG;
183
0
  }
184
0
185
0
  MOZ_ASSERT(aType == DecoderType::GIF || aType == DecoderType::PNG,
186
0
             "Calling CreateAnimationDecoder for non-animating DecoderType");
187
0
188
0
  // Create an anonymous decoder. Interaction with the SurfaceCache and the
189
0
  // owning RasterImage will be mediated by AnimationSurfaceProvider.
190
0
  RefPtr<Decoder> decoder = GetDecoder(aType, nullptr, /* aIsRedecode = */ true);
191
0
  MOZ_ASSERT(decoder, "Should have a decoder now");
192
0
193
0
  // Initialize the decoder.
194
0
  decoder->SetMetadataDecode(false);
195
0
  decoder->SetIterator(aSourceBuffer->Iterator());
196
0
  decoder->SetDecoderFlags(aDecoderFlags | DecoderFlags::IS_REDECODE);
197
0
  decoder->SetSurfaceFlags(aSurfaceFlags);
198
0
199
0
  nsresult rv = decoder->Init();
200
0
  if (NS_FAILED(rv)) {
201
0
    return NS_ERROR_FAILURE;
202
0
  }
203
0
204
0
  // Create an AnimationSurfaceProvider which will manage the decoding process
205
0
  // and make this decoder's output available in the surface cache.
206
0
  SurfaceKey surfaceKey =
207
0
    RasterSurfaceKey(aIntrinsicSize, aSurfaceFlags, PlaybackType::eAnimated);
208
0
  auto provider = MakeNotNull<RefPtr<AnimationSurfaceProvider>>(
209
0
    aImage, surfaceKey, WrapNotNull(decoder), aCurrentFrame);
210
0
211
0
  // Attempt to insert the surface provider into the surface cache right away so
212
0
  // we won't trigger any more decoders with the same parameters.
213
0
  switch (SurfaceCache::Insert(provider)) {
214
0
    case InsertOutcome::SUCCESS:
215
0
      break;
216
0
    case InsertOutcome::FAILURE_ALREADY_PRESENT:
217
0
      return NS_ERROR_ALREADY_INITIALIZED;
218
0
    default:
219
0
      return NS_ERROR_FAILURE;
220
0
  }
221
0
222
0
  // Return the surface provider in its IDecodingTask guise.
223
0
  RefPtr<IDecodingTask> task = provider.get();
224
0
  task.forget(aOutTask);
225
0
  return NS_OK;
226
0
}
227
228
/* static */ already_AddRefed<Decoder>
229
DecoderFactory::CloneAnimationDecoder(Decoder* aDecoder)
230
0
{
231
0
  MOZ_ASSERT(aDecoder);
232
0
233
0
  // In an ideal world, we would assert aDecoder->HasAnimation() but we cannot.
234
0
  // The decoder may not have detected it is animated yet (e.g. it did not even
235
0
  // get scheduled yet, or it has only decoded the first frame and has yet to
236
0
  // rediscover it is animated).
237
0
  DecoderType type = aDecoder->GetType();
238
0
  MOZ_ASSERT(type == DecoderType::GIF || type == DecoderType::PNG,
239
0
             "Calling CloneAnimationDecoder for non-animating DecoderType");
240
0
241
0
  RefPtr<Decoder> decoder = GetDecoder(type, nullptr, /* aIsRedecode = */ true);
242
0
  MOZ_ASSERT(decoder, "Should have a decoder now");
243
0
244
0
  // Initialize the decoder.
245
0
  decoder->SetMetadataDecode(false);
246
0
  decoder->SetIterator(aDecoder->GetSourceBuffer()->Iterator());
247
0
  decoder->SetDecoderFlags(aDecoder->GetDecoderFlags());
248
0
  decoder->SetSurfaceFlags(aDecoder->GetSurfaceFlags());
249
0
250
0
  if (NS_FAILED(decoder->Init())) {
251
0
    return nullptr;
252
0
  }
253
0
254
0
  return decoder.forget();
255
0
}
256
257
/* static */ already_AddRefed<IDecodingTask>
258
DecoderFactory::CreateMetadataDecoder(DecoderType aType,
259
                                      NotNull<RasterImage*> aImage,
260
                                      NotNull<SourceBuffer*> aSourceBuffer)
261
0
{
262
0
  if (aType == DecoderType::UNKNOWN) {
263
0
    return nullptr;
264
0
  }
265
0
266
0
  RefPtr<Decoder> decoder =
267
0
    GetDecoder(aType, aImage, /* aIsRedecode = */ false);
268
0
  MOZ_ASSERT(decoder, "Should have a decoder now");
269
0
270
0
  // Initialize the decoder.
271
0
  decoder->SetMetadataDecode(true);
272
0
  decoder->SetIterator(aSourceBuffer->Iterator());
273
0
274
0
  if (NS_FAILED(decoder->Init())) {
275
0
    return nullptr;
276
0
  }
277
0
278
0
  RefPtr<IDecodingTask> task = new MetadataDecodingTask(WrapNotNull(decoder));
279
0
  return task.forget();
280
0
}
281
282
/* static */ already_AddRefed<Decoder>
283
DecoderFactory::CreateDecoderForICOResource(DecoderType aType,
284
                                            SourceBufferIterator&& aIterator,
285
                                            NotNull<nsICODecoder*> aICODecoder,
286
                                            bool aIsMetadataDecode,
287
                                            const Maybe<IntSize>& aExpectedSize,
288
                                            const Maybe<uint32_t>& aDataOffset
289
                                              /* = Nothing() */)
290
0
{
291
0
  // Create the decoder.
292
0
  RefPtr<Decoder> decoder;
293
0
  switch (aType) {
294
0
    case DecoderType::BMP:
295
0
      MOZ_ASSERT(aDataOffset);
296
0
      decoder = new nsBMPDecoder(aICODecoder->GetImageMaybeNull(), *aDataOffset);
297
0
      break;
298
0
299
0
    case DecoderType::PNG:
300
0
      MOZ_ASSERT(!aDataOffset);
301
0
      decoder = new nsPNGDecoder(aICODecoder->GetImageMaybeNull());
302
0
      break;
303
0
304
0
    default:
305
0
      MOZ_ASSERT_UNREACHABLE("Invalid ICO resource decoder type");
306
0
      return nullptr;
307
0
  }
308
0
309
0
  MOZ_ASSERT(decoder);
310
0
311
0
  // Initialize the decoder, copying settings from @aICODecoder.
312
0
  decoder->SetMetadataDecode(aIsMetadataDecode);
313
0
  decoder->SetIterator(std::forward<SourceBufferIterator>(aIterator));
314
0
  if (!aIsMetadataDecode) {
315
0
    decoder->SetOutputSize(aICODecoder->OutputSize());
316
0
  }
317
0
  if (aExpectedSize) {
318
0
    decoder->SetExpectedSize(*aExpectedSize);
319
0
  }
320
0
  decoder->SetDecoderFlags(aICODecoder->GetDecoderFlags());
321
0
  decoder->SetSurfaceFlags(aICODecoder->GetSurfaceFlags());
322
0
  decoder->SetFinalizeFrames(false);
323
0
324
0
  if (NS_FAILED(decoder->Init())) {
325
0
    return nullptr;
326
0
  }
327
0
328
0
  return decoder.forget();
329
0
}
330
331
/* static */ already_AddRefed<Decoder>
332
DecoderFactory::CreateAnonymousDecoder(DecoderType aType,
333
                                       NotNull<SourceBuffer*> aSourceBuffer,
334
                                       const Maybe<IntSize>& aOutputSize,
335
                                       DecoderFlags aDecoderFlags,
336
                                       SurfaceFlags aSurfaceFlags)
337
0
{
338
0
  if (aType == DecoderType::UNKNOWN) {
339
0
    return nullptr;
340
0
  }
341
0
342
0
  RefPtr<Decoder> decoder =
343
0
    GetDecoder(aType, /* aImage = */ nullptr, /* aIsRedecode = */ false);
344
0
  MOZ_ASSERT(decoder, "Should have a decoder now");
345
0
346
0
  // Initialize the decoder.
347
0
  decoder->SetMetadataDecode(false);
348
0
  decoder->SetIterator(aSourceBuffer->Iterator());
349
0
350
0
  // Anonymous decoders are always transient; we don't want to optimize surfaces
351
0
  // or do any other expensive work that might be wasted.
352
0
  DecoderFlags decoderFlags = DecoderFlags::IMAGE_IS_TRANSIENT;
353
0
354
0
  decoder->SetDecoderFlags(aDecoderFlags | decoderFlags);
355
0
  decoder->SetSurfaceFlags(aSurfaceFlags);
356
0
357
0
  // Set an output size for downscale-during-decode if requested.
358
0
  if (aOutputSize) {
359
0
    decoder->SetOutputSize(*aOutputSize);
360
0
  }
361
0
362
0
  if (NS_FAILED(decoder->Init())) {
363
0
    return nullptr;
364
0
  }
365
0
366
0
  return decoder.forget();
367
0
}
368
369
/* static */ already_AddRefed<Decoder>
370
DecoderFactory::CreateAnonymousMetadataDecoder(DecoderType aType,
371
                                               NotNull<SourceBuffer*> aSourceBuffer)
372
0
{
373
0
  if (aType == DecoderType::UNKNOWN) {
374
0
    return nullptr;
375
0
  }
376
0
377
0
  RefPtr<Decoder> decoder =
378
0
    GetDecoder(aType, /* aImage = */ nullptr, /* aIsRedecode = */ false);
379
0
  MOZ_ASSERT(decoder, "Should have a decoder now");
380
0
381
0
  // Initialize the decoder.
382
0
  decoder->SetMetadataDecode(true);
383
0
  decoder->SetIterator(aSourceBuffer->Iterator());
384
0
  decoder->SetDecoderFlags(DecoderFlags::FIRST_FRAME_ONLY);
385
0
386
0
  if (NS_FAILED(decoder->Init())) {
387
0
    return nullptr;
388
0
  }
389
0
390
0
  return decoder.forget();
391
0
}
392
393
} // namespace image
394
} // namespace mozilla