| Index: nacl/src/nacl_debugger.cpp | 
| =================================================================== | 
| --- nacl/src/nacl_debugger.cpp	(revision 7896) | 
| +++ nacl/src/nacl_debugger.cpp	(working copy) | 
| @@ -6,75 +6,45 @@ | 
| #include "ppapi/cpp/image_data.h" | 
| #include "ppapi/cpp/instance.h" | 
| #include "ppapi/cpp/module.h" | 
| +#include "ppapi/cpp/point.h" | 
| +#include "ppapi/cpp/rect.h" | 
| #include "ppapi/cpp/var.h" | 
|  | 
| +#include "SkBase64.h" | 
| +#include "SkBitmap.h" | 
| #include "SkCanvas.h" | 
| -#include "SkBitmap.h" | 
| +#include "SkColor.h" | 
| +#include "SkDebugger.h" | 
| +#include "SkGraphics.h" | 
| +#include "SkStream.h" | 
| #include "SkString.h" | 
| -#include "SkThreadUtils.h" | 
|  | 
| class SkiaInstance; | 
|  | 
| // Used by SkDebugf | 
| SkiaInstance* gPluginInstance; | 
|  | 
| -// Main entry point for the app we're linked into | 
| -extern int tool_main(int, char**); | 
| +void FlushCallback(void* data, int32_t result); | 
|  | 
| -// Tokenize a command line and store it in argc and argv. | 
| -void SkStringToProgramArgs(const SkString commandLine, int* argc, char*** argv) { | 
| -    int numBreaks = 0; | 
| -    const char* commandChars = commandLine.c_str(); | 
| -    for (int i = 0; i < strlen(commandChars); i++) { | 
| -        if (isspace(commandChars[i])) { | 
| -            numBreaks++; | 
| -        } | 
| -    } | 
| -    int numArgs; | 
| -    if (strlen(commandChars) > 0) { | 
| -        numArgs = numBreaks + 1; | 
| -    } else { | 
| -        numArgs = 0; | 
| -    } | 
| -    *argc = numArgs; | 
| -    *argv = new char*[numArgs + 1]; | 
| -    (*argv)[numArgs] = NULL; | 
| -    char* start = (char*) commandChars; | 
| -    int length = 0; | 
| -    int argIndex = 0; | 
| -    for (int i = 0; i < strlen(commandChars) + 1; i++) { | 
| -        if (isspace(commandChars[i]) || '\0' == commandChars[i]) { | 
| -            if (length > 0) { | 
| -                char* argument = new char[length + 1]; | 
| -                memcpy(argument, start, length); | 
| -                argument[length] = '\0'; | 
| -                (*argv)[argIndex++] = argument; | 
| -            } | 
| -            start = (char*) commandChars + i + 1; | 
| -            length = 0; | 
| -        } else { | 
| -            length++; | 
| -        } | 
| -    } | 
| -} | 
| - | 
| -// Run the program with the given command line. | 
| -void RunProgram(const SkString& commandLine) { | 
| -    int argc; | 
| -    char** argv; | 
| -    SkStringToProgramArgs(commandLine, &argc, &argv); | 
| -    tool_main(argc, argv); | 
| -} | 
| - | 
| - | 
| // Skia's subclass of pp::Instance, our interface with the browser. | 
| class SkiaInstance : public pp::Instance { | 
| public: | 
| -    explicit SkiaInstance(PP_Instance instance) : pp::Instance(instance) { | 
| +    explicit SkiaInstance(PP_Instance instance) | 
| +        : pp::Instance(instance) | 
| +        , fBitmap() | 
| +        , fCanvas(NULL) | 
| +        , fDebugger() | 
| +        , fImage() | 
| +        , fFlushLoopRunning(false) | 
| +        , fFlushPending(false) | 
| +        , fPicture(NULL) | 
| +    { | 
| gPluginInstance = this; | 
| +        SkGraphics::Init(); | 
| } | 
|  | 
| virtual ~SkiaInstance() { | 
| +        SkGraphics::Term(); | 
| gPluginInstance = NULL; | 
| } | 
|  | 
| @@ -83,12 +53,143 @@ | 
| if (var_message.is_string()) { | 
| SkString msg(var_message.AsString().c_str()); | 
| if (msg.startsWith("init")) { | 
| -                RunProgram(msg); | 
| +            } else if (msg.startsWith("LoadSKP")) { | 
| +                size_t startIndex = strlen("LoadSKP"); | 
| +                size_t dataSize = msg.size()/sizeof(char) - startIndex; | 
| +                SkBase64 decodedData; | 
| +                decodedData.decode(msg.c_str() + startIndex, dataSize); | 
| +                size_t decodedSize = 3 * (dataSize / 4); | 
| +                SkDebugf("Got size: %d\n", decodedSize); | 
| +                if (!decodedData.getData()) { | 
| +                    SkDebugf("Failed to decode SKP\n"); | 
| +                    return; | 
| +                } | 
| +                SkMemoryStream pictureStream(decodedData.getData(), decodedSize); | 
| +                fPicture = new SkPicture(&pictureStream); | 
| +                if (fPicture->width() == 0 || fPicture->height() == 0) { | 
| +                    SkDebugf("Failed to create SKP.\n"); | 
| +                    return; | 
| +                } | 
| +                fDebugger.loadPicture(fPicture); | 
| +                SkTArray<SkString>* commands = fDebugger.getDrawCommandsAsStrings(); | 
| +                PostMessage("ClearCommands"); | 
| +                for (int i = 0; i < commands->count(); ++i) { | 
| +                    SkString message("AddCommand:"); | 
| +                    message.append((*commands)[i]); | 
| +                    PostMessage(message.c_str()); | 
| +                } | 
| +                if (!fFlushLoopRunning) { | 
| +                    Paint(); | 
| +                } | 
| +            } else if (msg.startsWith("CommandSelected:")) { | 
| +                size_t startIndex = strlen("CommandSelected:"); | 
| +                int index = atoi(msg.c_str() + startIndex); | 
| +                fDebugger.setIndex(index); | 
| +                if (!fFlushLoopRunning) { | 
| +                    Paint(); | 
| +                } | 
| +            } else if (msg.startsWith("Rewind")) { | 
| +                fCanvas->clear(SK_ColorWHITE); | 
| +                fDebugger.setIndex(0); | 
| +                if (!fFlushLoopRunning) { | 
| +                    Paint(); | 
| +                } | 
| +            } else if (msg.startsWith("StepBack")) { | 
| +                fCanvas->clear(SK_ColorWHITE); | 
| +                int currentIndex = fDebugger.index(); | 
| +                if (currentIndex > 1) { | 
| +                    fDebugger.setIndex(currentIndex - 1); | 
| +                    if (!fFlushLoopRunning) { | 
| +                        Paint(); | 
| +                    } | 
| +                } | 
| +            } else if (msg.startsWith("Pause")) { | 
| +                // TODO(borenet) | 
| +            } else if (msg.startsWith("StepForward")) { | 
| +                int currentIndex = fDebugger.index(); | 
| +                if (currentIndex < fDebugger.getSize() -1) { | 
| +                    fDebugger.setIndex(currentIndex + 1); | 
| +                    if (!fFlushLoopRunning) { | 
| +                        Paint(); | 
| +                    } | 
| +                } | 
| +            } else if (msg.startsWith("Play")) { | 
| +                fDebugger.setIndex(fDebugger.getSize() - 1); | 
| +                if (!fFlushLoopRunning) { | 
| +                    Paint(); | 
| +                } | 
| } | 
| } | 
| } | 
| + | 
| +    void Paint() { | 
| +        if (!fImage.is_null()) { | 
| +            fDebugger.draw(fCanvas); | 
| +            fDeviceContext.PaintImageData(fImage, pp::Point(0, 0)); | 
| +            if (!fFlushPending) { | 
| +                fFlushPending = true; | 
| +                fDeviceContext.Flush(pp::CompletionCallback(&FlushCallback, this)); | 
| +            } else { | 
| +                SkDebugf("A flush is pending... Skipping flush.\n"); | 
| +            } | 
| +        } else { | 
| +            SkDebugf("No pixels to write to!\n"); | 
| +        } | 
| +    } | 
| + | 
| +    virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) { | 
| +        if (position.size().width() == fWidth && | 
| +            position.size().height() == fHeight) { | 
| +            return;  // We don't care about the position, only the size. | 
| +        } | 
| +        fWidth = position.size().width(); | 
| +        fHeight = position.size().height(); | 
| + | 
| +        fDeviceContext = pp::Graphics2D(this, pp::Size(fWidth, fHeight), false); | 
| +        if (!BindGraphics(fDeviceContext)) { | 
| +            SkDebugf("Couldn't bind the device context\n"); | 
| +            return; | 
| +        } | 
| +        fImage = pp::ImageData(this, | 
| +                               PP_IMAGEDATAFORMAT_BGRA_PREMUL, | 
| +                               pp::Size(fWidth, fHeight), false); | 
| +        fBitmap.setConfig(SkBitmap::kARGB_8888_Config, fWidth, fHeight); | 
| +        fBitmap.setPixels(fImage.data()); | 
| +        if (fCanvas) { | 
| +            delete fCanvas; | 
| +        } | 
| +        fCanvas = new SkCanvas(fBitmap); | 
| +        fCanvas->clear(SK_ColorWHITE); | 
| +        if (!fFlushLoopRunning) { | 
| +            Paint(); | 
| +        } | 
| +    } | 
| + | 
| +    void OnFlush() { | 
| +        fFlushLoopRunning = true; | 
| +        fFlushPending = false; | 
| +        Paint(); | 
| +    } | 
| + | 
| +private: | 
| +    pp::Graphics2D fDeviceContext; | 
| +    pp::ImageData fImage; | 
| +    int fWidth; | 
| +    int fHeight; | 
| + | 
| +    SkBitmap fBitmap; | 
| +    SkCanvas* fCanvas; | 
| +    SkDebugger fDebugger; | 
| +    SkPicture* fPicture; | 
| + | 
| +    bool fFlushLoopRunning; | 
| +    bool fFlushPending; | 
| }; | 
|  | 
| +void FlushCallback(void* data, int32_t result) { | 
| +    static_cast<SkiaInstance*>(data)->OnFlush(); | 
| +} | 
| + | 
| class SkiaModule : public pp::Module { | 
| public: | 
| SkiaModule() : pp::Module() {} | 
| @@ -104,11 +205,3 @@ | 
| return new SkiaModule(); | 
| } | 
| }  // namespace pp | 
| - | 
| -/////////////////////////////////////////// | 
| -////////////// SkThread impl ////////////// | 
| -/////////////////////////////////////////// | 
| - | 
| -bool SkThread::setProcessorAffinity(unsigned int processor) { | 
| -    return false; | 
| -} | 
|  |