
/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "include/core/SkCanvas.h"
#include "include/core/SkFont.h"
#include "include/core/SkImage.h"
#include "include/core/SkPath.h"
#include "include/core/SkPoint3.h"
#include "include/utils/SkShadowUtils.h"
#include "tools/Resources.h"
#include "tools/viewer/Slide.h"

////////////////////////////////////////////////////////////////////////////
// Sample to demonstrate tonal color shadows

class ShadowColorSlide : public Slide {
    SkPath    fRectPath;
    int       fZIndex;

    bool      fShowAmbient;
    bool      fShowSpot;
    bool      fUseAlt;
    bool      fShowObject;
    bool      fTwoPassColor;
    bool      fDarkBackground;

public:
    ShadowColorSlide()
        : fZIndex(8)
        , fShowAmbient(true)
        , fShowSpot(true)
        , fUseAlt(false)
        , fShowObject(true)
        , fTwoPassColor(false)
        , fDarkBackground(false) {
        fName = "ShadowColor";
    }

    void load(SkScalar w, SkScalar h) override {
        fRectPath.addRect(SkRect::MakeXYWH(-50, -50, 100, 100));
    }

    bool onChar(SkUnichar uni) override {
            bool handled = false;
            switch (uni) {
                case 'W':
                    fShowAmbient = !fShowAmbient;
                    handled = true;
                    break;
                case 'S':
                    fShowSpot = !fShowSpot;
                    handled = true;
                    break;
                case 'T':
                    fUseAlt = !fUseAlt;
                    handled = true;
                    break;
                case 'O':
                    fShowObject = !fShowObject;
                    handled = true;
                    break;
                case 'X':
                    fTwoPassColor = !fTwoPassColor;
                    handled = true;
                    break;
                case 'Z':
                    fDarkBackground = !fDarkBackground;
                    handled = true;
                    break;
                case '>':
                    fZIndex = std::min(9, fZIndex+1);
                    handled = true;
                    break;
                case '<':
                    fZIndex = std::max(0, fZIndex-1);
                    handled = true;
                    break;
                default:
                    break;
            }
            if (handled) {
                return true;
            }
            return false;
    }

    void draw(SkCanvas* canvas) override {
        const SkScalar kLightWidth = 600;
        const SkScalar kAmbientAlpha = 0.03f;
        const SkScalar kSpotAlpha = 0.25f;

        const SkScalar kZValues[10] = { 1, 2, 3, 4, 6, 8, 9, 12, 16, 24 };

        const SkColor kColors[30] = {
            // purples
            0xFF3A0072, 0xFF5D0099, 0xFF7F12B2, 0xFFA02AD1, 0xFFC245E5,
            0xFFE95AF9, 0xFFFC79F0, 0xFFFDA6F0, 0xFFFFCCF8, 0xFFFFE1F9,
            // oranges
            0xFFEA3200, 0xFFFF4E00, 0xFFFF7300, 0xFFFF9100, 0xFFFFB000,
            0xFFFFCE00, 0xFFFFE000, 0xFFFFF64D, 0xFFFFF98F, 0xFFFFFBCC,
            // teals
            0xFF004D51, 0xFF066266, 0xFF057F7F, 0xFF009999, 0xFF00B2B2,
            0xFF15CCBE, 0xFF25E5CE, 0xFF2CFFE0, 0xFF80FFEA, 0xFFB3FFF0
        };

        SkFont font;
        SkPaint paint;
        paint.setAntiAlias(true);
        if (fDarkBackground) {
            canvas->drawColor(0xFF111111);
            paint.setColor(SK_ColorWHITE);
        } else {
            canvas->drawColor(0xFFEAEAEA);
            paint.setColor(SK_ColorBLACK);
        }
        if (fTwoPassColor) {
            canvas->drawString("Two pass", 10, 15, font, paint);
        } else {
            canvas->drawString("One pass", 10, 15, font, paint);
        }

        SkPoint3 lightPos = { 75, -400, 600 };
        SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, kZValues[fZIndex]);
        SkScalar yPos = 75;

