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

#include "Viewer.h"

#include "GMSlide.h"
#include "ImageSlide.h"
#include "Resources.h"
#include "SampleSlide.h"
#include "SKPSlide.h"

#include "GrContext.h"
#include "SkATrace.h"
#include "SkCanvas.h"
#include "SkColorSpace_Base.h"
#include "SkColorSpaceXformCanvas.h"
#include "SkCommandLineFlags.h"
#include "SkCommonFlagsPathRenderer.h"
#include "SkDashPathEffect.h"
#include "SkGraphics.h"
#include "SkImagePriv.h"
#include "SkMetaData.h"
#include "SkOnce.h"
#include "SkOSFile.h"
#include "SkOSPath.h"
#include "SkRandom.h"
#include "SkStream.h"
#include "SkSurface.h"
#include "SkSwizzle.h"
#include "SkTaskGroup.h"
#include "SkTime.h"
#include "SkVertices.h"

#include "imgui.h"

#include <stdlib.h>
#include <map>

using namespace sk_app;

using GpuPathRenderers = GrContextOptions::GpuPathRenderers;
static std::map<GpuPathRenderers, std::string> gPathRendererNames;

Application* Application::Create(int argc, char** argv, void* platformData) {
    return new Viewer(argc, argv, platformData);
}

static void on_backend_created_func(void* userData) {
    Viewer* vv = reinterpret_cast<Viewer*>(userData);

    return vv->onBackendCreated();
}

static void on_paint_handler(SkCanvas* canvas, void* userData) {
    Viewer* vv = reinterpret_cast<Viewer*>(userData);

    return vv->onPaint(canvas);
}

static bool on_touch_handler(intptr_t owner, Window::InputState state, float x, float y, void* userData)
{
    Viewer* viewer = reinterpret_cast<Viewer*>(userData);

    return viewer->onTouch(owner, state, x, y);
}

static void on_ui_state_changed_handler(const SkString& stateName, const SkString& stateValue, void* userData) {
    Viewer* viewer = reinterpret_cast<Viewer*>(userData);

    return viewer->onUIStateChanged(stateName, stateValue);
}

static bool on_mouse_handler(int x, int y, Window::InputState state, uint32_t modifiers,
                             void* userData) {
    ImGuiIO& io = ImGui::GetIO();
    io.MousePos.x = static_cast<float>(x);
    io.MousePos.y = static_cast<float>(y);
    if (Window::kDown_InputState == state) {
        io.MouseDown[0] = true;
    } else if (Window::kUp_InputState == state) {
        io.MouseDown[0] = false;
    }
    if (io.WantCaptureMouse) {
        return true;
    } else {
        Viewer* viewer = reinterpret_cast<Viewer*>(userData);
        return viewer->onMouse(x, y, state, modifiers);
    }
}

static bool on_mouse_wheel_handler(float delta, uint32_t modifiers, void* userData) {
    ImGuiIO& io = ImGui::GetIO();
    io.MouseWheel += delta;
    return true;
}

static bool on_key_handler(Window::Key key, Window::InputState state, uint32_t modifiers,
                           void* userData) {
    ImGuiIO& io = ImGui::GetIO();
    io.KeysDown[static_cast<int>(key)] = (Window::kDown_InputState == state);

    if (io.WantCaptureKeyboard) {
        return true;
    } else {
        Viewer* viewer = reinterpret_cast<Viewer*>(userData);
        return viewer->onKey(key, state, modifiers);
    }
}

static bool on_char_handler(SkUnichar c, uint32_t modifiers, void* userData) {
    ImGuiIO& io = ImGui::GetIO();
    if (io.WantTextInput) {
        if (c > 0 && c < 0x10000) {
            io.AddInputCharacter(c);
        }
        return true;
    } else {
        Viewer* viewer = reinterpret_cast<Viewer*>(userData);
        return viewer->onChar(c, modifiers);
    }
}

static DEFINE_bool2(fullscreen, f, true, "Run fullscreen.");

static DEFINE_string2(match, m, nullptr,
               "[~][^]substring[$] [...] of bench name to run.\n"
               "Multiple matches may be separated by spaces.\n"
               "~ causes a matching bench to always be skipped\n"
               "^ requires the start of the bench to match\n"
               "$ requires the end of the bench to match\n"
               "^ and $ requires an exact match\n"
               "If a bench does not match any list entry,\n"
               "it is skipped unless some list entry starts with ~");

DEFINE_string(slide, "", "Start on this sample.");
DEFINE_bool(list, false, "List samples?");

#ifdef SK_VULKAN
#    define BACKENDS_STR "\"sw\", \"gl\", and \"vk\""
#else
#    define BACKENDS_STR "\"sw\" and \"gl\""
#endif

#ifdef SK_BUILD_FOR_ANDROID
static DEFINE_string(skps, "/data/local/tmp/skia", "Directory to read skps from.");
static DEFINE_string(jpgs, "/data/local/tmp/skia", "Directory to read jpgs from.");
#else
static DEFINE_string(skps, "skps", "Directory to read skps from.");
static DEFINE_string(jpgs, "jpgs", "Directory to read jpgs from.");
#endif

static DEFINE_string2(backend, b, "sw", "Backend to use. Allowed values are " BACKENDS_STR ".");

static DEFINE_bool(atrace, false, "Enable support for using ATrace. ATrace is only supported on Android.");

DEFINE_int32(msaa, 0, "Number of subpixel samples. 0 for no HW antialiasing.");
DEFINE_pathrenderer_flag;

DEFINE_bool(instancedRendering, false, "Enable instanced rendering on GPU backends.");

const char *kBackendTypeStrings[sk_app::Window::kBackendTypeCount] = {
    "OpenGL",
#ifdef SK_VULKAN
    "Vulkan",
#endif
    "Raster"
};

static sk_app::Window::BackendType get_backend_type(const char* str) {
#ifdef SK_VULKAN
    if (0 == strcmp(str, "vk")) {
        return sk_app::Window::kVulkan_BackendType;
    } else
#endif
    if (0 == strcmp(str, "gl")) {
        return sk_app::Window::kNativeGL_BackendType;
    } else if (0 == strcmp(str, "sw")) {
        return sk_app::Window::kRaster_BackendType;
    } else {
        SkDebugf("Unknown backend type, %s, defaulting to sw.", str);
        return sk_app::Window::kRaster_BackendType;
    }
}

static SkColorSpacePrimaries gSrgbPrimaries = {
    0.64f, 0.33f,
    0.30f, 0.60f,
    0.15f, 0.06f,
    0.3127f, 0.3290f };

static SkColorSpacePrimaries gAdobePrimaries = {
    0.64f, 0.33f,
    0.21f, 0.71f,
    0.15f, 0.06f,
    0.3127f, 0.3290f };

static SkColorSpacePrimaries gP3Primaries = {
    0.680f, 0.320f,
    0.265f, 0.690f,
    0.150f, 0.060f,
    0.3127f, 0.3290f };

static SkColorSpacePrimaries gRec2020Primaries = {
    0.708f, 0.292f,
    0.170f, 0.797f,
    0.131f, 0.046f,
    0.3127f, 0.3290f };

struct NamedPrimaries {
    const char* fName;
    SkColorSpacePrimaries* fPrimaries;
} gNamedPrimaries[] = {
    { "sRGB", &gSrgbPrimaries },
    { "AdobeRGB", &gAdobePrimaries },
    { "P3", &gP3Primaries },
    { "Rec. 2020", &gRec2020Primaries },
};

