diff options
-rw-r--r-- | DEPS | 8 | ||||
-rw-r--r-- | dm/DMSrcSink.cpp | 35 | ||||
-rw-r--r-- | gyp/codec.gyp | 29 | ||||
-rw-r--r-- | gyp/common_variables.gypi | 11 | ||||
-rw-r--r-- | gyp/libpng.gyp | 16 | ||||
-rw-r--r-- | gyp/skia_lib.gyp | 1 | ||||
-rw-r--r-- | include/codec/SkCodec.h | 92 | ||||
-rw-r--r-- | src/codec/SkCodec.cpp | 50 | ||||
-rw-r--r-- | src/codec/SkCodec_libpng.cpp | 492 | ||||
-rw-r--r-- | src/codec/SkCodec_libpng.h | 34 | ||||
-rw-r--r-- | src/codec/SkSwizzler.cpp | 221 | ||||
-rw-r--r-- | src/codec/SkSwizzler.h | 94 | ||||
-rw-r--r-- | third_party/libpng/LICENSE | 172 | ||||
-rw-r--r-- | third_party/libpng/README.google | 16 | ||||
-rw-r--r-- | third_party/libpng/pnglibconf.h | 210 |
15 files changed, 1468 insertions, 13 deletions
@@ -9,15 +9,17 @@ deps = { # - both Android and ChromeOS pull the same giflib; # - can use use our existing t_p/e/libjpeg instead of pulling it for Android? - "third_party/externals/angle2" : "https://chromium.googlesource.com/angle/angle.git@c415283b2bcd786e1a8c55c19ef3511eb2b3928c", - "third_party/externals/freetype" : "https://skia.googlesource.com/third_party/freetype2.git@VER-2-5-0-1", - "third_party/externals/gyp" : "https://chromium.googlesource.com/external/gyp.git@dd831fd86e7a254c696f53944333562466e453ad", + "third_party/externals/angle2" : "https://chromium.googlesource.com/angle/angle.git@c415283b2bcd786e1a8c55c19ef3511eb2b3928c", + "third_party/externals/freetype": "https://skia.googlesource.com/third_party/freetype2.git@VER-2-5-0-1", + "third_party/externals/gyp" : "https://chromium.googlesource.com/external/gyp.git@dd831fd86e7a254c696f53944333562466e453ad", "third_party/externals/harfbuzz": "https://skia.googlesource.com/third_party/harfbuzz.git@0.9.35", "third_party/externals/jsoncpp" : "https://chromium.googlesource.com/external/jsoncpp/jsoncpp.git@1afff032c83e26ddf7f2776e8b43de5ad666c1fa", "third_party/externals/libjpeg" : "https://chromium.googlesource.com/chromium/deps/libjpeg_turbo.git@82ce8a6d4ebe12a177c0c3597192f2b4f09e81c3", "third_party/externals/libwebp" : "https://chromium.googlesource.com/webm/libwebp.git@3fe91635df8734b23f3c1b9d1f0c4fa8cfaf4e39", "third_party/externals/nanomsg" : "https://skia.googlesource.com/third_party/nanomsg.git@0.4-beta", "third_party/externals/zlib" : "https://chromium.googlesource.com/chromium/src/third_party/zlib@4ba7cdd0e7bf49d671645264f839838fc56e1492", + # NOTE: If we update libpng, we may need to update the generated file at third_party/libpng/pnglibconf.h + "third_party/externals/libpng" : "git://git.code.sf.net/p/libpng/code@070a616b8275277e18ef8ee91e2ca23f7bdc67d5", "platform_tools/android/third_party/externals/expat" : "https://android.googlesource.com/platform/external/expat.git@android-4.2.2_r1.2", "platform_tools/android/third_party/externals/gif" : "https://android.googlesource.com/platform/external/giflib.git@android-4.2.2_r1.2", diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp index e67d4355e4..67f8ac6edb 100644 --- a/dm/DMSrcSink.cpp +++ b/dm/DMSrcSink.cpp @@ -1,6 +1,7 @@ #include "DMSrcSink.h" #include "SamplePipeControllers.h" #include "SkCommonFlags.h" +#include "SkCodec.h" #include "SkDocument.h" #include "SkError.h" #include "SkMultiPictureDraw.h" @@ -12,6 +13,8 @@ #include "SkStream.h" #include "SkXMLWriter.h" +DEFINE_bool(codec, false, "Use SkCodec instead of SkImageDecoder"); + namespace DM { GMSrc::GMSrc(skiagm::GMRegistry::Factory factory) : fFactory(factory) {} @@ -46,9 +49,35 @@ Error ImageSrc::draw(SkCanvas* canvas) const { if (fDivisor == 0) { // Decode the full image. SkBitmap bitmap; - if (!SkImageDecoder::DecodeMemory(encoded->data(), encoded->size(), &bitmap, - dstColorType, SkImageDecoder::kDecodePixels_Mode)) { - return SkStringPrintf("Couldn't decode %s.", fPath.c_str()); + if (FLAGS_codec) { + SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded)); + if (!codec) { + return SkStringPrintf("Couldn't decode %s.", fPath.c_str()); + } + SkImageInfo info; + if (!codec->getInfo(&info)) { + return SkStringPrintf("Couldn't getInfo %s.", fPath.c_str()); + } + info = info.makeColorType(dstColorType); + if (info.alphaType() == kUnpremul_SkAlphaType) { + // FIXME: Currently we cannot draw unpremultiplied sources. + info = info.makeAlphaType(kPremul_SkAlphaType); + } + if (!bitmap.tryAllocPixels(info)) { + return SkStringPrintf("Image(%s) is too large (%d x %d)\n", fPath.c_str(), + info.width(), info.height()); + } + SkAutoLockPixels alp(bitmap); + const SkImageGenerator::Result result = codec->getPixels(info, bitmap.getPixels(), + bitmap.rowBytes()); + if (result != SkImageGenerator::kSuccess) { + return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str()); + } + } else { + if (!SkImageDecoder::DecodeMemory(encoded->data(), encoded->size(), &bitmap, + dstColorType, SkImageDecoder::kDecodePixels_Mode)) { + return SkStringPrintf("Couldn't decode %s.", fPath.c_str()); + } } encoded.reset((SkData*)NULL); // Might as well drop this when we're done with it. canvas->drawBitmap(bitmap, 0,0); diff --git a/gyp/codec.gyp b/gyp/codec.gyp new file mode 100644 index 0000000000..b9627995ef --- /dev/null +++ b/gyp/codec.gyp @@ -0,0 +1,29 @@ +# GYP file for codec project. +{ + 'targets': [ + { + 'target_name': 'codec', + 'product_name': 'skia_codec', + 'type': 'static_library', + 'standalone_static_library': 1, + 'dependencies': [ + 'core.gyp:*', + 'libpng.gyp:libpng', + ], + 'include_dirs': [ + '../include/codec', + '../src/codec', + ], + 'sources': [ + '../src/codec/SkCodec.cpp', + '../src/codec/SkCodec_libpng.cpp', + '../src/codec/SkSwizzler.cpp', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '../include/codec', + ], + }, + }, + ], +} diff --git a/gyp/common_variables.gypi b/gyp/common_variables.gypi index 97501871a9..d089512cd3 100644 --- a/gyp/common_variables.gypi +++ b/gyp/common_variables.gypi @@ -76,10 +76,16 @@ 'skia_os%': 'android', 'skia_chrome_utils%': 0, 'skia_use_system_json%': 1, + # skia_libpng_static - instead of linking libpng with '-lpng' and + # including the headers from '/usr/include/png.h', compile and + # statically link the version of libpng in + # third_party/externals/libpng. + 'skia_libpng_static%': '0', }, { 'skia_os%': '<(skia_os)', 'skia_chrome_utils%': 1, 'skia_use_system_json%': 0, + 'skia_libpng_static%': '1', }], [ 'skia_os == "win"', { 'os_posix%': 0, @@ -129,11 +135,6 @@ # giflib in third_party/externals/giflib. 'skia_giflib_static%': '0', - # skia_libpng_static - on OS variants that normally would link libpng - # with '-lpng' and include the headers from '/usr/include/png.h', - # don't do that; instead compile and staticlly link the version of - # libpng in third_party/externals/libpng. - 'skia_libpng_static%': '0', # skia_no_fontconfig - On POSIX systems that would normally use the # SkFontHost_fontconfig interface; use the SkFontHost_linux diff --git a/gyp/libpng.gyp b/gyp/libpng.gyp index 92ff8d5e77..1ca6eef253 100644 --- a/gyp/libpng.gyp +++ b/gyp/libpng.gyp @@ -16,6 +16,8 @@ 'type': 'static_library', 'include_dirs': [ '../third_party/externals/libpng', + # Needed for generated pnglibconf.h + '../third_party/libpng', ], 'dependencies': [ 'zlib.gyp:zlib', @@ -26,16 +28,27 @@ 'direct_dependent_settings': { 'include_dirs': [ '../third_party/externals/libpng', + # Needed for generated pnglibconf.h + '../third_party/libpng', ], }, 'cflags': [ '-w', '-fvisibility=hidden', ], + 'conditions': [ + ['not arm_neon', { + 'defines': [ + # FIXME: Why is this needed? Without it, pngpriv.h sets it + # to 2 if __ARM_NEON is defined, but shouldn't __ARM_NEON + # not be defined since arm_neon is 0? + 'PNG_ARM_NEON_OPT=0', + ], + }], + ], 'sources': [ '../third_party/externals/libpng/png.c', '../third_party/externals/libpng/pngerror.c', - '../third_party/externals/libpng/pnggccrd.c', '../third_party/externals/libpng/pngget.c', '../third_party/externals/libpng/pngmem.c', '../third_party/externals/libpng/pngpread.c', @@ -45,7 +58,6 @@ '../third_party/externals/libpng/pngrutil.c', '../third_party/externals/libpng/pngset.c', '../third_party/externals/libpng/pngtrans.c', - '../third_party/externals/libpng/pngvcrd.c', '../third_party/externals/libpng/pngwio.c', '../third_party/externals/libpng/pngwrite.c', '../third_party/externals/libpng/pngwtran.c', diff --git a/gyp/skia_lib.gyp b/gyp/skia_lib.gyp index cc4984aa7f..80d4f8f5bf 100644 --- a/gyp/skia_lib.gyp +++ b/gyp/skia_lib.gyp @@ -4,6 +4,7 @@ 'variables': { 'component_libs': [ 'core.gyp:core', + 'codec.gyp:codec', 'effects.gyp:effects', 'images.gyp:images', 'opts.gyp:opts', diff --git a/include/codec/SkCodec.h b/include/codec/SkCodec.h new file mode 100644 index 0000000000..beb9cb97b3 --- /dev/null +++ b/include/codec/SkCodec.h @@ -0,0 +1,92 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkCodec_DEFINED +#define SkCodec_DEFINED + +#include "SkImageGenerator.h" +#include "SkImageInfo.h" +#include "SkSize.h" +#include "SkTemplates.h" +#include "SkTypes.h" + +class SkData; +class SkStream; + +/** + * Abstraction layer directly on top of an image codec. + */ +class SkCodec : public SkImageGenerator { +public: + /** + * If this stream represents an encoded image that we know how to decode, + * return an SkCodec that can decode it. Otherwise return NULL. + * + * If NULL is returned, the stream is deleted immediately. Otherwise, the + * SkCodec takes ownership of it, and will delete it when done with it. + */ + static SkCodec* NewFromStream(SkStream*); + + /** + * If this data represents an encoded image that we know how to decode, + * return an SkCodec that can decode it. Otherwise return NULL. + * + * Will take a ref if it returns a codec, else will not affect the data. + */ + static SkCodec* NewFromData(SkData*); + + /** + * Return a size that approximately supports the desired scale factor. + * The codec may not be able to scale efficiently to the exact scale + * factor requested, so return a size that approximates that scale. + * + * FIXME: Move to SkImageGenerator? + */ + SkISize getScaledDimensions(float desiredScale) const; + +protected: + SkCodec(const SkImageInfo&, SkStream*); + + /** + * The SkAlphaType is a conservative answer. i.e. it is possible that it + * initially returns a non-opaque answer, but completing the decode + * reveals that the image is actually opaque. + */ + bool onGetInfo(SkImageInfo* info) SK_OVERRIDE { + *info = fInfo; + return true; + } + + // Helper for subclasses. + const SkImageInfo& getOriginalInfo() { return fInfo; } + + virtual SkISize onGetScaledDimensions(float /* desiredScale */) const { + // By default, scaling is not supported. + return fInfo.dimensions(); + } + + /** + * If the stream was previously read, attempt to rewind. + * @returns: + * true + * - if the stream needed to be rewound, and the rewind + * succeeded. + * - if the stream did not need to be rewound. + * false + * - if the stream needed to be rewound, and rewind failed. + * Subclasses MUST call this function before reading the stream (e.g. in + * onGetPixels). If it returns false, onGetPixels should return + * kCouldNotRewind. + */ + bool SK_WARN_UNUSED_RESULT rewindIfNeeded(); + +private: + const SkImageInfo fInfo; + SkAutoTDelete<SkStream> fStream; + bool fNeedsRewind; +}; +#endif // SkCodec_DEFINED diff --git a/src/codec/SkCodec.cpp b/src/codec/SkCodec.cpp new file mode 100644 index 0000000000..ec36bc75e9 --- /dev/null +++ b/src/codec/SkCodec.cpp @@ -0,0 +1,50 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkCodec.h" +#include "SkData.h" +#include "SkCodec_libpng.h" +#include "SkStream.h" + +SkCodec* SkCodec::NewFromStream(SkStream* stream) { + if (!stream) { + return NULL; + } + SkAutoTDelete<SkStream> streamDeleter(stream); + const bool isPng = SkPngCodec::IsPng(stream); + // TODO: Avoid rewinding. + if (!stream->rewind()) { + return NULL; + } + if (isPng) { + streamDeleter.detach(); + return SkPngCodec::NewFromStream(stream); + } + // TODO: Check other image types. + return NULL; +} + +SkCodec* SkCodec::NewFromData(SkData* data) { + if (!data) { + return NULL; + } + return NewFromStream(SkNEW_ARGS(SkMemoryStream, (data))); +} + +SkCodec::SkCodec(const SkImageInfo& info, SkStream* stream) + : fInfo(info) + , fStream(stream) + , fNeedsRewind(false) +{} + +bool SkCodec::rewindIfNeeded() { + // Store the value of fNeedsRewind so we can update it. Next read will + // require a rewind. + const bool neededRewind = fNeedsRewind; + fNeedsRewind = true; + return !neededRewind || fStream->rewind(); +} diff --git a/src/codec/SkCodec_libpng.cpp b/src/codec/SkCodec_libpng.cpp new file mode 100644 index 0000000000..8e7ee33a95 --- /dev/null +++ b/src/codec/SkCodec_libpng.cpp @@ -0,0 +1,492 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkCodec_libpng.h" +#include "SkColorPriv.h" +#include "SkColorTable.h" +#include "SkBitmap.h" +#include "SkMath.h" +#include "SkSize.h" +#include "SkStream.h" +#include "SkSwizzler.h" + +/////////////////////////////////////////////////////////////////////////////// +// Helper macros +/////////////////////////////////////////////////////////////////////////////// + +#ifndef png_jmpbuf +# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) +#endif + +/* These were dropped in libpng >= 1.4 */ +#ifndef png_infopp_NULL + #define png_infopp_NULL NULL +#endif + +#ifndef png_bytepp_NULL + #define png_bytepp_NULL NULL +#endif + +#ifndef int_p_NULL + #define int_p_NULL NULL +#endif + +#ifndef png_flush_ptr_NULL + #define png_flush_ptr_NULL NULL +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Callback functions +/////////////////////////////////////////////////////////////////////////////// + +static void sk_error_fn(png_structp png_ptr, png_const_charp msg) { + SkDebugf("------ png error %s\n", msg); + longjmp(png_jmpbuf(png_ptr), 1); +} + +static void sk_read_fn(png_structp png_ptr, png_bytep data, + png_size_t length) { + SkStream* stream = static_cast<SkStream*>(png_get_io_ptr(png_ptr)); + const size_t bytes = stream->read(data, length); + if (bytes != length) { + // FIXME: We want to report the fact that the stream was truncated. + // One way to do that might be to pass a enum to longjmp so setjmp can + // specify the failure. + png_error(png_ptr, "Read Error!"); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Helpers +/////////////////////////////////////////////////////////////////////////////// + +class AutoCleanPng : public SkNoncopyable { +public: + AutoCleanPng(png_structp png_ptr) + : fPng_ptr(png_ptr) + , fInfo_ptr(NULL) {} + + ~AutoCleanPng() { + // fInfo_ptr will never be non-NULL unless fPng_ptr is. + if (fPng_ptr) { + png_infopp info_pp = fInfo_ptr ? &fInfo_ptr : NULL; + png_destroy_read_struct(&fPng_ptr, info_pp, png_infopp_NULL); + } + } + + void setInfoPtr(png_infop info_ptr) { + SkASSERT(NULL == fInfo_ptr); + fInfo_ptr = info_ptr; + } + + void detach() { + fPng_ptr = NULL; + fInfo_ptr = NULL; + } + +private: + png_structp fPng_ptr; + png_infop fInfo_ptr; +}; +#define AutoCleanPng(...) SK_REQUIRE_LOCAL_VAR(AutoCleanPng) + +// call only if color_type is PALETTE. Returns true if the ctable has alpha +static bool has_transparency_in_palette(png_structp png_ptr, + png_infop info_ptr) { + if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { + return false; + } + + png_bytep trans; + int num_trans; + png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); + return num_trans > 0; +} + +// Method for coverting to either an SkPMColor or a similarly packed +// unpremultiplied color. +typedef uint32_t (*PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b); + +// Note: SkColorTable claims to store SkPMColors, which is not necessarily +// the case here. +SkColorTable* decode_palette(png_structp png_ptr, png_infop info_ptr, + bool premultiply, SkAlphaType* outAlphaType) { + SkASSERT(outAlphaType != NULL); + int numPalette; + png_colorp palette; + png_bytep trans; + + if (!png_get_PLTE(png_ptr, info_ptr, &palette, &numPalette)) { + return NULL; + } + + /* BUGGY IMAGE WORKAROUND + + We hit some images (e.g. fruit_.png) who contain bytes that are == colortable_count + which is a problem since we use the byte as an index. To work around this we grow + the colortable by 1 (if its < 256) and duplicate the last color into that slot. + */ + const int colorCount = numPalette + (numPalette < 256); + // Note: These are not necessarily SkPMColors. + SkPMColor colorStorage[256]; // worst-case storage + SkPMColor* colorPtr = colorStorage; + + int numTrans; + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { + png_get_tRNS(png_ptr, info_ptr, &trans, &numTrans, NULL); + } else { + numTrans = 0; + } + + // check for bad images that might make us crash + if (numTrans > numPalette) { + numTrans = numPalette; + } + + int index = 0; + int transLessThanFF = 0; + + // Choose which function to use to create the color table. If the final destination's + // colortype is unpremultiplied, the color table will store unpremultiplied colors. + PackColorProc proc; + if (premultiply) { + proc = &SkPreMultiplyARGB; + } else { + proc = &SkPackARGB32NoCheck; + } + for (; index < numTrans; index++) { + transLessThanFF |= (int)*trans - 0xFF; + *colorPtr++ = proc(*trans++, palette->red, palette->green, palette->blue); + palette++; + } + + if (transLessThanFF < 0) { + *outAlphaType = premultiply ? kPremul_SkAlphaType : kUnpremul_SkAlphaType; + } else { + *outAlphaType = kOpaque_SkAlphaType; + } + + for (; index < numPalette; index++) { + *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette->blue); + palette++; + } + + // see BUGGY IMAGE WORKAROUND comment above + if (numPalette < 256) { + *colorPtr = colorPtr[-1]; + } + + return SkNEW_ARGS(SkColorTable, (colorStorage, colorCount)); +} + +/////////////////////////////////////////////////////////////////////////////// +// Creation +/////////////////////////////////////////////////////////////////////////////// + +#define PNG_BYTES_TO_CHECK 4 + +bool SkPngCodec::IsPng(SkStream* stream) { + char buf[PNG_BYTES_TO_CHECK]; + if (stream->read(buf, PNG_BYTES_TO_CHECK) != PNG_BYTES_TO_CHECK) { + return false; + } + if (png_sig_cmp((png_bytep) buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) { + return false; + } + return true; +} + +SkCodec* SkPngCodec::NewFromStream(SkStream* stream) { + // The image is known to be a PNG. Decode enough to know the SkImageInfo. + // FIXME: Allow silencing warnings. + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, + sk_error_fn, NULL); + if (!png_ptr) { + return NULL; + } + + AutoCleanPng autoClean(png_ptr); + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + return NULL; + } + + autoClean.setInfoPtr(info_ptr); + + // FIXME: Could we use the return value of setjmp to specify the type of + // error? + if (setjmp(png_jmpbuf(png_ptr))) { + return NULL; + } + + png_set_read_fn(png_ptr, static_cast<void*>(stream), sk_read_fn); + + // FIXME: This is where the old code hooks up the Peeker. Does it need to + // be set this early? (i.e. where are the user chunks? early in the stream, + // potentially?) + // If it does, we need to figure out a way to set it here. + + // The call to png_read_info() gives us all of the information from the + // PNG file before the first IDAT (image data chunk). + png_read_info(png_ptr, info_ptr); + png_uint_32 origWidth, origHeight; + int bitDepth, colorType; + png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, + &colorType, int_p_NULL, int_p_NULL, int_p_NULL); + + // sanity check for size + { + int64_t size = sk_64_mul(origWidth, origHeight); + // now check that if we are 4-bytes per pixel, we also don't overflow + if (size < 0 || size > (0x7FFFFFFF >> 2)) { + return NULL; + } + } + + // Tell libpng to strip 16 bit/color files down to 8 bits/color + if (bitDepth == 16) { + png_set_strip_16(png_ptr); + } +#ifdef PNG_READ_PACK_SUPPORTED + // Extract multiple pixels with bit depths of 1, 2, and 4 from a single + // byte into separate bytes (useful for paletted and grayscale images). + if (bitDepth < 8) { + png_set_packing(png_ptr); + } +#endif + // Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel. + if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) { + png_set_expand_gray_1_2_4_to_8(png_ptr); + } + + + // Now determine the default SkColorType and SkAlphaType. + SkColorType skColorType; + SkAlphaType skAlphaType; + switch (colorType) { + case PNG_COLOR_TYPE_PALETTE: + // Technically, this is true of the data, but I don't think we want + // to support it. + // skColorType = kIndex8_SkColorType; + skColorType = kN32_SkColorType; + skAlphaType = has_transparency_in_palette(png_ptr, info_ptr) ? + kUnpremul_SkAlphaType : kOpaque_SkAlphaType; + break; + case PNG_COLOR_TYPE_GRAY: + if (false) { + // FIXME: Is this the wrong default behavior? This means if the + // caller supplies the info we gave them, they'll get Alpha 8. + skColorType = kAlpha_8_SkColorType; + // FIXME: Strangely, the canonical type for Alpha 8 is Premul. + skAlphaType = kPremul_SkAlphaType; + } else { + skColorType = kN32_SkColorType; + skAlphaType = kOpaque_SkAlphaType; + } + break; + default: + // Note: This *almost* mimics the code in SkImageDecoder_libpng. + // has_transparency_in_palette makes an additional check - whether + // numTrans is greater than 0. Why does the other code not make that + // check? + if (has_transparency_in_palette(png_ptr, info_ptr) + || PNG_COLOR_TYPE_RGB_ALPHA == colorType + || PNG_COLOR_TYPE_GRAY_ALPHA == colorType) + { + skAlphaType = kUnpremul_SkAlphaType; + } else { + skAlphaType = kOpaque_SkAlphaType; + } + skColorType = kN32_SkColorType; + break; + } + + { + // FIXME: Again, this block needs to go into onGetPixels. + bool convertGrayToRGB = PNG_COLOR_TYPE_GRAY == colorType && skColorType != kAlpha_8_SkColorType; + + // Unless the user is requesting A8, convert a grayscale image into RGB. + // GRAY_ALPHA will always be converted to RGB + if (convertGrayToRGB || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) { + png_set_gray_to_rgb(png_ptr); + } + + // Add filler (or alpha) byte (after each RGB triplet) if necessary. + // FIXME: It seems like we could just use RGB as the SrcConfig here. + if (colorType == PNG_COLOR_TYPE_RGB || convertGrayToRGB) { + png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); + } + } + + // FIXME: Also need to check for sRGB (skbug.com/3471). + + SkImageInfo info = SkImageInfo::Make(origWidth, origHeight, skColorType, + skAlphaType); + SkCodec* codec = SkNEW_ARGS(SkPngCodec, (info, stream, png_ptr, info_ptr)); + autoClean.detach(); + return codec; +} + +SkPngCodec::SkPngCodec(const SkImageInfo& info, SkStream* stream, + png_structp png_ptr, png_infop info_ptr) + : INHERITED(info, stream) + , fPng_ptr(png_ptr) + , fInfo_ptr(info_ptr) {} + +SkPngCodec::~SkPngCodec() { + png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, png_infopp_NULL); +} + +/////////////////////////////////////////////////////////////////////////////// +// Getting the pixels +/////////////////////////////////////////////////////////////////////////////// + +static bool premul_and_unpremul(SkAlphaType A, SkAlphaType B) { + return kPremul_SkAlphaType == A && kUnpremul_SkAlphaType == B; +} + +static bool conversion_possible(const SkImageInfo& A, const SkImageInfo& B) { + // TODO: Support other conversions + if (A.colorType() != B.colorType()) { + return false; + } + if (A.profileType() != B.profileType()) { + return false; + } + if (A.alphaType() == B.alphaType()) { + return true; + } + return premul_and_unpremul(A.alphaType(), B.alphaType()) + || premul_and_unpremul(B.alphaType(), A.alphaType()); +} + +SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void* dst, + size_t rowBytes, SkPMColor ctable[], + int* ctableCount) { + if (!this->rewindIfNeeded()) { + return kCouldNotRewind; + } + if (requestedInfo.dimensions() != this->getOriginalInfo().dimensions()) { + return kInvalidScale; + } + if (!conversion_possible(requestedInfo, this->getOriginalInfo())) { + return kInvalidConversion; + } + + SkBitmap decodedBitmap; + // If installPixels would have failed, getPixels should have failed before + // calling onGetPixels. + SkAssertResult(decodedBitmap.installPixels(requestedInfo, dst, rowBytes)); + + // Initialize all non-trivial objects before setjmp. + SkAutoTUnref<SkColorTable> colorTable; + SkAutoTDelete<SkSwizzler> swizzler; + SkAutoMalloc storage; // Scratch memory for pre-swizzled rows. + + // FIXME: Could we use the return value of setjmp to specify the type of + // error? + if (setjmp(png_jmpbuf(fPng_ptr))) { + SkDebugf("setjmp long jump!\n"); + return kInvalidInput; + } + + // FIXME: We already retrieved this information. Store it in SkPngCodec? + png_uint_32 origWidth, origHeight; + int bitDepth, pngColorType, interlaceType; + png_get_IHDR(fPng_ptr, fInfo_ptr, &origWidth, &origHeight, &bitDepth, + &pngColorType, &interlaceType, int_p_NULL, int_p_NULL); + + const int numberPasses = (interlaceType != PNG_INTERLACE_NONE) ? + png_set_interlace_handling(fPng_ptr) : 1; + + SkSwizzler::SrcConfig sc; + bool reallyHasAlpha = false; + if (PNG_COLOR_TYPE_PALETTE == pngColorType) { + sc = SkSwizzler::kIndex; + SkAlphaType at = requestedInfo.alphaType(); + colorTable.reset(decode_palette(fPng_ptr, fInfo_ptr, + kPremul_SkAlphaType == at, + &at)); + if (!colorTable) { + return kInvalidInput; + } + + reallyHasAlpha = (at != kOpaque_SkAlphaType); + + if (at != requestedInfo.alphaType()) { + // It turns out the image is opaque. + SkASSERT(kOpaque_SkAlphaType == at); + } + } else if (kAlpha_8_SkColorType == requestedInfo.colorType()) { + // Note: we check the destination, since otherwise we would have + // told png to upscale. + SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType); + sc = SkSwizzler::kGray; + } else if (this->getOriginalInfo().alphaType() == kOpaque_SkAlphaType) { + sc = SkSwizzler::kRGBX; + } else { + sc = SkSwizzler::kRGBA; + } + const SkPMColor* colors = colorTable ? colorTable->readColors() : NULL; + // TODO: Support skipZeroes. + swizzler.reset(SkSwizzler::CreateSwizzler(sc, colors, requestedInfo, + dst, rowBytes, false)); + if (!swizzler) { + // FIXME: CreateSwizzler could fail for another reason. + return kUnimplemented; + } + + // FIXME: Here is where we should likely insert some of the modifications + // made in the factory. + png_read_update_info(fPng_ptr, fInfo_ptr); + + if (numberPasses > 1) { + const int width = requestedInfo.width(); + const int height = requestedInfo.height(); + const int bpp = SkSwizzler::BytesPerPixel(sc); + const size_t rowBytes = width * bpp; + + storage.reset(width * height * bpp); + uint8_t* const base = static_cast<uint8_t*>(storage.get()); + + for (int i = 0; i < numberPasses; i++) { + uint8_t* row = base; + for (int y = 0; y < height; y++) { + uint8_t* bmRow = row; + png_read_rows(fPng_ptr, &bmRow, png_bytepp_NULL, 1); + row += rowBytes; + } + } + + // Now swizzle it. + uint8_t* row = base; + for (int y = 0; y < height; y++) { + reallyHasAlpha |= swizzler->next(row); + row += rowBytes; + } + } else { + storage.reset(requestedInfo.width() * SkSwizzler::BytesPerPixel(sc)); + uint8_t* srcRow = static_cast<uint8_t*>(storage.get()); + for (int y = 0; y < requestedInfo.height(); y++) { + png_read_rows(fPng_ptr, &srcRow, png_bytepp_NULL, 1); + reallyHasAlpha |= swizzler->next(srcRow); + } + } + + /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ + png_read_end(fPng_ptr, fInfo_ptr); + + // FIXME: do we need substituteTranspColor? + + if (reallyHasAlpha && requestedInfo.alphaType() != kOpaque_SkAlphaType) { + // FIXME: We want to alert the caller. Is this the right way? + SkImageInfo* modInfo = const_cast<SkImageInfo*>(&requestedInfo); + *modInfo = requestedInfo.makeAlphaType(kOpaque_SkAlphaType); + } + return kSuccess; +} diff --git a/src/codec/SkCodec_libpng.h b/src/codec/SkCodec_libpng.h new file mode 100644 index 0000000000..a5327dda41 --- /dev/null +++ b/src/codec/SkCodec_libpng.h @@ -0,0 +1,34 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkCodec.h" +#include "SkImageInfo.h" + +extern "C" { + // FIXME: I'd like to force all platforms to use the same decoder, but this + // means an extra dependency on Mac/Win. + #include "png.h" +} + +class SkStream; + +class SkPngCodec : public SkCodec { +public: + // Assumes IsPng was called and returned true. + static SkCodec* NewFromStream(SkStream*); + static bool IsPng(SkStream*); +protected: + Result onGetPixels(const SkImageInfo&, void*, size_t, SkPMColor*, int*) SK_OVERRIDE; +private: + png_structp fPng_ptr; + png_infop fInfo_ptr; + + SkPngCodec(const SkImageInfo&, SkStream*, png_structp, png_infop); + ~SkPngCodec(); + + typedef SkCodec INHERITED; +}; diff --git a/src/codec/SkSwizzler.cpp b/src/codec/SkSwizzler.cpp new file mode 100644 index 0000000000..563933f13a --- /dev/null +++ b/src/codec/SkSwizzler.cpp @@ -0,0 +1,221 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkColorPriv.h" +#include "SkSwizzler.h" +#include "SkTemplates.h" + +// index + +#define A32_MASK_IN_PLACE (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT) + +static bool swizzle_index_to_n32(void* SK_RESTRICT dstRow, + const uint8_t* SK_RESTRICT src, + int width, int deltaSrc, int, const SkPMColor ctable[]) { + + SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; + SkPMColor cc = A32_MASK_IN_PLACE; + for (int x = 0; x < width; x++) { + SkPMColor c = ctable[*src]; + cc &= c; + dst[x] = c; + src += deltaSrc; + } + return cc != A32_MASK_IN_PLACE; +} + +static bool swizzle_index_to_n32_skipZ(void* SK_RESTRICT dstRow, + const uint8_t* SK_RESTRICT src, + int width, int deltaSrc, int, + const SkPMColor ctable[]) { + + SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; + SkPMColor cc = A32_MASK_IN_PLACE; + for (int x = 0; x < width; x++) { + SkPMColor c = ctable[*src]; + cc &= c; + if (c != 0) { + dst[x] = c; + } + src += deltaSrc; + } + return cc != A32_MASK_IN_PLACE; +} + +#undef A32_MASK_IN_PLACE + +// n32 +static bool swizzle_rgbx_to_n32(void* SK_RESTRICT dstRow, + const uint8_t* SK_RESTRICT src, + int width, int deltaSrc, int, const SkPMColor[]) { + SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; + for (int x = 0; x < width; x++) { + dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]); + src += deltaSrc; + } + return false; +} + +static bool swizzle_rgba_to_n32_premul(void* SK_RESTRICT dstRow, + const uint8_t* SK_RESTRICT src, + int width, int deltaSrc, int, const SkPMColor[]) { + SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; + unsigned alphaMask = 0xFF; + for (int x = 0; x < width; x++) { + unsigned alpha = src[3]; + dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); + src += deltaSrc; + alphaMask &= alpha; + } + return alphaMask != 0xFF; +} + +static bool swizzle_rgba_to_n32_unpremul(void* SK_RESTRICT dstRow, + const uint8_t* SK_RESTRICT src, + int width, int deltaSrc, int, + const SkPMColor[]) { + uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow); + unsigned alphaMask = 0xFF; + for (int x = 0; x < width; x++) { + unsigned alpha = src[3]; + dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); + src += deltaSrc; + alphaMask &= alpha; + } + return alphaMask != 0xFF; +} + +static bool swizzle_rgba_to_n32_premul_skipZ(void* SK_RESTRICT dstRow, + const uint8_t* SK_RESTRICT src, + int width, int deltaSrc, int, + const SkPMColor[]) { + SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; + unsigned alphaMask = 0xFF; + for (int x = 0; x < width; x++) { + unsigned alpha = src[3]; + if (0 != alpha) { + dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); + } + src += deltaSrc; + alphaMask &= alpha; + } + return alphaMask != 0xFF; +} + +/** + FIXME: This was my idea to cheat in order to continue taking advantage of skipping zeroes. + This would be fine for drawing normally, but not for drawing with transfer modes. Being + honest means we can draw correctly with transfer modes, with the cost of not being able + to take advantage of Android's free unwritten pages. Something to keep in mind when we + decide whether to switch to unpremul default. +static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow, + const uint8_t* SK_RESTRICT src, + int width, int deltaSrc, int, + const SkPMColor[]) { + SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; + unsigned alphaMask = 0xFF; + for (int x = 0; x < width; x++) { + unsigned alpha = src[3]; + // NOTE: We cheat here. The caller requested unpremul and skip zeroes. It's possible + // the color components are not zero, but we skip them anyway, meaning they'll remain + // zero (implied by the request to skip zeroes). + if (0 != alpha) { + dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); + } + src += deltaSrc; + alphaMask &= alpha; + } + return alphaMask != 0xFF; +} +*/ + +SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, const SkPMColor* ctable, + const SkImageInfo& info, void* dst, + size_t dstRowBytes, bool skipZeroes) { + if (info.colorType() == kUnknown_SkColorType) { + return NULL; + } + if (info.minRowBytes() > dstRowBytes) { + return NULL; + } + if (kIndex == sc && NULL == ctable) { + return NULL; + } + RowProc proc = NULL; + switch (sc) { + case kIndex: + switch (info.colorType()) { + case kN32_SkColorType: + // We assume the color premultiplied ctable (or not) as desired. + if (skipZeroes) { + proc = &swizzle_index_to_n32_skipZ; + } else { + proc = &swizzle_index_to_n32; + } + break; + + default: + break; + } + break; + case kRGBX: + // TODO: Support other swizzles. + switch (info.colorType()) { + case kN32_SkColorType: + proc = &swizzle_rgbx_to_n32; + break; + default: + break; + } + break; + case kRGBA: + switch (info.colorType()) { + case kN32_SkColorType: + if (info.alphaType() == kUnpremul_SkAlphaType) { + // Respect skipZeroes? + proc = &swizzle_rgba_to_n32_unpremul; + } else { + if (skipZeroes) { + proc = &swizzle_rgba_to_n32_premul_skipZ; + } else { + proc = &swizzle_rgba_to_n32_premul; + } + } + break; + default: + break; + } + break; + default: + break; + } + if (NULL == proc) { + return NULL; + } + return SkNEW_ARGS(SkSwizzler, (proc, ctable, BytesPerPixel(sc), info, dst, dstRowBytes)); +} + +SkSwizzler::SkSwizzler(RowProc proc, const SkPMColor* ctable, int srcBpp, + const SkImageInfo& info, void* dst, size_t rowBytes) + : fRowProc(proc) + , fColorTable(ctable) + , fSrcPixelSize(srcBpp) + , fDstInfo(info) + , fDstRow(dst) + , fDstRowBytes(rowBytes) + , fCurrY(0) +{ +} + +bool SkSwizzler::next(const uint8_t* SK_RESTRICT src) { + SkASSERT(fCurrY < fDstInfo.height()); + const bool hadAlpha = fRowProc(fDstRow, src, fDstInfo.width(), fSrcPixelSize, + fCurrY, fColorTable); + fCurrY++; + fDstRow = SkTAddOffset<void>(fDstRow, fDstRowBytes); + return hadAlpha; +} diff --git a/src/codec/SkSwizzler.h b/src/codec/SkSwizzler.h new file mode 100644 index 0000000000..0bf2ee306a --- /dev/null +++ b/src/codec/SkSwizzler.h @@ -0,0 +1,94 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkSwizzler_DEFINED +#define SkSwizzler_DEFINED + +#include "SkTypes.h" +#include "SkColor.h" +#include "SkImageInfo.h" + +class SkSwizzler : public SkNoncopyable { +public: + /** + * Enum describing the config of the source data. + */ + enum SrcConfig { + kGray, // 1 byte per pixel + kIndex, // 1 byte per pixel + kRGB, // 3 bytes per pixel + kRGBX, // 4 byes per pixel (ignore 4th) + kRGBA, // 4 bytes per pixel + kRGB_565 // 2 bytes per pixel + }; + + static int BytesPerPixel(SrcConfig sc) { + switch (sc) { + case kGray: + case kIndex: + return 1; + case kRGB: + return 3; + case kRGBX: + case kRGBA: + return 4; + case kRGB_565: + return 2; + default: + SkDebugf("invalid source config passed to BytesPerPixel\n"); + return -1; + } + } + + /** + * Create a new SkSwizzler. + * @param sc SrcConfig + * @param info dimensions() describe both the src and the dst. + * Other fields describe the dst. + * @param dst Destination to write pixels. Must match info and dstRowBytes + * @param dstRowBytes rowBytes for dst. + * @param skipZeroes Whether to skip writing zeroes. Useful if dst is + * zero-initialized. The implementation may or may not respect this. + * @return A new SkSwizzler or NULL on failure. + */ + static SkSwizzler* CreateSwizzler(SrcConfig sc, const SkPMColor* ctable, + const SkImageInfo& info, void* dst, + size_t dstRowBytes, bool skipZeroes); + /** + * Swizzle the next line. Call height times, once for each row of source. + * @param src The next row of the source data. + * @return Whether the row had non-opaque alpha. + */ + bool next(const uint8_t* SK_RESTRICT src); +private: + /** + * Method for converting raw data to Skia pixels. + * @param dstRow Row in which to write the resulting pixels. + * @param src Row of src data, in format specified by SrcConfig + * @param width Width in pixels + * @param bpp bytes per pixel of the source. + * @param y Line of source. + * @param ctable Colors (used for kIndex source). + */ + typedef bool (*RowProc)(void* SK_RESTRICT dstRow, + const uint8_t* SK_RESTRICT src, + int width, int bpp, int y, + const SkPMColor ctable[]); + + const RowProc fRowProc; + const SkPMColor* fColorTable; // Unowned pointer + const int fSrcPixelSize; + const SkImageInfo fDstInfo; + void* fDstRow; + const size_t fDstRowBytes; + int fCurrY; + + SkSwizzler(RowProc proc, const SkPMColor* ctable, int srcBpp, + const SkImageInfo& info, void* dst, size_t rowBytes); + +}; +#endif // SkSwizzler_DEFINED diff --git a/third_party/libpng/LICENSE b/third_party/libpng/LICENSE new file mode 100644 index 0000000000..ce2f3c8569 --- /dev/null +++ b/third_party/libpng/LICENSE @@ -0,0 +1,172 @@ +/* + * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + * + * If you modify libpng you may insert additional notices immediately following + * this sentence. + * + * This code is released under the libpng license. + * + * libpng versions 1.2.6, August 15, 2004, through 1.6.16, December 22, 2014, are + * Copyright (c) 2004, 2006-2014 Glenn Randers-Pehrson, and are + * distributed according to the same disclaimer and license as libpng-1.2.5 + * with the following individual added to the list of Contributing Authors: + * + * Cosmin Truta + * + * libpng versions 1.0.7, July 1, 2000, through 1.2.5, October 3, 2002, are + * Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are + * distributed according to the same disclaimer and license as libpng-1.0.6 + * with the following individuals added to the list of Contributing Authors: + * + * Simon-Pierre Cadieux + * Eric S. Raymond + * Gilles Vollant + * + * and with the following additions to the disclaimer: + * + * There is no warranty against interference with your enjoyment of the + * library or against infringement. There is no warranty that our + * efforts or the library will fulfill any of your particular purposes + * or needs. This library is provided with all faults, and the entire + * risk of satisfactory quality, performance, accuracy, and effort is with + * the user. + * + * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are + * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson, and are + * distributed according to the same disclaimer and license as libpng-0.96, + * with the following individuals added to the list of Contributing Authors: + * + * Tom Lane + * Glenn Randers-Pehrson + * Willem van Schaik + * + * libpng versions 0.89, June 1996, through 0.96, May 1997, are + * Copyright (c) 1996, 1997 Andreas Dilger + * Distributed according to the same disclaimer and license as libpng-0.88, + * with the following individuals added to the list of Contributing Authors: + * + * John Bowler + * Kevin Bracey + * Sam Bushell + * Magnus Holmgren + * Greg Roelofs + * Tom Tanner + * + * libpng versions 0.5, May 1995, through 0.88, January 1996, are + * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. + * + * For the purposes of this copyright and license, "Contributing Authors" + * is defined as the following set of individuals: + * + * Andreas Dilger + * Dave Martindale + * Guy Eric Schalnat + * Paul Schmidt + * Tim Wegner + * + * The PNG Reference Library is supplied "AS IS". The Contributing Authors + * and Group 42, Inc. disclaim all warranties, expressed or implied, + * including, without limitation, the warranties of merchantability and of + * fitness for any purpose. The Contributing Authors and Group 42, Inc. + * assume no liability for direct, indirect, incidental, special, exemplary, + * or consequential damages, which may result from the use of the PNG + * Reference Library, even if advised of the possibility of such damage. + * + * Permission is hereby granted to use, copy, modify, and distribute this + * source code, or portions hereof, for any purpose, without fee, subject + * to the following restrictions: + * + * 1. The origin of this source code must not be misrepresented. + * + * 2. Altered versions must be plainly marked as such and must not + * be misrepresented as being the original source. + * + * 3. This Copyright notice may not be removed or altered from + * any source or altered source distribution. + * + * The Contributing Authors and Group 42, Inc. specifically permit, without + * fee, and encourage the use of this source code as a component to + * supporting the PNG file format in commercial products. If you use this + * source code in a product, acknowledgment is not required but would be + * appreciated. + */ + +/* + * A "png_get_copyright" function is available, for convenient use in "about" + * boxes and the like: + * + * printf("%s", png_get_copyright(NULL)); + * + * Also, the PNG logo (in PNG format, of course) is supplied in the + * files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + */ + +/* + * Libpng is OSI Certified Open Source Software. OSI Certified is a + * certification mark of the Open Source Initiative. + */ + +/* + * The contributing authors would like to thank all those who helped + * with testing, bug fixes, and patience. This wouldn't have been + * possible without all of you. + * + * Thanks to Frank J. T. Wojcik for helping with the documentation. + */ + +/* + * Y2K compliance in libpng: + * ========================= + * + * December 22, 2014 + * + * Since the PNG Development group is an ad-hoc body, we can't make + * an official declaration. + * + * This is your unofficial assurance that libpng from version 0.71 and + * upward through 1.6.16 are Y2K compliant. It is my belief that + * earlier versions were also Y2K compliant. + * + * Libpng only has two year fields. One is a 2-byte unsigned integer + * that will hold years up to 65535. The other, which is deprecated, + * holds the date in text format, and will hold years up to 9999. + * + * The integer is + * "png_uint_16 year" in png_time_struct. + * + * The string is + * "char time_buffer[29]" in png_struct. This is no longer used + * in libpng-1.6.x and will be removed from libpng-1.7.0. + * + * There are seven time-related functions: + * png.c: png_convert_to_rfc_1123_buffer() in png.c + * (formerly png_convert_to_rfc_1123() prior to libpng-1.5.x and + * png_convert_to_rfc_1152() in error prior to libpng-0.98) + * png_convert_from_struct_tm() in pngwrite.c, called in pngwrite.c + * png_convert_from_time_t() in pngwrite.c + * png_get_tIME() in pngget.c + * png_handle_tIME() in pngrutil.c, called in pngread.c + * png_set_tIME() in pngset.c + * png_write_tIME() in pngwutil.c, called in pngwrite.c + * + * All handle dates properly in a Y2K environment. The + * png_convert_from_time_t() function calls gmtime() to convert from system + * clock time, which returns (year - 1900), which we properly convert to + * the full 4-digit year. There is a possibility that libpng applications + * are not passing 4-digit years into the png_convert_to_rfc_1123_buffer() + * function, or that they are incorrectly passing only a 2-digit year + * instead of "year - 1900" into the png_convert_from_struct_tm() function, + * but this is not under our control. The libpng documentation has always + * stated that it works with 4-digit years, and the APIs have been + * documented as such. + * + * The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned + * integer to hold the year, and can hold years as large as 65535. + * + * zlib, upon which libpng depends, is also Y2K compliant. It contains + * no date-related code. + * + * Glenn Randers-Pehrson + * libpng maintainer + * PNG Development Group + */ diff --git a/third_party/libpng/README.google b/third_party/libpng/README.google new file mode 100644 index 0000000000..4578d353cf --- /dev/null +++ b/third_party/libpng/README.google @@ -0,0 +1,16 @@ +URL: http://www.libpng.org/pub/png/libpng.html +Version: 1.6.16 +License: libpng license +License File: LICENSE, pulled out of png.h +Description: png compression/decompression library +Local Modifications: Created pnglibconf.h from pnglibconf.h.prebuilt (just a + rename). Pulled LICENSE into its own file. + +FAQ: +Q: Why does this directory exist? +A: libpng is pulled in through DEPS, but in order to build it using ninja, we + need to create pnglibconf.h. In https://codereview.chromium.org/930283002/, + we originally tried creating the file as an action, but this apparently led + to a race condition on Windows, where some builds failed to create the file + in time for other files to include it. By checking pnglibconf.h directly + into Skia, we eliminate the race condition. diff --git a/third_party/libpng/pnglibconf.h b/third_party/libpng/pnglibconf.h new file mode 100644 index 0000000000..da3b229215 --- /dev/null +++ b/third_party/libpng/pnglibconf.h @@ -0,0 +1,210 @@ +/* libpng 1.6.16 STANDARD API DEFINITION */ + +/* pnglibconf.h - library build configuration */ + +/* Libpng version 1.6.16 - December 22, 2014 */ + +/* Copyright (c) 1998-2014 Glenn Randers-Pehrson */ + +/* This code is released under the libpng license. */ +/* For conditions of distribution and use, see the disclaimer */ +/* and license in png.h */ + +/* pnglibconf.h */ +/* Machine generated file: DO NOT EDIT */ +/* Derived from: scripts/pnglibconf.dfa */ +#ifndef PNGLCONF_H +#define PNGLCONF_H +/* options */ +#define PNG_16BIT_SUPPORTED +#define PNG_ALIGNED_MEMORY_SUPPORTED +/*#undef PNG_ARM_NEON_API_SUPPORTED*/ +/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/ +#define PNG_BENIGN_ERRORS_SUPPORTED +#define PNG_BENIGN_READ_ERRORS_SUPPORTED +/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/ +#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_COLORSPACE_SUPPORTED +#define PNG_CONSOLE_IO_SUPPORTED +#define PNG_CONVERT_tIME_SUPPORTED +#define PNG_EASY_ACCESS_SUPPORTED +/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ +#define PNG_ERROR_TEXT_SUPPORTED +#define PNG_FIXED_POINT_SUPPORTED +#define PNG_FLOATING_ARITHMETIC_SUPPORTED +#define PNG_FLOATING_POINT_SUPPORTED +#define PNG_FORMAT_AFIRST_SUPPORTED +#define PNG_FORMAT_BGR_SUPPORTED +#define PNG_GAMMA_SUPPORTED +#define PNG_GET_PALETTE_MAX_SUPPORTED +#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +#define PNG_INCH_CONVERSIONS_SUPPORTED +#define PNG_INFO_IMAGE_SUPPORTED +#define PNG_IO_STATE_SUPPORTED +#define PNG_MNG_FEATURES_SUPPORTED +#define PNG_POINTER_INDEXING_SUPPORTED +#define PNG_PROGRESSIVE_READ_SUPPORTED +#define PNG_READ_16BIT_SUPPORTED +#define PNG_READ_ALPHA_MODE_SUPPORTED +#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_READ_BACKGROUND_SUPPORTED +#define PNG_READ_BGR_SUPPORTED +#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_READ_COMPOSITE_NODIV_SUPPORTED +#define PNG_READ_COMPRESSED_TEXT_SUPPORTED +#define PNG_READ_EXPAND_16_SUPPORTED +#define PNG_READ_EXPAND_SUPPORTED +#define PNG_READ_FILLER_SUPPORTED +#define PNG_READ_GAMMA_SUPPORTED +#define PNG_READ_GET_PALETTE_MAX_SUPPORTED +#define PNG_READ_GRAY_TO_RGB_SUPPORTED +#define PNG_READ_INTERLACING_SUPPORTED +#define PNG_READ_INT_FUNCTIONS_SUPPORTED +#define PNG_READ_INVERT_ALPHA_SUPPORTED +#define PNG_READ_INVERT_SUPPORTED +#define PNG_READ_OPT_PLTE_SUPPORTED +#define PNG_READ_PACKSWAP_SUPPORTED +#define PNG_READ_PACK_SUPPORTED +#define PNG_READ_QUANTIZE_SUPPORTED +#define PNG_READ_RGB_TO_GRAY_SUPPORTED +#define PNG_READ_SCALE_16_TO_8_SUPPORTED +#define PNG_READ_SHIFT_SUPPORTED +#define PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_STRIP_ALPHA_SUPPORTED +#define PNG_READ_SUPPORTED +#define PNG_READ_SWAP_ALPHA_SUPPORTED +#define PNG_READ_SWAP_SUPPORTED +#define PNG_READ_TEXT_SUPPORTED +#define PNG_READ_TRANSFORMS_SUPPORTED +#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_READ_USER_CHUNKS_SUPPORTED +#define PNG_READ_USER_TRANSFORM_SUPPORTED +#define PNG_READ_bKGD_SUPPORTED +#define PNG_READ_cHRM_SUPPORTED +#define PNG_READ_gAMA_SUPPORTED +#define PNG_READ_hIST_SUPPORTED +#define PNG_READ_iCCP_SUPPORTED +#define PNG_READ_iTXt_SUPPORTED +#define PNG_READ_oFFs_SUPPORTED +#define PNG_READ_pCAL_SUPPORTED +#define PNG_READ_pHYs_SUPPORTED +#define PNG_READ_sBIT_SUPPORTED +#define PNG_READ_sCAL_SUPPORTED +#define PNG_READ_sPLT_SUPPORTED +#define PNG_READ_sRGB_SUPPORTED +#define PNG_READ_tEXt_SUPPORTED +#define PNG_READ_tIME_SUPPORTED +#define PNG_READ_tRNS_SUPPORTED +#define PNG_READ_zTXt_SUPPORTED +/*#undef PNG_SAFE_LIMITS_SUPPORTED*/ +#define PNG_SAVE_INT_32_SUPPORTED +#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SEQUENTIAL_READ_SUPPORTED +#define PNG_SETJMP_SUPPORTED +#define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED +#define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED +#define PNG_SET_OPTION_SUPPORTED +#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SET_USER_LIMITS_SUPPORTED +#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED +#define PNG_SIMPLIFIED_READ_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_SUPPORTED +#define PNG_STDIO_SUPPORTED +#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_TEXT_SUPPORTED +#define PNG_TIME_RFC1123_SUPPORTED +#define PNG_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_USER_CHUNKS_SUPPORTED +#define PNG_USER_LIMITS_SUPPORTED +#define PNG_USER_MEM_SUPPORTED +#define PNG_USER_TRANSFORM_INFO_SUPPORTED +#define PNG_USER_TRANSFORM_PTR_SUPPORTED +#define PNG_WARNINGS_SUPPORTED +#define PNG_WRITE_16BIT_SUPPORTED +#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_WRITE_BGR_SUPPORTED +#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +#define PNG_WRITE_FILLER_SUPPORTED +#define PNG_WRITE_FILTER_SUPPORTED +#define PNG_WRITE_FLUSH_SUPPORTED +#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED +#define PNG_WRITE_INTERLACING_SUPPORTED +#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED +#define PNG_WRITE_INVERT_ALPHA_SUPPORTED +#define PNG_WRITE_INVERT_SUPPORTED +#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED +#define PNG_WRITE_PACKSWAP_SUPPORTED +#define PNG_WRITE_PACK_SUPPORTED +#define PNG_WRITE_SHIFT_SUPPORTED +#define PNG_WRITE_SUPPORTED +#define PNG_WRITE_SWAP_ALPHA_SUPPORTED +#define PNG_WRITE_SWAP_SUPPORTED +#define PNG_WRITE_TEXT_SUPPORTED +#define PNG_WRITE_TRANSFORMS_SUPPORTED +#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_WRITE_USER_TRANSFORM_SUPPORTED +#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#define PNG_WRITE_bKGD_SUPPORTED +#define PNG_WRITE_cHRM_SUPPORTED +#define PNG_WRITE_gAMA_SUPPORTED +#define PNG_WRITE_hIST_SUPPORTED +#define PNG_WRITE_iCCP_SUPPORTED +#define PNG_WRITE_iTXt_SUPPORTED +#define PNG_WRITE_oFFs_SUPPORTED +#define PNG_WRITE_pCAL_SUPPORTED +#define PNG_WRITE_pHYs_SUPPORTED +#define PNG_WRITE_sBIT_SUPPORTED +#define PNG_WRITE_sCAL_SUPPORTED +#define PNG_WRITE_sPLT_SUPPORTED +#define PNG_WRITE_sRGB_SUPPORTED +#define PNG_WRITE_tEXt_SUPPORTED +#define PNG_WRITE_tIME_SUPPORTED +#define PNG_WRITE_tRNS_SUPPORTED +#define PNG_WRITE_zTXt_SUPPORTED +#define PNG_bKGD_SUPPORTED +#define PNG_cHRM_SUPPORTED +#define PNG_gAMA_SUPPORTED +#define PNG_hIST_SUPPORTED +#define PNG_iCCP_SUPPORTED +#define PNG_iTXt_SUPPORTED +#define PNG_oFFs_SUPPORTED +#define PNG_pCAL_SUPPORTED +#define PNG_pHYs_SUPPORTED +#define PNG_sBIT_SUPPORTED +#define PNG_sCAL_SUPPORTED +#define PNG_sPLT_SUPPORTED +#define PNG_sRGB_SUPPORTED +#define PNG_tEXt_SUPPORTED +#define PNG_tIME_SUPPORTED +#define PNG_tRNS_SUPPORTED +#define PNG_zTXt_SUPPORTED +/* end of options */ +/* settings */ +#define PNG_API_RULE 0 +#define PNG_COST_SHIFT 3 +#define PNG_DEFAULT_READ_MACROS 1 +#define PNG_GAMMA_THRESHOLD_FIXED 5000 +#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE +#define PNG_INFLATE_BUF_SIZE 1024 +#define PNG_MAX_GAMMA_8 11 +#define PNG_QUANTIZE_BLUE_BITS 5 +#define PNG_QUANTIZE_GREEN_BITS 5 +#define PNG_QUANTIZE_RED_BITS 5 +#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1) +#define PNG_TEXT_Z_DEFAULT_STRATEGY 0 +#define PNG_WEIGHT_SHIFT 8 +#define PNG_ZBUF_SIZE 8192 +#define PNG_ZLIB_VERNUM 0 /* unknown */ +#define PNG_Z_DEFAULT_COMPRESSION (-1) +#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0 +#define PNG_Z_DEFAULT_STRATEGY 1 +#define PNG_sCAL_PRECISION 5 +#define PNG_sRGB_PROFILE_CHECKS 2 +/* end of settings */ +#endif /* PNGLCONF_H */ |