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 |