static bool primaries_equal(const SkColorSpacePrimaries& a, const SkColorSpacePrimaries& b) {
    return memcmp(&a, &b, sizeof(SkColorSpacePrimaries)) == 0;
}

const char* kName = "name";
const char* kValue = "value";
const char* kOptions = "options";
const char* kSlideStateName = "Slide";
const char* kBackendStateName = "Backend";
const char* kMSAAStateName = "MSAA";
const char* kPathRendererStateName = "Path renderer";
const char* kInstancedRenderingStateName = "Instanced rendering";
const char* kSoftkeyStateName = "Softkey";
const char* kSoftkeyHint = "Please select a softkey";
const char* kFpsStateName = "FPS";
const char* kON = "ON";
const char* kOFF = "OFF";
const char* kRefreshStateName = "Refresh";

Viewer::Viewer(int argc, char** argv, void* platformData)
    : fCurrentMeasurement(0)
    , fDisplayStats(false)
    , fRefresh(false)
    , fShowImGuiDebugWindow(false)
    , fShowImGuiTestWindow(false)
    , fShowZoomWindow(false)
    , fLastImage(nullptr)
    , fBackendType(sk_app::Window::kNativeGL_BackendType)
    , fColorMode(ColorMode::kLegacy)
    , fColorSpacePrimaries(gSrgbPrimaries)
    , fZoomCenterX(0.0f)
    , fZoomCenterY(0.0f)
    , fZoomLevel(0.0f)
    , fZoomScale(SK_Scalar1)
{
    static SkTaskGroup::Enabler kTaskGroupEnabler;
    SkGraphics::Init();

    static SkOnce initPathRendererNames;
    initPathRendererNames([]() {
        gPathRendererNames[GpuPathRenderers::kAll] = "Default Ganesh Behavior (best path renderer)";
        gPathRendererNames[GpuPathRenderers::kStencilAndCover] = "NV_path_rendering";
        gPathRendererNames[GpuPathRenderers::kMSAA] = "Sample shading";
        gPathRendererNames[GpuPathRenderers::kSmall] = "Small paths (cached sdf or alpha masks)";
        gPathRendererNames[GpuPathRenderers::kTessellating] = "Tessellating";
        gPathRendererNames[GpuPathRenderers::kDefault] = "Original Ganesh path renderer";
        gPathRendererNames[GpuPathRenderers::kNone] = "Software masks";
    });

    memset(fPaintTimes, 0, sizeof(fPaintTimes));
    memset(fFlushTimes, 0, sizeof(fFlushTimes));
    memset(fAnimateTimes, 0, sizeof(fAnimateTimes));

    SkDebugf("Command line arguments: ");
    for (int i = 1; i < argc; ++i) {
        SkDebugf("%s ", argv[i]);
    }
    SkDebugf("\n");

    SkCommandLineFlags::Parse(argc, argv);
#ifdef SK_BUILD_FOR_ANDROID
    SetResourcePath("/data/local/tmp/skia");
#endif

    if (FLAGS_atrace) {
        SkAssertResult(SkEventTracer::SetInstance(new SkATrace()));
    }

    fBackendType = get_backend_type(FLAGS_backend[0]);
    fWindow = Window::CreateNativeWindow(platformData);

    DisplayParams displayParams;
    displayParams.fMSAASampleCount = FLAGS_msaa;
    displayParams.fGrContextOptions.fEnableInstancedRendering = FLAGS_instancedRendering;
    displayParams.fGrContextOptions.fGpuPathRenderers = CollectGpuPathRenderersFromFlags();
    fWindow->setRequestedDisplayParams(displayParams);

    // register callbacks
    fCommands.attach(fWindow);
    fWindow->registerBackendCreatedFunc(on_backend_created_func, this);
    fWindow->registerPaintFunc(on_paint_handler, this);
    fWindow->registerTouchFunc(on_touch_handler, this);
    fWindow->registerUIStateChangedFunc(on_ui_state_changed_handler, this);
    fWindow->registerMouseFunc(on_mouse_handler, this);
    fWindow->registerMouseWheelFunc(on_mouse_wheel_handler, this);
    fWindow->registerKeyFunc(on_key_handler, this);
    fWindow->registerCharFunc(on_char_handler, this);

    // add key-bindings
    fCommands.addCommand(' ', "GUI", "Toggle Debug GUI", [this]() {
        this->fShowImGuiDebugWindow = !this->fShowImGuiDebugWindow;
        fWindow->inval();
    });
    fCommands.addCommand('g', "GUI", "Toggle GUI Demo", [this]() {
        this->fShowImGuiTestWindow = !this->fShowImGuiTestWindow;
        fWindow->inval();
    });
    fCommands.addCommand('z', "GUI", "Toggle zoom window", [this]() {
        this->fShowZoomWindow = !this->fShowZoomWindow;
        fWindow->inval();
    });
    fCommands.addCommand('s', "Overlays", "Toggle stats display", [this]() {
        this->fDisplayStats = !this->fDisplayStats;
        fWindow->inval();
    });
    fCommands.addCommand('c', "Modes", "Cycle color mode", [this]() {
        switch (fColorMode) {
            case ColorMode::kLegacy:
                this->setColorMode(ColorMode::kColorManagedSRGB8888_NonLinearBlending);
                break;
            case ColorMode::kColorManagedSRGB8888_NonLinearBlending:
                this->setColorMode(ColorMode::kColorManagedSRGB8888);
                break;
            case ColorMode::kColorManagedSRGB8888:
                this->setColorMode(ColorMode::kColorManagedLinearF16);
                break;
            case ColorMode::kColorManagedLinearF16:
                this->setColorMode(ColorMode::kLegacy);
                break;
        }
    });
    fCommands.addCommand(Window::Key::kRight, "Right", "Navigation", "Next slide", [this]() {
        int previousSlide = fCurrentSlide;
        fCurrentSlide++;
        if (fCurrentSlide >= fSlides.count()) {
            fCurrentSlide = 0;
        }
        this->setupCurrentSlide(previousSlide);
    });
    fCommands.addCommand(Window::Key::kLeft, "Left", "Navigation", "Previous slide", [this]() {
        int previousSlide = fCurrentSlide;
        fCurrentSlide--;
        if (fCurrentSlide < 0) {
            fCurrentSlide = fSlides.count() - 1;
        }
        this->setupCurrentSlide(previousSlide);
    });
    fCommands.addCommand(Window::Key::kUp, "Up", "Transform", "Zoom in", [this]() {
        this->changeZoomLevel(1.f / 32.f);
        fWindow->inval();
    });
    fCommands.addCommand(Window::Key::kDown, "Down", "Transform", "Zoom out", [this]() {
        this->changeZoomLevel(-1.f / 32.f);
        fWindow->inval();
    });
    fCommands.addCommand('d', "Modes", "Change rendering backend", [this]() {
        sk_app::Window::BackendType newBackend = fBackendType;
#if defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC)
        if (sk_app::Window::kRaster_BackendType == fBackendType) {
            newBackend = sk_app::Window::kNativeGL_BackendType;
#ifdef SK_VULKAN
        } else if (sk_app::Window::kNativeGL_BackendType == fBackendType) {
            newBackend = sk_app::Window::kVulkan_BackendType;
#endif
        } else {
            newBackend = sk_app::Window::kRaster_BackendType;
        }
#elif defined(SK_BUILD_FOR_UNIX)
        // Switching to and from Vulkan is problematic on Linux so disabled for now
        if (sk_app::Window::kRaster_BackendType == fBackendType) {
            newBackend = sk_app::Window::kNativeGL_BackendType;
        } else if (sk_app::Window::kNativeGL_BackendType == fBackendType) {
            newBackend = sk_app::Window::kRaster_BackendType;
        }
#endif

        this->setBackend(newBackend);
    });

    // set up slides
    this->initSlides();
    this->setStartupSlide();
    if (FLAGS_list) {
        this->listNames();
    }

    fAnimTimer.run();

    // ImGui initialization:
    ImGuiIO& io = ImGui::GetIO();
    io.DisplaySize.x = static_cast<float>(fWindow->width());
    io.DisplaySize.y = static_cast<float>(fWindow->height());

    // Keymap...
    io.KeyMap[ImGuiKey_Tab] = (int)Window::Key::kTab;
    io.KeyMap[ImGuiKey_LeftArrow] = (int)Window::Key::kLeft;
    io.KeyMap[ImGuiKey_RightArrow] = (int)Window::Key::kRight;
    io.KeyMap[ImGuiKey_UpArrow] = (int)Window::Key::kUp;
    io.KeyMap[ImGuiKey_DownArrow] = (int)Window::Key::kDown;
    io.KeyMap[ImGuiKey_PageUp] = (int)Window::Key::kPageUp;
    io.KeyMap[ImGuiKey_PageDown] = (int)Window::Key::kPageDown;
    io.KeyMap[ImGuiKey_Home] = (int)Window::Key::kHome;
    io.KeyMap[ImGuiKey_End] = (int)Window::Key::kEnd;
    io.KeyMap[ImGuiKey_Delete] = (int)Window::Key::kDelete;
    io.KeyMap[ImGuiKey_Backspace] = (int)Window::Key::kBack;
    io.KeyMap[ImGuiKey_Enter] = (int)Window::Key::kOK;
    io.KeyMap[ImGuiKey_Escape] = (int)Window::Key::kEscape;
    io.KeyMap[ImGuiKey_A] = (int)Window::Key::kA;
    io.KeyMap[ImGuiKey_C] = (int)Window::Key::kC;
    io.KeyMap[ImGuiKey_V] = (int)Window::Key::kV;
    io.KeyMap[ImGuiKey_X] = (int)Window::Key::kX;
    io.KeyMap[ImGuiKey_Y] = (int)Window::Key::kY;
    io.KeyMap[ImGuiKey_Z] = (int)Window::Key::kZ;

    int w, h;
    unsigned char* pixels;
    io.Fonts->GetTexDataAsAlpha8(&pixels, &w, &h);
    SkImageInfo info = SkImageInfo::MakeA8(w, h);
    SkPixmap pmap(info, pixels, info.minRowBytes());
    SkMatrix localMatrix = SkMatrix::MakeScale(1.0f / w, 1.0f / h);
    auto fontImage = SkImage::MakeFromRaster(pmap, nullptr, nullptr);
    auto fontShader = fontImage->makeShader(&localMatrix);
    fImGuiFontPaint.setShader(fontShader);
    fImGuiFontPaint.setColor(SK_ColorWHITE);
    fImGuiFontPaint.setFilterQuality(kLow_SkFilterQuality);
    io.Fonts->TexID = &fImGuiFontPaint;

    auto gamutImage = GetResourceAsImage("gamut.png");
    if (gamutImage) {
        fImGuiGamutPaint.setShader(gamutImage->makeShader());
    }
    fImGuiGamutPaint.setColor(SK_ColorWHITE);
    fImGuiGamutPaint.setFilterQuality(kLow_SkFilterQuality);

    fWindow->attach(fBackendType);
}

