image/decoders/nsPNGDecoder.h
author Ryan VanderMeulen <ryanvm@gmail.com>
Mon, 12 Jan 2015 13:17:52 -0500
changeset 249210 cb26891d69e9c2c4d18a7ab648630ee5d88e8306
parent 249143 c86c43915254b769d8b63cdf997a159d32905055
child 249804 9051a8b7ee5a9876c84fb63fd5dd26755b6a1a8d
permissions -rw-r--r--
Backed out 5 changesets (bug 1079627) for causing B2G crashes on a CLOSED TREE. Backed out changeset e8ddeaeb82ee (bug 1079627) Backed out changeset 14cc155b0d6e (bug 1079627) Backed out changeset e7add8446221 (bug 1079627) Backed out changeset 44b622a479b6 (bug 1079627) Backed out changeset c86c43915254 (bug 1079627)

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef nsPNGDecoder_h
#define nsPNGDecoder_h

#include "Decoder.h"

#include "gfxTypes.h"

#include "nsCOMPtr.h"

#include "png.h"

#include "qcms.h"

namespace mozilla {
namespace image {
class RasterImage;

class nsPNGDecoder : public Decoder
{
public:
  explicit nsPNGDecoder(RasterImage& aImage);
  virtual ~nsPNGDecoder();

  virtual void InitInternal() MOZ_OVERRIDE;
  virtual void WriteInternal(const char* aBuffer, uint32_t aCount) MOZ_OVERRIDE;
  virtual Telemetry::ID SpeedHistogram() MOZ_OVERRIDE;

  void CreateFrame(png_uint_32 x_offset, png_uint_32 y_offset,
                   int32_t width, int32_t height,
                   gfx::SurfaceFormat format);
  void EndImageFrame();

  // Check if PNG is valid ICO (32bpp RGBA)
  // http://blogs.msdn.com/b/oldnewthing/archive/2010/10/22/10079192.aspx
  bool IsValidICO() const
  {
    // If there are errors in the call to png_get_IHDR, the error_callback in
    // nsPNGDecoder.cpp is called.  In this error callback we do a longjmp, so
    // we need to save the jump buffer here. Oterwise we'll end up without a
    // proper callstack.
    if (setjmp(png_jmpbuf(mPNG))) {
      // We got here from a longjmp call indirectly from png_get_IHDR
      return false;
    }

    png_uint_32
        png_width,  // Unused
        png_height; // Unused

    int png_bit_depth,
        png_color_type;

    if (png_get_IHDR(mPNG, mInfo, &png_width, &png_height, &png_bit_depth,
                     &png_color_type, nullptr, nullptr, nullptr)) {

      return ((png_color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
               png_color_type == PNG_COLOR_TYPE_RGB) &&
              png_bit_depth == 8);
    } else {
      return false;
    }
  }

public:
  png_structp mPNG;
  png_infop mInfo;
  nsIntRect mFrameRect;
  uint8_t* mCMSLine;
  uint8_t* interlacebuf;
  qcms_profile* mInProfile;
  qcms_transform* mTransform;

  gfx::SurfaceFormat format;

  // For size decodes
  uint8_t mSizeBytes[8]; // Space for width and height, both 4 bytes
  uint32_t mHeaderBytesRead;

  // whether CMS or premultiplied alpha are forced off
  uint32_t mCMSMode;

  uint8_t mChannels;
  bool mFrameHasNoAlpha;
  bool mFrameIsHidden;
  bool mDisablePremultipliedAlpha;

  struct AnimFrameInfo
  {
    AnimFrameInfo();
#ifdef PNG_APNG_SUPPORTED
    AnimFrameInfo(png_structp aPNG, png_infop aInfo);
#endif

    DisposalMethod mDispose;
    BlendMethod mBlend;
    int32_t mTimeout;
  };

  AnimFrameInfo mAnimInfo;

  // The number of frames we've finished.
  uint32_t mNumFrames;

  // libpng callbacks
  // We put these in the class so that they can access protected members.
  static void PNGAPI info_callback(png_structp png_ptr, png_infop info_ptr);
  static void PNGAPI row_callback(png_structp png_ptr, png_bytep new_row,
                                  png_uint_32 row_num, int pass);
#ifdef PNG_APNG_SUPPORTED
  static void PNGAPI frame_info_callback(png_structp png_ptr,
                                         png_uint_32 frame_num);
#endif
  static void PNGAPI end_callback(png_structp png_ptr, png_infop info_ptr);
  static void PNGAPI error_callback(png_structp png_ptr,
                                    png_const_charp error_msg);
  static void PNGAPI warning_callback(png_structp png_ptr,
                                      png_const_charp warning_msg);

  // This is defined in the PNG spec as an invariant. We use it to
  // do manual validation without libpng.
  static const uint8_t pngSignatureBytes[];
};

} // namespace image
} // namespace mozilla

#endif // nsPNGDecoder_h