# - 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",
- "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",
#include "DMSrcSink.h"
#include "SamplePipeControllers.h"
#include "SkCommonFlags.h"
-#include "SkCodec.h"
#include "SkDocument.h"
#include "SkError.h"
#include "SkMultiPictureDraw.h"
#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) {}
if (fDivisor == 0) {
// Decode the full image.
SkBitmap bitmap;
- 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());
- }
+ 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);
+++ /dev/null
-# 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',
- ],
- },
- },
- ],
-}
'skia_freetype_static%': '0',
}
],
- [ 'skia_os in ["mac", "ios", "win"]', {
- # 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%': '1',
- }, {
- 'skia_libpng_static%': '0',
- }
- ],
],
# skia_giflib_static - on OS variants that normally would link giflib
# 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
+++ /dev/null
-#!/usr/bin/python
-
-# Copyright 2015 Google Inc.
-#
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""
-Copy a file.
-"""
-
-import argparse
-import os
-import shutil
-
-if __name__ == '__main__':
- parser = argparse.ArgumentParser()
- parser.add_argument('src', help='File to copy.')
- parser.add_argument('dst', help='Location to copy to.')
- args = parser.parse_args()
-
- src = os.path.abspath(os.path.join(os.getcwd(), args.src))
- dst = os.path.abspath(os.path.join(os.getcwd(), args.dst))
-
- print 'Copying from %s to %s' % (src, dst)
-
- src_dir = os.path.dirname(src)
- if not os.path.exists(src_dir):
- raise AssertionError('src directory %s does not exist!' % src_dir)
-
- if not os.path.exists(src):
- raise AssertionError('file to copy %s does not exist' % src)
-
- dst_dir = os.path.dirname(dst)
- if not os.path.exists(dst_dir):
- print 'dst directory %s does not exist! creating it!' % dst_dir
- os.makedirs(dst_dir)
-
- shutil.copyfile(src, dst)
'-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',
- ],
- }],
- ],
- 'actions': [
- {
- 'action_name': 'generate_pngconf',
- 'variables' : {
- 'prebuilt': '../third_party/externals/libpng/scripts/pnglibconf.h.prebuilt',
- 'generated': '../third_party/externals/libpng/pnglibconf.h',
- },
- 'inputs': [
- '<(prebuilt)',
- ],
- 'outputs': [
- '<(generated)',
- ],
- 'action': ['python', 'copy_file.py', '<(prebuilt)', '<(generated)'],
- },
- ],
'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',
'../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',
'variables': {
'component_libs': [
'core.gyp:core',
- 'codec.gyp:codec',
'effects.gyp:effects',
'images.gyp:images',
'opts.gyp:opts',
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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();
-}
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-/*
- * 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;
-};
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-/*
- * 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