void Viewer::initSlides() {
    fAllSlideNames = Json::Value(Json::arrayValue);

    const skiagm::GMRegistry* gms(skiagm::GMRegistry::Head());
    while (gms) {
        std::unique_ptr<skiagm::GM> gm(gms->factory()(nullptr));

        if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, gm->getName())) {
            sk_sp<Slide> slide(new GMSlide(gm.release()));
            fSlides.push_back(slide);
        }

        gms = gms->next();
    }

    // reverse array
    for (int i = 0; i < fSlides.count()/2; ++i) {
        sk_sp<Slide> temp = fSlides[i];
        fSlides[i] = fSlides[fSlides.count() - i - 1];
        fSlides[fSlides.count() - i - 1] = temp;
    }

    // samples
    const SkViewRegister* reg = SkViewRegister::Head();
    while (reg) {
        sk_sp<Slide> slide(new SampleSlide(reg->factory()));
        if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, slide->getName().c_str())) {
            fSlides.push_back(slide);
        }
        reg = reg->next();
    }

    // SKPs
    for (int i = 0; i < FLAGS_skps.count(); i++) {
        if (SkStrEndsWith(FLAGS_skps[i], ".skp")) {
            if (SkCommandLineFlags::ShouldSkip(FLAGS_match, FLAGS_skps[i])) {
                continue;
            }

            SkString path(FLAGS_skps[i]);
            sk_sp<SKPSlide> slide(new SKPSlide(SkOSPath::Basename(path.c_str()), path));
            if (slide) {
                fSlides.push_back(slide);
            }
        } else {
            SkOSFile::Iter it(FLAGS_skps[i], ".skp");
            SkString skpName;
            while (it.next(&skpName)) {
                if (SkCommandLineFlags::ShouldSkip(FLAGS_match, skpName.c_str())) {
                    continue;
                }

                SkString path = SkOSPath::Join(FLAGS_skps[i], skpName.c_str());
                sk_sp<SKPSlide> slide(new SKPSlide(skpName, path));
                if (slide) {
                    fSlides.push_back(slide);
                }
            }
        }
    }

    // JPGs
    for (int i = 0; i < FLAGS_jpgs.count(); i++) {
        SkOSFile::Iter it(FLAGS_jpgs[i], ".jpg");
        SkString jpgName;
        while (it.next(&jpgName)) {
            if (SkCommandLineFlags::ShouldSkip(FLAGS_match, jpgName.c_str())) {
                continue;
            }

            SkString path = SkOSPath::Join(FLAGS_jpgs[i], jpgName.c_str());
            sk_sp<ImageSlide> slide(new ImageSlide(jpgName, path));
            if (slide) {
                fSlides.push_back(slide);
            }
        }
    }
}


Viewer::~Viewer() {
    fWindow->detach();
    delete fWindow;
}

void Viewer::updateTitle() {
    if (!fWindow) {
        return;
    }
    if (fWindow->sampleCount() < 0) {
        return; // Surface hasn't been created yet.
    }

    SkString title("Viewer: ");
    title.append(fSlides[fCurrentSlide]->getName());

    switch (fColorMode) {
        case ColorMode::kLegacy:
            title.append(" Legacy 8888");
            break;
        case ColorMode::kColorManagedSRGB8888_NonLinearBlending:
            title.append(" ColorManaged 8888 (Nonlinear blending)");
            break;
        case ColorMode::kColorManagedSRGB8888:
            title.append(" ColorManaged 8888");
            break;
        case ColorMode::kColorManagedLinearF16:
            title.append(" ColorManaged F16");
            break;
    }

    if (ColorMode::kLegacy != fColorMode) {
        int curPrimaries = -1;
        for (size_t i = 0; i < SK_ARRAY_COUNT(gNamedPrimaries); ++i) {
            if (primaries_equal(*gNamedPrimaries[i].fPrimaries, fColorSpacePrimaries)) {
                curPrimaries = i;
                break;
            }
        }
        title.appendf(" %s", curPrimaries >= 0 ? gNamedPrimaries[curPrimaries].fName : "Custom");
    }

    title.append(" [");
    title.append(kBackendTypeStrings[fBackendType]);
    if (int msaa = fWindow->sampleCount()) {
        title.appendf(" MSAA: %i", msaa);
    }
    title.append("]");

    GpuPathRenderers pr = fWindow->getRequestedDisplayParams().fGrContextOptions.fGpuPathRenderers;
    if (GpuPathRenderers::kAll != pr) {
        title.appendf(" [Path renderer: %s]", gPathRendererNames[pr].c_str());
    }

    fWindow->setTitle(title.c_str());
}

