| OLD | NEW |
| (Empty) |
| 1 | |
| 2 /* | |
| 3 * Copyright 2013 Google Inc. | |
| 4 * | |
| 5 * Use of this source code is governed by a BSD-style license that can be | |
| 6 * found in the LICENSE file. | |
| 7 */ | |
| 8 | |
| 9 #include "ppapi/cpp/completion_callback.h" | |
| 10 #include "ppapi/cpp/graphics_2d.h" | |
| 11 #include "ppapi/cpp/image_data.h" | |
| 12 #include "ppapi/cpp/instance.h" | |
| 13 #include "ppapi/cpp/module.h" | |
| 14 #include "ppapi/cpp/point.h" | |
| 15 #include "ppapi/cpp/rect.h" | |
| 16 #include "ppapi/cpp/var.h" | |
| 17 | |
| 18 #include "SkBase64.h" | |
| 19 #include "SkBitmap.h" | |
| 20 #include "SkCanvas.h" | |
| 21 #include "SkColor.h" | |
| 22 #include "SkDebugger.h" | |
| 23 #include "SkGraphics.h" | |
| 24 #include "SkStream.h" | |
| 25 #include "SkString.h" | |
| 26 | |
| 27 class SkiaInstance; | |
| 28 | |
| 29 // Used by SkDebugf | |
| 30 SkiaInstance* gPluginInstance; | |
| 31 | |
| 32 void FlushCallback(void* data, int32_t result); | |
| 33 | |
| 34 // Skia's subclass of pp::Instance, our interface with the browser. | |
| 35 class SkiaInstance : public pp::Instance { | |
| 36 public: | |
| 37 explicit SkiaInstance(PP_Instance instance) | |
| 38 : pp::Instance(instance) | |
| 39 , fCanvas(NULL) | |
| 40 , fFlushLoopRunning(false) | |
| 41 , fFlushPending(false) | |
| 42 | |
| 43 { | |
| 44 gPluginInstance = this; | |
| 45 SkGraphics::Init(); | |
| 46 } | |
| 47 | |
| 48 virtual ~SkiaInstance() { | |
| 49 SkGraphics::Term(); | |
| 50 gPluginInstance = NULL; | |
| 51 } | |
| 52 | |
| 53 virtual void HandleMessage(const pp::Var& var_message) { | |
| 54 // Receive a message from javascript. | |
| 55 if (var_message.is_string()) { | |
| 56 SkString msg(var_message.AsString().c_str()); | |
| 57 if (msg.startsWith("init")) { | |
| 58 } else if (msg.startsWith("LoadSKP")) { | |
| 59 size_t startIndex = strlen("LoadSKP"); | |
| 60 size_t dataSize = msg.size()/sizeof(char) - startIndex; | |
| 61 SkBase64 decodedData; | |
| 62 decodedData.decode(msg.c_str() + startIndex, dataSize); | |
| 63 size_t decodedSize = 3 * (dataSize / 4); | |
| 64 SkDebugf("Got size: %d\n", decodedSize); | |
| 65 if (!decodedData.getData()) { | |
| 66 SkDebugf("Failed to decode SKP\n"); | |
| 67 return; | |
| 68 } | |
| 69 SkMemoryStream pictureStream(decodedData.getData(), decodedSize)
; | |
| 70 SkPicture* picture = SkPicture::CreateFromStream(&pictureStream)
; | |
| 71 if (NULL == picture) { | |
| 72 SkDebugf("Failed to create SKP.\n"); | |
| 73 return; | |
| 74 } | |
| 75 fDebugger.loadPicture(picture); | |
| 76 picture->unref(); | |
| 77 | |
| 78 // Set up the command list. | |
| 79 PostMessage("ClearCommands"); | |
| 80 for (int i = 0; i < fDebugger.getSize(); ++i) { | |
| 81 SkString addCommand("AddCommand:"); | |
| 82 addCommand.append(fDebugger.getDrawCommandAt(i)->toString())
; | |
| 83 PostMessage(addCommand.c_str()); | |
| 84 } | |
| 85 PostMessage("UpdateCommands"); | |
| 86 | |
| 87 // Set the overview text. | |
| 88 SkString overviewText; | |
| 89 fDebugger.getOverviewText(NULL, 0.0, &overviewText, 1); | |
| 90 overviewText.prepend("SetOverview:"); | |
| 91 PostMessage(overviewText.c_str()); | |
| 92 | |
| 93 // Draw the SKP. | |
| 94 if (!fFlushLoopRunning) { | |
| 95 Paint(); | |
| 96 } | |
| 97 } else if (msg.startsWith("CommandSelected:")) { | |
| 98 size_t startIndex = strlen("CommandSelected:"); | |
| 99 int index = atoi(msg.c_str() + startIndex); | |
| 100 fDebugger.setIndex(index); | |
| 101 if (!fFlushLoopRunning) { | |
| 102 Paint(); | |
| 103 } | |
| 104 } else if (msg.startsWith("Rewind")) { | |
| 105 fCanvas->clear(SK_ColorWHITE); | |
| 106 fDebugger.setIndex(0); | |
| 107 if (!fFlushLoopRunning) { | |
| 108 Paint(); | |
| 109 } | |
| 110 } else if (msg.startsWith("StepBack")) { | |
| 111 fCanvas->clear(SK_ColorWHITE); | |
| 112 int currentIndex = fDebugger.index(); | |
| 113 if (currentIndex > 1) { | |
| 114 fDebugger.setIndex(currentIndex - 1); | |
| 115 if (!fFlushLoopRunning) { | |
| 116 Paint(); | |
| 117 } | |
| 118 } | |
| 119 } else if (msg.startsWith("Pause")) { | |
| 120 // TODO(borenet) | |
| 121 } else if (msg.startsWith("StepForward")) { | |
| 122 int currentIndex = fDebugger.index(); | |
| 123 if (currentIndex < fDebugger.getSize() -1) { | |
| 124 fDebugger.setIndex(currentIndex + 1); | |
| 125 if (!fFlushLoopRunning) { | |
| 126 Paint(); | |
| 127 } | |
| 128 } | |
| 129 } else if (msg.startsWith("Play")) { | |
| 130 fDebugger.setIndex(fDebugger.getSize() - 1); | |
| 131 if (!fFlushLoopRunning) { | |
| 132 Paint(); | |
| 133 } | |
| 134 } | |
| 135 } | |
| 136 } | |
| 137 | |
| 138 void Paint() { | |
| 139 if (!fImage.is_null()) { | |
| 140 fDebugger.draw(fCanvas); | |
| 141 fDeviceContext.PaintImageData(fImage, pp::Point(0, 0)); | |
| 142 if (!fFlushPending) { | |
| 143 fFlushPending = true; | |
| 144 fDeviceContext.Flush(pp::CompletionCallback(&FlushCallback, this
)); | |
| 145 } else { | |
| 146 SkDebugf("A flush is pending... Skipping flush.\n"); | |
| 147 } | |
| 148 } else { | |
| 149 SkDebugf("No pixels to write to!\n"); | |
| 150 } | |
| 151 } | |
| 152 | |
| 153 virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) { | |
| 154 if (position.size().width() == fWidth && | |
| 155 position.size().height() == fHeight) { | |
| 156 return; // We don't care about the position, only the size. | |
| 157 } | |
| 158 fWidth = position.size().width(); | |
| 159 fHeight = position.size().height(); | |
| 160 | |
| 161 fDeviceContext = pp::Graphics2D(this, pp::Size(fWidth, fHeight), false); | |
| 162 if (!BindGraphics(fDeviceContext)) { | |
| 163 SkDebugf("Couldn't bind the device context\n"); | |
| 164 return; | |
| 165 } | |
| 166 fImage = pp::ImageData(this, | |
| 167 PP_IMAGEDATAFORMAT_BGRA_PREMUL, | |
| 168 pp::Size(fWidth, fHeight), false); | |
| 169 const SkImageInfo info = SkImageInfo::MakeN32Premul(fWidth, fHeight); | |
| 170 fBitmap.installPixels(info, fImage.data(), info.minRowBytes()); | |
| 171 if (fCanvas) { | |
| 172 delete fCanvas; | |
| 173 } | |
| 174 fCanvas = new SkCanvas(fBitmap); | |
| 175 fCanvas->clear(SK_ColorWHITE); | |
| 176 if (!fFlushLoopRunning) { | |
| 177 Paint(); | |
| 178 } | |
| 179 } | |
| 180 | |
| 181 void OnFlush() { | |
| 182 fFlushLoopRunning = true; | |
| 183 fFlushPending = false; | |
| 184 Paint(); | |
| 185 } | |
| 186 | |
| 187 private: | |
| 188 pp::Graphics2D fDeviceContext; | |
| 189 pp::ImageData fImage; | |
| 190 int fWidth; | |
| 191 int fHeight; | |
| 192 | |
| 193 SkBitmap fBitmap; | |
| 194 SkCanvas* fCanvas; | |
| 195 SkDebugger fDebugger; | |
| 196 | |
| 197 bool fFlushLoopRunning; | |
| 198 bool fFlushPending; | |
| 199 }; | |
| 200 | |
| 201 void FlushCallback(void* data, int32_t result) { | |
| 202 static_cast<SkiaInstance*>(data)->OnFlush(); | |
| 203 } | |
| 204 | |
| 205 class SkiaModule : public pp::Module { | |
| 206 public: | |
| 207 SkiaModule() : pp::Module() {} | |
| 208 virtual ~SkiaModule() {} | |
| 209 | |
| 210 virtual pp::Instance* CreateInstance(PP_Instance instance) { | |
| 211 return new SkiaInstance(instance); | |
| 212 } | |
| 213 }; | |
| 214 | |
| 215 namespace pp { | |
| 216 Module* CreateModule() { | |
| 217 return new SkiaModule(); | |
| 218 } | |
| 219 } // namespace pp | |
| OLD | NEW |