        for (int row = 0; row < 3; ++row) {
            lightPos.fX = 75;
            SkScalar xPos = 75;
            for (int col = 0; col < 10; ++col) {
                paint.setColor(kColors[10*row + col]);

                canvas->save();
                canvas->translate(xPos, yPos);
                this->drawShadowedPath(canvas, fRectPath, zPlaneParams, paint, kAmbientAlpha,
                                       lightPos, kLightWidth, kSpotAlpha);
                canvas->restore();

                lightPos.fX += 120;
                xPos += 120;
            }

            lightPos.fY += 200;
            yPos += 200;
        }
    }

private:
    void drawShadowedPath(SkCanvas* canvas, const SkPath& path,
                          const SkPoint3& zPlaneParams,
                          const SkPaint& paint, SkScalar ambientAlpha,
                          const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha) {
        if (!fShowAmbient) {
            ambientAlpha = 0;
        }
        if (!fShowSpot) {
            spotAlpha = 0;
        }
        uint32_t flags = 0;
        if (fUseAlt) {
            flags |= SkShadowFlags::kGeometricOnly_ShadowFlag;
        }

        if (fTwoPassColor) {
            SkColor ambientColor = SkColorSetARGB(ambientAlpha*255, 0, 0, 0);
            SkShadowUtils::DrawShadow(canvas, path, zPlaneParams,
                                      lightPos, lightWidth,
                                      ambientColor, SK_ColorTRANSPARENT, flags);

            if (paint.getColor() != SK_ColorBLACK) {
                SkColor color = paint.getColor();

                uint8_t max = std::max(std::max(SkColorGetR(color), SkColorGetG(color)),
                                       SkColorGetB(color));
                uint8_t min = std::min(std::min(SkColorGetR(color), SkColorGetG(color)),
                                       SkColorGetB(color));
                SkScalar luminance = 0.5f*(max + min) / 255.f;
                SkScalar alpha = (.6 - .4*luminance)*luminance*luminance + 0.3f;
                spotAlpha -= (alpha - 0.3f)*.5f;
                SkColor spotColor = SkColorSetARGB(alpha*SkColorGetA(color), SkColorGetR(color),
                                                   SkColorGetG(color), SkColorGetB(color));

                SkShadowUtils::DrawShadow(canvas, path, zPlaneParams,
                                          lightPos, lightWidth,
                                          SK_ColorTRANSPARENT, spotColor, flags);
            }

            SkColor spotGreyscale = SkColorSetARGB(spotAlpha * 255, 0, 0, 0);
            SkShadowUtils::DrawShadow(canvas, path, zPlaneParams,
                                      lightPos, lightWidth,
                                      SK_ColorTRANSPARENT, spotGreyscale, flags);
        } else {
            SkColor color = paint.getColor();
            SkColor baseAmbient = SkColorSetARGB(ambientAlpha*SkColorGetA(color),
                                                 SkColorGetR(color), SkColorGetG(color),
                                                 SkColorGetB(color));
            SkColor baseSpot = SkColorSetARGB(spotAlpha*SkColorGetA(color),
                                              SkColorGetR(color), SkColorGetG(color),
                                              SkColorGetB(color));
            SkColor tonalAmbient, tonalSpot;
            SkShadowUtils::ComputeTonalColors(baseAmbient, baseSpot, &tonalAmbient, &tonalSpot);
            SkShadowUtils::DrawShadow(canvas, path, zPlaneParams,
                                      lightPos, lightWidth,
                                      tonalAmbient, tonalSpot, flags);
        }
        if (fShowObject) {
            canvas->drawPath(path, paint);
        } else {
            SkPaint strokePaint;

            strokePaint.setColor(paint.getColor());
            strokePaint.setStyle(SkPaint::kStroke_Style);

            canvas->drawPath(path, strokePaint);
        }
    }
};

//////////////////////////////////////////////////////////////////////////////

DEF_SLIDE( return new ShadowColorSlide(); )