void Viewer::setStartupSlide() {

    if (!FLAGS_slide.isEmpty()) {
        int count = fSlides.count();
        for (int i = 0; i < count; i++) {
            if (fSlides[i]->getName().equals(FLAGS_slide[0])) {
                fCurrentSlide = i;
                return;
            }
        }

        fprintf(stderr, "Unknown slide \"%s\"\n", FLAGS_slide[0]);
        this->listNames();
    }

    fCurrentSlide = 0;
}

void Viewer::listNames() {
    int count = fSlides.count();
    SkDebugf("All Slides:\n");
    for (int i = 0; i < count; i++) {
        SkDebugf("    %s\n", fSlides[i]->getName().c_str());
    }
}

void Viewer::setupCurrentSlide(int previousSlide) {
    if (fCurrentSlide == previousSlide) {
        return; // no change; do nothing
    }
    // prepare dimensions for image slides
    fSlides[fCurrentSlide]->load(SkIntToScalar(fWindow->width()), SkIntToScalar(fWindow->height()));

    fGesture.reset();
    fDefaultMatrix.reset();
    fDefaultMatrixInv.reset();

    if (fWindow->supportsContentRect() && fWindow->scaleContentToFit()) {
        const SkRect contentRect = fWindow->getContentRect();
        const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions();
        const SkRect slideBounds = SkRect::MakeIWH(slideSize.width(), slideSize.height());
        if (contentRect.width() > 0 && contentRect.height() > 0) {
            fDefaultMatrix.setRectToRect(slideBounds, contentRect, SkMatrix::kStart_ScaleToFit);
            SkAssertResult(fDefaultMatrix.invert(&fDefaultMatrixInv));
        }
    }

    if (fWindow->supportsContentRect()) {
        const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions();
        SkRect windowRect = fWindow->getContentRect();
        fDefaultMatrixInv.mapRect(&windowRect);
        fGesture.setTransLimit(SkRect::MakeWH(SkIntToScalar(slideSize.width()), 
                                              SkIntToScalar(slideSize.height())),
                               windowRect);
    }

    this->updateTitle();
    this->updateUIState();
    if (previousSlide >= 0) {
        fSlides[previousSlide]->unload();
    }
    fWindow->inval();
}

#define MAX_ZOOM_LEVEL  8
#define MIN_ZOOM_LEVEL  -8

void Viewer::changeZoomLevel(float delta) {
    fZoomLevel += delta;
    if (fZoomLevel > 0) {
        fZoomLevel = SkMinScalar(fZoomLevel, MAX_ZOOM_LEVEL);
        fZoomScale = fZoomLevel + SK_Scalar1;
    } else if (fZoomLevel < 0) {
        fZoomLevel = SkMaxScalar(fZoomLevel, MIN_ZOOM_LEVEL);
        fZoomScale = SK_Scalar1 / (SK_Scalar1 - fZoomLevel);
    } else {
        fZoomScale = SK_Scalar1;
    }
}

SkMatrix Viewer::computeMatrix() {
    SkMatrix m;
    m.reset();

    if (fZoomLevel) {
        SkPoint center;
        //m = this->getLocalMatrix();//.invert(&m);
        m.mapXY(fZoomCenterX, fZoomCenterY, &center);
        SkScalar cx = center.fX;
        SkScalar cy = center.fY;

        m.setTranslate(-cx, -cy);
        m.postScale(fZoomScale, fZoomScale);
        m.postTranslate(cx, cy);
    }

    m.preConcat(fGesture.localM());
    m.preConcat(fGesture.globalM());

    return m;
}

void Viewer::setBackend(sk_app::Window::BackendType backendType) {
    fBackendType = backendType;

    fWindow->detach();

#if defined(SK_BUILD_FOR_WIN) && defined(SK_VULKAN)
    // Switching from OpenGL to Vulkan in the same window is problematic at this point on
    // Windows, so we just delete the window and recreate it.
    if (sk_app::Window::kVulkan_BackendType == fBackendType) {
        DisplayParams params = fWindow->getRequestedDisplayParams();
        delete fWindow;
        fWindow = Window::CreateNativeWindow(nullptr);

        // re-register callbacks
        fCommands.attach(fWindow);
        fWindow->registerBackendCreatedFunc(on_backend_created_func, this);
        fWindow->registerPaintFunc(on_paint_handler, this);
        fWindow->registerTouchFunc(on_touch_handler, this);
        fWindow->registerUIStateChangedFunc(on_ui_state_changed_handler, this);
        fWindow->registerMouseFunc(on_mouse_handler, this);
        fWindow->registerMouseWheelFunc(on_mouse_wheel_handler, this);
        fWindow->registerKeyFunc(on_key_handler, this);
        fWindow->registerCharFunc(on_char_handler, this);
        fWindow->setRequestedDisplayParams(params);
    }
#endif

    fWindow->attach(fBackendType);
}

void Viewer::setColorMode(ColorMode colorMode) {
    fColorMode = colorMode;

    // When we're in color managed mode, we tag our window surface as sRGB. If we've switched into
    // or out of legacy/nonlinear mode, we need to update our window configuration.
    DisplayParams params = fWindow->getRequestedDisplayParams();
    bool wasInLegacy = !SkToBool(params.fColorSpace);
    bool wantLegacy = (ColorMode::kLegacy == fColorMode) ||
                      (ColorMode::kColorManagedSRGB8888_NonLinearBlending == fColorMode);
    if (wasInLegacy != wantLegacy) {
        params.fColorSpace = wantLegacy ? nullptr : SkColorSpace::MakeSRGB();
        fWindow->setRequestedDisplayParams(params);
    }

    this->updateTitle();
    fWindow->inval();
}

