/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "picture_utils.h"
#include "SkBitmap.h"
#include "SkColorPriv.h"
#include "SkHalf.h"
#include "SkImageEncoder.h"
#include "SkOSFile.h"
#include "SkOSPath.h"
#include "SkPM4fPriv.h"
#include "SkPicture.h"
#include "SkStream.h"
#include "SkString.h"

namespace sk_tools {
    void force_all_opaque(const SkBitmap& bitmap) {
        SkASSERT(kN32_SkColorType == bitmap.colorType());
        if (kN32_SkColorType == bitmap.colorType()) {
            return;
        }

        SkAutoLockPixels lock(bitmap);
        for (int y = 0; y < bitmap.height(); y++) {
            for (int x = 0; x < bitmap.width(); x++) {
                *bitmap.getAddr32(x, y) |= (SK_A32_MASK << SK_A32_SHIFT);
            }
        }
    }

    void replace_char(SkString* str, const char oldChar, const char newChar) {
        if (nullptr == str) {
            return;
        }
        for (size_t i = 0; i < str->size(); ++i) {
            if (oldChar == str->operator[](i)) {
                str->operator[](i) = newChar;
            }
        }
    }

    bool is_percentage(const char* const string) {
        SkString skString(string);
        return skString.endsWith("%");
    }

    void setup_bitmap(SkBitmap* bitmap, int width, int height) {
        bitmap->allocN32Pixels(width, height);
        bitmap->eraseColor(SK_ColorTRANSPARENT);
    }

    bool write_bitmap_to_disk(const SkBitmap& bm, const SkString& dirPath,
                              const char *subdirOrNull, const SkString& baseName) {
        SkString partialPath;
        if (subdirOrNull) {
            partialPath = SkOSPath::Join(dirPath.c_str(), subdirOrNull);
            sk_mkdir(partialPath.c_str());
        } else {
            partialPath.set(dirPath);
        }
        SkString fullPath = SkOSPath::Join(partialPath.c_str(), baseName.c_str());
        if (SkImageEncoder::EncodeFile(fullPath.c_str(), bm, SkImageEncoder::kPNG_Type, 100)) {
            return true;
        } else {
            SkDebugf("Failed to write the bitmap to %s.\n", fullPath.c_str());
            return false;
        }
    }

    sk_sp<SkData> encode_bitmap_for_png(SkBitmap bitmap) {
        const int w = bitmap.width(),
                h = bitmap.height();
        // PNG wants unpremultiplied 8-bit RGBA pixels (16-bit could work fine too).
        // We leave the gamma of these bytes unspecified, to continue the status quo,
        // which we think generally is to interpret them as sRGB.

        SkAutoTMalloc<uint32_t> rgba(w*h);

        auto srgbColorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
        if (bitmap. colorType() ==  kN32_SkColorType &&
            bitmap.colorSpace() == srgbColorSpace.get()) {
            // These are premul sRGB 8-bit pixels in SkPMColor order.
            // We want unpremul sRGB 8-bit pixels in RGBA order.  We'll get there via floats.
            bitmap.lockPixels();
            auto px = (const uint32_t*)bitmap.getPixels();
            if (!px) {
                return nullptr;
            }
            for (int i = 0; i < w*h; i++) {
                Sk4f fs = Sk4f_fromS32(px[i]);         // Convert up to linear floats.
#if defined(SK_PMCOLOR_IS_BGRA)
                fs = SkNx_shuffle<2,1,0,3>(fs);        // Shuffle to RGBA, if not there already.
#endif
                float invA = 1.0f / fs[3];
                fs = fs * Sk4f(invA, invA, invA, 1);   // Unpremultiply.
                rgba[i] = Sk4f_toS32(fs);              // Pack down to sRGB bytes.
            }

        } else if (bitmap.colorType() == kRGBA_F16_SkColorType) {
            // These are premul linear half-float pixels in RGBA order.
            // We want unpremul sRGB 8-bit pixels in RGBA order.  We'll get there via floats.
            bitmap.lockPixels();
            auto px = (const uint64_t*)bitmap.getPixels();
            if (!px) {
                return nullptr;
            }
            for (int i = 0; i < w*h; i++) {
                // Convert up to linear floats.
                Sk4f fs(SkHalfToFloat(static_cast<SkHalf>(px[i] >> (0 * 16))),
                        SkHalfToFloat(static_cast<SkHalf>(px[i] >> (1 * 16))),
                        SkHalfToFloat(static_cast<SkHalf>(px[i] >> (2 * 16))),
                        SkHalfToFloat(static_cast<SkHalf>(px[i] >> (3 * 16))));
                fs = Sk4f::Max(0.0f, Sk4f::Min(fs, 1.0f));  // Clamp
                float invA = 1.0f / fs[3];
                fs = fs * Sk4f(invA, invA, invA, 1);  // Unpremultiply.
                rgba[i] = Sk4f_toS32(fs);             // Pack down to sRGB bytes.
            }

        } else {
            // We "should" gamma correct in here but we don't.
            // We want Gold to show exactly what our clients are seeing, broken gamma.

            // Convert smaller formats up to premul linear 8-bit (in SkPMColor order).
            if (bitmap.colorType() != kN32_SkColorType) {
                SkBitmap n32;
                if (!bitmap.copyTo(&n32, kN32_SkColorType)) {
                    return nullptr;
                }
                bitmap = n32;
            }

            // Convert premul linear 8-bit to unpremul linear 8-bit RGBA.
            if (!bitmap.readPixels(SkImageInfo::Make(w,h, kRGBA_8888_SkColorType,
                                                     kUnpremul_SkAlphaType),
                                   rgba, 4*w, 0,0)) {
                return nullptr;
            }
        }

        return SkData::MakeFromMalloc(rgba.release(), w*h*sizeof(uint32_t));
    }

} // namespace sk_tools