void Viewer::drawSlide(SkCanvas* canvas) {
    SkAutoCanvasRestore autorestore(canvas, false);

    if (fWindow->supportsContentRect()) {
        SkRect contentRect = fWindow->getContentRect();
        canvas->clipRect(contentRect);
        canvas->translate(contentRect.fLeft, contentRect.fTop);
    }

    // By default, we render directly into the window's surface/canvas
    SkCanvas* slideCanvas = canvas;
    fLastImage.reset();

    // If we're in any of the color managed modes, construct the color space we're going to use
    sk_sp<SkColorSpace> cs = nullptr;
    if (ColorMode::kLegacy != fColorMode) {
        auto transferFn = (ColorMode::kColorManagedLinearF16 == fColorMode)
            ? SkColorSpace::kLinear_RenderTargetGamma : SkColorSpace::kSRGB_RenderTargetGamma;
        SkMatrix44 toXYZ;
        SkAssertResult(fColorSpacePrimaries.toXYZD50(&toXYZ));
        cs = SkColorSpace::MakeRGB(transferFn, toXYZ);
    }

    // If we're in F16, or we're zooming, or we're in color correct 8888 and the gamut isn't sRGB,
    // we need to render offscreen
    sk_sp<SkSurface> offscreenSurface = nullptr;
    if (ColorMode::kColorManagedLinearF16 == fColorMode ||
        fShowZoomWindow ||
        (ColorMode::kColorManagedSRGB8888 == fColorMode &&
         !primaries_equal(fColorSpacePrimaries, gSrgbPrimaries))) {

        SkColorType colorType = (ColorMode::kColorManagedLinearF16 == fColorMode)
            ? kRGBA_F16_SkColorType : kN32_SkColorType;
        // In nonlinear blending mode, we actually use a legacy off-screen canvas, and wrap it
        // with a special canvas (below) that has the color space attached
        sk_sp<SkColorSpace> offscreenColorSpace =
            (ColorMode::kColorManagedSRGB8888_NonLinearBlending == fColorMode) ? nullptr : cs;
        SkImageInfo info = SkImageInfo::Make(fWindow->width(), fWindow->height(), colorType,
                                             kPremul_SkAlphaType, std::move(offscreenColorSpace));
        offscreenSurface = canvas->makeSurface(info);
        slideCanvas = offscreenSurface->getCanvas();
    }

    std::unique_ptr<SkCanvas> xformCanvas = nullptr;
    if (ColorMode::kColorManagedSRGB8888_NonLinearBlending == fColorMode) {
        xformCanvas = SkCreateColorSpaceXformCanvas(slideCanvas, cs);
        slideCanvas = xformCanvas.get();
    }

    int count = slideCanvas->save();
    slideCanvas->clear(SK_ColorWHITE);
    slideCanvas->concat(fDefaultMatrix);
    slideCanvas->concat(computeMatrix());
    // Time the painting logic of the slide
    double startTime = SkTime::GetMSecs();
    fSlides[fCurrentSlide]->draw(slideCanvas);
    fPaintTimes[fCurrentMeasurement] = SkTime::GetMSecs() - startTime;
    slideCanvas->restoreToCount(count);

    // Force a flush so we can time that, too
    startTime = SkTime::GetMSecs();
    slideCanvas->flush();
    fFlushTimes[fCurrentMeasurement] = SkTime::GetMSecs() - startTime;

    // If we rendered offscreen, snap an image and push the results to the window's canvas
    if (offscreenSurface) {
        fLastImage = offscreenSurface->makeImageSnapshot();

        // Tag the image with the sRGB gamut, so no further color space conversion happens
        sk_sp<SkColorSpace> srgb = (ColorMode::kColorManagedLinearF16 == fColorMode)
            ? SkColorSpace::MakeSRGBLinear() : SkColorSpace::MakeSRGB();
        auto retaggedImage = SkImageMakeRasterCopyAndAssignColorSpace(fLastImage.get(), srgb.get());
        SkPaint paint;
        paint.setBlendMode(SkBlendMode::kSrc);
        canvas->drawImage(retaggedImage, 0, 0, &paint);
    }
}

void Viewer::onBackendCreated() {
    this->updateTitle();
    this->updateUIState();
    this->setupCurrentSlide(-1);
    fWindow->show();
    fWindow->inval();
}

void Viewer::onPaint(SkCanvas* canvas) {
    // Update ImGui input
    ImGuiIO& io = ImGui::GetIO();
    io.DeltaTime = 1.0f / 60.0f;
    io.DisplaySize.x = static_cast<float>(fWindow->width());
    io.DisplaySize.y = static_cast<float>(fWindow->height());

    io.KeyAlt = io.KeysDown[static_cast<int>(Window::Key::kOption)];
    io.KeyCtrl = io.KeysDown[static_cast<int>(Window::Key::kCtrl)];
    io.KeyShift = io.KeysDown[static_cast<int>(Window::Key::kShift)];

    ImGui::NewFrame();

    drawSlide(canvas);

    // Advance our timing bookkeeping
    fCurrentMeasurement = (fCurrentMeasurement + 1) & (kMeasurementCount - 1);
    SkASSERT(fCurrentMeasurement < kMeasurementCount);

    // Draw any overlays or UI that we don't want timed
    if (fDisplayStats) {
        drawStats(canvas);
    }
    fCommands.drawHelp(canvas);

    drawImGui(canvas);

    // Update the FPS
    updateUIState();
}

bool Viewer::onTouch(intptr_t owner, Window::InputState state, float x, float y) {
    void* castedOwner = reinterpret_cast<void*>(owner);
    SkPoint touchPoint = fDefaultMatrixInv.mapXY(x, y);
    switch (state) {
        case Window::kUp_InputState: {
            fGesture.touchEnd(castedOwner);
            break;
        }
        case Window::kDown_InputState: {
            fGesture.touchBegin(castedOwner, touchPoint.fX, touchPoint.fY);
            break;
        }
        case Window::kMove_InputState: {
            fGesture.touchMoved(castedOwner, touchPoint.fX, touchPoint.fY);
            break;
        }
    }
    fWindow->inval();
    return true;
}

bool Viewer::onMouse(float x, float y, Window::InputState state, uint32_t modifiers) {

    SkPoint touchPoint = fDefaultMatrixInv.mapXY(x, y);
    switch (state) {
        case Window::kUp_InputState: {
            fGesture.touchEnd(nullptr);
            break;
        }
        case Window::kDown_InputState: {
            fGesture.touchBegin(nullptr, touchPoint.fX, touchPoint.fY);
            break;
        }
        case Window::kMove_InputState: {
            fGesture.touchMoved(nullptr, touchPoint.fX, touchPoint.fY);
            break;
        }
    }
    fWindow->inval();
    return true;
}

void Viewer::drawStats(SkCanvas* canvas) {
    static const float kPixelPerMS = 2.0f;
    static const int kDisplayWidth = 130;
    static const int kDisplayHeight = 100;
    static const int kDisplayPadding = 10;
    static const int kGraphPadding = 3;
    static const SkScalar kBaseMS = 1000.f / 60.f;  // ms/frame to hit 60 fps

    SkISize canvasSize = canvas->getBaseLayerSize();
    SkRect rect = SkRect::MakeXYWH(SkIntToScalar(canvasSize.fWidth-kDisplayWidth-kDisplayPadding),
                                   SkIntToScalar(kDisplayPadding),
                                   SkIntToScalar(kDisplayWidth), SkIntToScalar(kDisplayHeight));
    SkPaint paint;
    canvas->save();

    if (fWindow->supportsContentRect()) {
        SkRect contentRect = fWindow->getContentRect();
        canvas->clipRect(contentRect);
        canvas->translate(contentRect.fLeft, contentRect.fTop);
    }

    canvas->clipRect(rect);
    paint.setColor(SK_ColorBLACK);
    canvas->drawRect(rect, paint);
    // draw the 16ms line
    paint.setColor(SK_ColorLTGRAY);
    canvas->drawLine(rect.fLeft, rect.fBottom - kBaseMS*kPixelPerMS,
                     rect.fRight, rect.fBottom - kBaseMS*kPixelPerMS, paint);
    paint.setColor(SK_ColorRED);
    paint.setStyle(SkPaint::kStroke_Style);
    canvas->drawRect(rect, paint);

    int x = SkScalarTruncToInt(rect.fLeft) + kGraphPadding;
    const int xStep = 2;
    int i = fCurrentMeasurement;
    do {
        // Round to nearest values
        int animateHeight = (int)(fAnimateTimes[i] * kPixelPerMS + 0.5);
        int paintHeight = (int)(fPaintTimes[i] * kPixelPerMS + 0.5);
        int flushHeight = (int)(fFlushTimes[i] * kPixelPerMS + 0.5);
        int startY = SkScalarTruncToInt(rect.fBottom);
        int endY = startY - flushHeight;
        paint.setColor(SK_ColorRED);
        canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
                         SkIntToScalar(x), SkIntToScalar(endY), paint);
        startY = endY;
        endY = startY - paintHeight;
        paint.setColor(SK_ColorGREEN);
        canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
                         SkIntToScalar(x), SkIntToScalar(endY), paint);
        startY = endY;
        endY = startY - animateHeight;
        paint.setColor(SK_ColorMAGENTA);
        canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
                         SkIntToScalar(x), SkIntToScalar(endY), paint);
        i++;
        i &= (kMeasurementCount - 1);  // fast mod
        x += xStep;
    } while (i != fCurrentMeasurement);

    canvas->restore();
}

static ImVec2 ImGui_DragPrimary(const char* label, float* x, float* y,
                                const ImVec2& pos, const ImVec2& size) {
    // Transform primaries ([0, 0] - [0.8, 0.9]) to screen coords (including Y-flip)
    ImVec2 center(pos.x + (*x / 0.8f) * size.x, pos.y + (1.0f - (*y / 0.9f)) * size.y);

    // Invisible 10x10 button
    ImGui::SetCursorScreenPos(ImVec2(center.x - 5, center.y - 5));
    ImGui::InvisibleButton(label, ImVec2(10, 10));

    if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) {
        ImGuiIO& io = ImGui::GetIO();
        // Normalized mouse position, relative to our gamut box
        ImVec2 mousePosXY((io.MousePos.x - pos.x) / size.x, (io.MousePos.y - pos.y) / size.y);
        // Clamp to edge of box, convert back to primary scale
        *x = SkTPin(mousePosXY.x, 0.0f, 1.0f) * 0.8f;
        *y = SkTPin(1 - mousePosXY.y, 0.0f, 1.0f) * 0.9f;
    }

    if (ImGui::IsItemHovered()) {
        ImGui::SetTooltip("x: %.3f\ny: %.3f", *x, *y);
    }

    // Return screen coordinates for the caller. We could just return center here, but we'd have
    // one frame of lag during drag.
    return ImVec2(pos.x + (*x / 0.8f) * size.x, pos.y + (1.0f - (*y / 0.9f)) * size.y);
}

static void ImGui_Primaries(SkColorSpacePrimaries* primaries, SkPaint* gamutPaint) {
    ImDrawList* drawList = ImGui::GetWindowDrawList();

    // The gamut image covers a (0.8 x 0.9) shaped region, so fit our image/canvas to the available
    // width, and scale the height to maintain aspect ratio.
    float canvasWidth = SkTMax(ImGui::GetContentRegionAvailWidth(), 50.0f);
    ImVec2 size = ImVec2(canvasWidth, canvasWidth * (0.9f / 0.8f));
    ImVec2 pos = ImGui::GetCursorScreenPos();

    // Background image. Only draw a subset of the image, to avoid the regions less than zero.
    // Simplifes re-mapping math, clipping behavior, and increases resolution in the useful area.
    // Magic numbers are pixel locations of the origin and upper-right corner.
    drawList->AddImage(gamutPaint, pos, ImVec2(pos.x + size.x, pos.y + size.y),
                       ImVec2(242, 61), ImVec2(1897, 1922));
    ImVec2 endPos = ImGui::GetCursorPos();

    // Primary markers
    ImVec2 r = ImGui_DragPrimary("R", &primaries->fRX, &primaries->fRY, pos, size);
    ImVec2 g = ImGui_DragPrimary("G", &primaries->fGX, &primaries->fGY, pos, size);
    ImVec2 b = ImGui_DragPrimary("B", &primaries->fBX, &primaries->fBY, pos, size);
    ImVec2 w = ImGui_DragPrimary("W", &primaries->fWX, &primaries->fWY, pos, size);

    // Gamut triangle
    drawList->AddCircle(r, 5.0f, 0xFF000040);
    drawList->AddCircle(g, 5.0f, 0xFF004000);
    drawList->AddCircle(b, 5.0f, 0xFF400000);
    drawList->AddCircle(w, 5.0f, 0xFFFFFFFF);
    drawList->AddTriangle(r, g, b, 0xFFFFFFFF);

    // Re-position cursor immediate after the diagram for subsequent controls
    ImGui::SetCursorPos(endPos);
}

void Viewer::drawImGui(SkCanvas* canvas) {
    // Support drawing the ImGui demo window. Superfluous, but gives a good idea of what's possible
    if (fShowImGuiTestWindow) {
        ImGui::ShowTestWindow(&fShowImGuiTestWindow);
    }

    if (fShowImGuiDebugWindow) {
        // We have some dynamic content that sizes to fill available size. If the scroll bar isn't
        // always visible, we can end up in a layout feedback loop.
        ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiSetCond_FirstUseEver);
        DisplayParams params = fWindow->getRequestedDisplayParams();
        bool paramsChanged = false;
        if (ImGui::Begin("Tools", &fShowImGuiDebugWindow,
                         ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
            if (ImGui::CollapsingHeader("Backend")) {
                int newBackend = static_cast<int>(fBackendType);
                ImGui::RadioButton("Raster", &newBackend, sk_app::Window::kRaster_BackendType);
                ImGui::SameLine();
                ImGui::RadioButton("OpenGL", &newBackend, sk_app::Window::kNativeGL_BackendType);
#if defined(SK_VULKAN)
                ImGui::SameLine();
                ImGui::RadioButton("Vulkan", &newBackend, sk_app::Window::kVulkan_BackendType);
#endif
                if (newBackend != fBackendType) {
                    fDeferredActions.push_back([=]() {
                        this->setBackend(static_cast<sk_app::Window::BackendType>(newBackend));
                    });
                }

                const GrContext* ctx = fWindow->getGrContext();
                bool* inst = &params.fGrContextOptions.fEnableInstancedRendering;
                if (ctx && ImGui::Checkbox("Instanced Rendering", inst)) {
                    paramsChanged = true;
                }
                bool* wire = &params.fGrContextOptions.fWireframeMode;
                if (ctx && ImGui::Checkbox("Wireframe Mode", wire)) {
                    paramsChanged = true;
                }

                if (ctx) {
                    int sampleCount = fWindow->sampleCount();
                    ImGui::Text("MSAA: "); ImGui::SameLine();
                    ImGui::RadioButton("0", &sampleCount, 0); ImGui::SameLine();
                    ImGui::RadioButton("4", &sampleCount, 4); ImGui::SameLine();
                    ImGui::RadioButton("8", &sampleCount, 8); ImGui::SameLine();
                    ImGui::RadioButton("16", &sampleCount, 16);

                    if (sampleCount != params.fMSAASampleCount) {
                        params.fMSAASampleCount = sampleCount;
                        paramsChanged = true;
                    }
                }

                if (ImGui::TreeNode("Path Renderers")) {
                    GpuPathRenderers prevPr = params.fGrContextOptions.fGpuPathRenderers;
                    auto prButton = [&](GpuPathRenderers x) {
                        if (ImGui::RadioButton(gPathRendererNames[x].c_str(), prevPr == x)) {
                            if (x != params.fGrContextOptions.fGpuPathRenderers) {
                                params.fGrContextOptions.fGpuPathRenderers = x;
                                paramsChanged = true;
                            }
                        }
                    };

                    if (!ctx) {
                        ImGui::RadioButton("Software", true);
                    } else if (fWindow->sampleCount()) {
                        prButton(GpuPathRenderers::kAll);
                        if (ctx->caps()->shaderCaps()->pathRenderingSupport()) {
                            prButton(GpuPathRenderers::kStencilAndCover);
                        }
                        if (ctx->caps()->sampleShadingSupport()) {
                            prButton(GpuPathRenderers::kMSAA);
                        }
                        prButton(GpuPathRenderers::kTessellating);
                        prButton(GpuPathRenderers::kDefault);
                        prButton(GpuPathRenderers::kNone);
                    } else {
                        prButton(GpuPathRenderers::kAll);
                        prButton(GpuPathRenderers::kSmall);
                        prButton(GpuPathRenderers::kTessellating);
                        prButton(GpuPathRenderers::kNone);
                    }
                    ImGui::TreePop();
                }
            }

            if (ImGui::CollapsingHeader("Slide")) {
                static ImGuiTextFilter filter;
                filter.Draw();
                int previousSlide = fCurrentSlide;
                fCurrentSlide = 0;
                for (auto slide : fSlides) {
                    if (filter.PassFilter(slide->getName().c_str())) {
                        ImGui::BulletText("%s", slide->getName().c_str());
                        if (ImGui::IsItemClicked()) {
                            setupCurrentSlide(previousSlide);
                            break;
                        }
                    }
                    ++fCurrentSlide;
                }
                if (fCurrentSlide >= fSlides.count()) {
                    fCurrentSlide = previousSlide;
                }
            }

            if (ImGui::CollapsingHeader("Color Mode")) {
                ColorMode newMode = fColorMode;
                auto cmButton = [&](ColorMode mode, const char* label) {
                    if (ImGui::RadioButton(label, mode == fColorMode)) {
                        newMode = mode;
                    }
                };

                cmButton(ColorMode::kLegacy, "Legacy 8888");
                cmButton(ColorMode::kColorManagedSRGB8888_NonLinearBlending,
                         "Color Managed 8888 (Nonlinear blending)");
                cmButton(ColorMode::kColorManagedSRGB8888, "Color Managed 8888");
                cmButton(ColorMode::kColorManagedLinearF16, "Color Managed F16");

                if (newMode != fColorMode) {
                    // It isn't safe to switch color mode now (in the middle of painting). We might
                    // tear down the back-end, etc... Defer this change until the next onIdle.
                    fDeferredActions.push_back([=]() {
                        this->setColorMode(newMode);
                    });
                }

                // Pick from common gamuts:
                int primariesIdx = 4; // Default: Custom
                for (size_t i = 0; i < SK_ARRAY_COUNT(gNamedPrimaries); ++i) {
                    if (primaries_equal(*gNamedPrimaries[i].fPrimaries, fColorSpacePrimaries)) {
                        primariesIdx = i;
                        break;
                    }
                }

                if (ImGui::Combo("Primaries", &primariesIdx,
                                 "sRGB\0AdobeRGB\0P3\0Rec. 2020\0Custom\0\0")) {
                    if (primariesIdx >= 0 && primariesIdx <= 3) {
                        fColorSpacePrimaries = *gNamedPrimaries[primariesIdx].fPrimaries;
                    }
                }

                // Allow direct editing of gamut
                ImGui_Primaries(&fColorSpacePrimaries, &fImGuiGamutPaint);
            }
        }
        if (paramsChanged) {
            fDeferredActions.push_back([=]() {
                fWindow->setRequestedDisplayParams(params);
                fWindow->inval();
                this->updateTitle();
            });
        }
        ImGui::End();
    }

    SkPaint zoomImagePaint;
    if (fShowZoomWindow && fLastImage) {
        if (ImGui::Begin("Zoom", &fShowZoomWindow, ImVec2(200, 200))) {
            static int zoomFactor = 4;
            ImGui::SliderInt("Scale", &zoomFactor, 1, 16);

            zoomImagePaint.setShader(fLastImage->makeShader());
            zoomImagePaint.setColor(SK_ColorWHITE);

            // Zoom by shrinking the corner UVs towards the mouse cursor
            ImVec2 mousePos = ImGui::GetMousePos();
            ImVec2 avail = ImGui::GetContentRegionAvail();

            ImVec2 zoomHalfExtents = ImVec2((avail.x * 0.5f) / zoomFactor,
                                            (avail.y * 0.5f) / zoomFactor);
            ImGui::Image(&zoomImagePaint, avail,
                         ImVec2(mousePos.x - zoomHalfExtents.x, mousePos.y - zoomHalfExtents.y),
                         ImVec2(mousePos.x + zoomHalfExtents.x, mousePos.y + zoomHalfExtents.y));
        }

        ImGui::End();
    }

    // This causes ImGui to rebuild vertex/index data based on all immediate-mode commands
    // (widgets, etc...) that have been issued
    ImGui::Render();

    // Then we fetch the most recent data, and convert it so we can render with Skia
    const ImDrawData* drawData = ImGui::GetDrawData();
    SkTDArray<SkPoint> pos;
    SkTDArray<SkPoint> uv;
    SkTDArray<SkColor> color;

    for (int i = 0; i < drawData->CmdListsCount; ++i) {
        const ImDrawList* drawList = drawData->CmdLists[i];

        // De-interleave all vertex data (sigh), convert to Skia types
        pos.rewind(); uv.rewind(); color.rewind();
        for (int i = 0; i < drawList->VtxBuffer.size(); ++i) {
            const ImDrawVert& vert = drawList->VtxBuffer[i];
            pos.push(SkPoint::Make(vert.pos.x, vert.pos.y));
            uv.push(SkPoint::Make(vert.uv.x, vert.uv.y));
            color.push(vert.col);
        }
        // ImGui colors are RGBA
        SkSwapRB(color.begin(), color.begin(), color.count());

        int indexOffset = 0;

        // Draw everything with canvas.drawVertices...
        for (int j = 0; j < drawList->CmdBuffer.size(); ++j) {
            const ImDrawCmd* drawCmd = &drawList->CmdBuffer[j];

            // TODO: Find min/max index for each draw, so we know how many vertices (sigh)
            if (drawCmd->UserCallback) {
                drawCmd->UserCallback(drawList, drawCmd);
            } else {
                SkPaint* paint = static_cast<SkPaint*>(drawCmd->TextureId);
                SkASSERT(paint);

                canvas->save();
                canvas->clipRect(SkRect::MakeLTRB(drawCmd->ClipRect.x, drawCmd->ClipRect.y,
                                                  drawCmd->ClipRect.z, drawCmd->ClipRect.w));
                canvas->drawVertices(SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode,
                                                          drawList->VtxBuffer.size(), pos.begin(),
                                                          uv.begin(), color.begin(),
                                                          drawCmd->ElemCount,
                                                          drawList->IdxBuffer.begin() + indexOffset),
                                     SkBlendMode::kModulate, *paint);
                indexOffset += drawCmd->ElemCount;
                canvas->restore();
            }
        }
    }
}

void Viewer::onIdle() {
    for (int i = 0; i < fDeferredActions.count(); ++i) {
        fDeferredActions[i]();
    }
    fDeferredActions.reset();

    double startTime = SkTime::GetMSecs();
    fAnimTimer.updateTime();
    bool animateWantsInval = fSlides[fCurrentSlide]->animate(fAnimTimer);
    fAnimateTimes[fCurrentMeasurement] = SkTime::GetMSecs() - startTime;

    ImGuiIO& io = ImGui::GetIO();
    if (animateWantsInval || fDisplayStats || fRefresh || io.MetricsActiveWindows) {
        fWindow->inval();
    }
}

void Viewer::updateUIState() {
    if (!fWindow) {
        return;
    }
    if (fWindow->sampleCount() < 0) {
        return; // Surface hasn't been created yet.
    }

    // Slide state
    Json::Value slideState(Json::objectValue);
    slideState[kName] = kSlideStateName;
    slideState[kValue] = fSlides[fCurrentSlide]->getName().c_str();
    if (fAllSlideNames.size() == 0) {
        for(auto slide : fSlides) {
            fAllSlideNames.append(Json::Value(slide->getName().c_str()));
        }
    }
    slideState[kOptions] = fAllSlideNames;

    // Backend state
    Json::Value backendState(Json::objectValue);
    backendState[kName] = kBackendStateName;
    backendState[kValue] = kBackendTypeStrings[fBackendType];
    backendState[kOptions] = Json::Value(Json::arrayValue);
    for (auto str : kBackendTypeStrings) {
        backendState[kOptions].append(Json::Value(str));
    }

    // MSAA state
    Json::Value msaaState(Json::objectValue);
    msaaState[kName] = kMSAAStateName;
    msaaState[kValue] = fWindow->sampleCount();
    msaaState[kOptions] = Json::Value(Json::arrayValue);
    if (sk_app::Window::kRaster_BackendType == fBackendType) {
        msaaState[kOptions].append(Json::Value(0));
    } else {
        for (int msaa : {0, 4, 8, 16}) {
            msaaState[kOptions].append(Json::Value(msaa));
        }
    }

    // Path renderer state
    GpuPathRenderers pr = fWindow->getRequestedDisplayParams().fGrContextOptions.fGpuPathRenderers;
    Json::Value prState(Json::objectValue);
    prState[kName] = kPathRendererStateName;
    prState[kValue] = gPathRendererNames[pr];
    prState[kOptions] = Json::Value(Json::arrayValue);
    const GrContext* ctx = fWindow->getGrContext();
    if (!ctx) {
        prState[kOptions].append("Software");
    } else if (fWindow->sampleCount()) {
        prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kAll]);
        if (ctx->caps()->shaderCaps()->pathRenderingSupport()) {
            prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kStencilAndCover]);
        }
        if (ctx->caps()->sampleShadingSupport()) {
            prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kMSAA]);
        }
        prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kTessellating]);
        prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kDefault]);
        prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kNone]);
    } else {
        prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kAll]);
        prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kSmall]);
        prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kTessellating]);
        prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kNone]);
    }

    // Instanced rendering state
    Json::Value instState(Json::objectValue);
    instState[kName] = kInstancedRenderingStateName;
    if (ctx) {
        if (fWindow->getRequestedDisplayParams().fGrContextOptions.fEnableInstancedRendering) {
            instState[kValue] = kON;
        } else {
            instState[kValue] = kOFF;
        }
        instState[kOptions] = Json::Value(Json::arrayValue);
        instState[kOptions].append(kOFF);
        instState[kOptions].append(kON);
    }

    // Softkey state
    Json::Value softkeyState(Json::objectValue);
    softkeyState[kName] = kSoftkeyStateName;
    softkeyState[kValue] = kSoftkeyHint;
    softkeyState[kOptions] = Json::Value(Json::arrayValue);
    softkeyState[kOptions].append(kSoftkeyHint);
    for (const auto& softkey : fCommands.getCommandsAsSoftkeys()) {
        softkeyState[kOptions].append(Json::Value(softkey.c_str()));
    }

    // FPS state
    Json::Value fpsState(Json::objectValue);
    fpsState[kName] = kFpsStateName;
    int idx = (fCurrentMeasurement + (kMeasurementCount - 1)) & (kMeasurementCount - 1);
    fpsState[kValue] = SkStringPrintf("%8.3lf ms\n\nA %8.3lf\nP %8.3lf\nF%8.3lf",
                                      fAnimateTimes[idx] + fPaintTimes[idx] + fFlushTimes[idx],
                                      fAnimateTimes[idx],
                                      fPaintTimes[idx],
                                      fFlushTimes[idx]).c_str();
    fpsState[kOptions] = Json::Value(Json::arrayValue);

    Json::Value state(Json::arrayValue);
    state.append(slideState);
    state.append(backendState);
    state.append(msaaState);
    state.append(prState);
    state.append(instState);
    state.append(softkeyState);
    state.append(fpsState);

    fWindow->setUIState(state);
}

void Viewer::onUIStateChanged(const SkString& stateName, const SkString& stateValue) {
    // For those who will add more features to handle the state change in this function:
    // After the change, please call updateUIState no notify the frontend (e.g., Android app).
    // For example, after slide change, updateUIState is called inside setupCurrentSlide;
    // after backend change, updateUIState is called in this function.
    if (stateName.equals(kSlideStateName)) {
        int previousSlide = fCurrentSlide;
        fCurrentSlide = 0;
        for(auto slide : fSlides) {
            if (slide->getName().equals(stateValue)) {
                this->setupCurrentSlide(previousSlide);
                break;
            }
            fCurrentSlide++;
        }
        if (fCurrentSlide >= fSlides.count()) {
            fCurrentSlide = previousSlide;
            SkDebugf("Slide not found: %s", stateValue.c_str());
        }
    } else if (stateName.equals(kBackendStateName)) {
        for (int i = 0; i < sk_app::Window::kBackendTypeCount; i++) {
            if (stateValue.equals(kBackendTypeStrings[i])) {
                if (fBackendType != i) {
                    fBackendType = (sk_app::Window::BackendType)i;
                    fWindow->detach();
                    fWindow->attach(fBackendType);
                }
                break;
            }
        }
    } else if (stateName.equals(kMSAAStateName)) {
        DisplayParams params = fWindow->getRequestedDisplayParams();
        int sampleCount = atoi(stateValue.c_str());
        if (sampleCount != params.fMSAASampleCount) {
            params.fMSAASampleCount = sampleCount;
            fWindow->setRequestedDisplayParams(params);
            fWindow->inval();
            this->updateTitle();
            this->updateUIState();
        }
    } else if (stateName.equals(kPathRendererStateName)) {
        DisplayParams params = fWindow->getRequestedDisplayParams();
        for (const auto& pair : gPathRendererNames) {
            if (pair.second == stateValue.c_str()) {
                if (params.fGrContextOptions.fGpuPathRenderers != pair.first) {
                    params.fGrContextOptions.fGpuPathRenderers = pair.first;
                    fWindow->setRequestedDisplayParams(params);
                    fWindow->inval();
                    this->updateTitle();
                    this->updateUIState();
                }
                break;
            }
        }
    } else if (stateName.equals(kInstancedRenderingStateName)) {
        DisplayParams params = fWindow->getRequestedDisplayParams();
        bool value = !strcmp(stateValue.c_str(), kON);
        if (params.fGrContextOptions.fEnableInstancedRendering != value) {
            params.fGrContextOptions.fEnableInstancedRendering = value;
            fWindow->setRequestedDisplayParams(params);
            fWindow->inval();
            this->updateTitle();
            this->updateUIState();
        }
    } else if (stateName.equals(kSoftkeyStateName)) {
        if (!stateValue.equals(kSoftkeyHint)) {
            fCommands.onSoftkey(stateValue);
            this->updateUIState(); // This is still needed to reset the value to kSoftkeyHint
        }
    } else if (stateName.equals(kRefreshStateName)) {
        // This state is actually NOT in the UI state.
        // We use this to allow Android to quickly set bool fRefresh.
        fRefresh = stateValue.equals(kON);
    } else {
        SkDebugf("Unknown stateName: %s", stateName.c_str());
    }
}

bool Viewer::onKey(sk_app::Window::Key key, sk_app::Window::InputState state, uint32_t modifiers) {
    return fCommands.onKey(key, state, modifiers);
}

bool Viewer::onChar(SkUnichar c, uint32_t modifiers) {
    if (fSlides[fCurrentSlide]->onChar(c)) {
        fWindow->inval();
        return true;
    }

    return fCommands.onChar(c, modifiers);
}
