blob: ca7eddd12dbb4a8c4732df1cfeff49aaa00f413d [file] [log] [blame]
jvanverth9f372462016-04-06 06:08:59 -07001/*
2* Copyright 2016 Google Inc.
3*
4* Use of this source code is governed by a BSD-style license that can be
5* found in the LICENSE file.
6*/
7
jvanverth34524262016-05-04 13:49:13 -07008#include "Viewer.h"
jvanverth9f372462016-04-06 06:08:59 -07009
jvanverth2bb3b6d2016-04-08 07:24:09 -070010#include "GMSlide.h"
jvanverth76963e72016-06-13 09:31:26 -070011#include "SampleSlide.h"
jvanverth2bb3b6d2016-04-08 07:24:09 -070012#include "SKPSlide.h"
jvanverth9f372462016-04-06 06:08:59 -070013
jvanverth2bb3b6d2016-04-08 07:24:09 -070014#include "SkCanvas.h"
15#include "SkCommonFlags.h"
16#include "SkOSFile.h"
17#include "SkRandom.h"
18#include "SkStream.h"
jvanverth9f372462016-04-06 06:08:59 -070019
jvanverth34524262016-05-04 13:49:13 -070020using namespace sk_app;
21
jvanverth9f372462016-04-06 06:08:59 -070022Application* Application::Create(int argc, char** argv, void* platformData) {
jvanverth34524262016-05-04 13:49:13 -070023 return new Viewer(argc, argv, platformData);
jvanverth9f372462016-04-06 06:08:59 -070024}
25
jvanverth9f372462016-04-06 06:08:59 -070026static void on_paint_handler(SkCanvas* canvas, void* userData) {
jvanverth34524262016-05-04 13:49:13 -070027 Viewer* vv = reinterpret_cast<Viewer*>(userData);
jvanverth9f372462016-04-06 06:08:59 -070028
29 return vv->onPaint(canvas);
30}
31
jvanverth814e38d2016-06-06 08:48:47 -070032static bool on_touch_handler(intptr_t owner, Window::InputState state, float x, float y, void* userData)
liyuqiand3cdbca2016-05-17 12:44:20 -070033{
34 Viewer* viewer = reinterpret_cast<Viewer*>(userData);
35
36 return viewer->onTouch(owner, state, x, y);
37}
38
liyuqiane5a6cd92016-05-27 08:52:52 -070039static void on_ui_state_changed_handler(const SkString& stateName, const SkString& stateValue, void* userData) {
40 Viewer* viewer = reinterpret_cast<Viewer*>(userData);
41
42 return viewer->onUIStateChanged(stateName, stateValue);
43}
44
45DEFINE_bool2(fullscreen, f, true, "Run fullscreen.");
jvanverth2bb3b6d2016-04-08 07:24:09 -070046DEFINE_string2(match, m, nullptr,
47 "[~][^]substring[$] [...] of bench name to run.\n"
48 "Multiple matches may be separated by spaces.\n"
49 "~ causes a matching bench to always be skipped\n"
50 "^ requires the start of the bench to match\n"
51 "$ requires the end of the bench to match\n"
52 "^ and $ requires an exact match\n"
53 "If a bench does not match any list entry,\n"
54 "it is skipped unless some list entry starts with ~");
55DEFINE_string(skps, "skps", "Directory to read skps from.");
liyuqian71491dc2016-06-09 12:02:34 -070056#ifdef SK_BUILD_FOR_ANDROID
57DEFINE_bool(vulkan, false, "Run with Vulkan.");
58#else
jvanverth85f758c2016-05-27 06:47:08 -070059DEFINE_bool(vulkan, true, "Run with Vulkan.");
liyuqian71491dc2016-06-09 12:02:34 -070060#endif
jvanverth2bb3b6d2016-04-08 07:24:09 -070061
jvanverthaf236b52016-05-20 06:01:06 -070062const char *kBackendTypeStrings[sk_app::Window::kBackendTypeCount] = {
63 " [OpenGL]",
liyuqiand94ad582016-06-07 14:22:37 -070064 " [Vulkan]",
65 " [Raster]"
jvanverthaf236b52016-05-20 06:01:06 -070066};
67
liyuqiane5a6cd92016-05-27 08:52:52 -070068const char* kName = "name";
69const char* kValue = "value";
70const char* kOptions = "options";
71const char* kSlideStateName = "Slide";
72const char* kBackendStateName = "Backend";
liyuqianb73c24b2016-06-03 08:47:23 -070073const char* kSoftkeyStateName = "Softkey";
74const char* kSoftkeyHint = "Please select a softkey";
liyuqian1f508fd2016-06-07 06:57:40 -070075const char* kFpsStateName = "FPS";
liyuqiane5a6cd92016-05-27 08:52:52 -070076
jvanverth34524262016-05-04 13:49:13 -070077Viewer::Viewer(int argc, char** argv, void* platformData)
jvanverthc265a922016-04-08 12:51:45 -070078 : fCurrentMeasurement(0)
79 , fDisplayStats(false)
jvanverthaf236b52016-05-20 06:01:06 -070080 , fBackendType(sk_app::Window::kVulkan_BackendType)
egdaniel2a0bb0a2016-04-11 08:30:40 -070081 , fZoomCenterX(0.0f)
82 , fZoomCenterY(0.0f)
83 , fZoomLevel(0.0f)
84 , fZoomScale(SK_Scalar1)
jvanverthc265a922016-04-08 12:51:45 -070085{
jvanverth3d6ed3a2016-04-07 11:09:51 -070086 memset(fMeasurements, 0, sizeof(fMeasurements));
jvanverth9f372462016-04-06 06:08:59 -070087
jvanverth2bb3b6d2016-04-08 07:24:09 -070088 SkDebugf("Command line arguments: ");
89 for (int i = 1; i < argc; ++i) {
90 SkDebugf("%s ", argv[i]);
91 }
92 SkDebugf("\n");
93
94 SkCommandLineFlags::Parse(argc, argv);
95
jvanverth85f758c2016-05-27 06:47:08 -070096 fBackendType = FLAGS_vulkan ? sk_app::Window::kVulkan_BackendType
97 : sk_app::Window::kNativeGL_BackendType;
98
jvanverth9f372462016-04-06 06:08:59 -070099 fWindow = Window::CreateNativeWindow(platformData);
jvanverthaf236b52016-05-20 06:01:06 -0700100 fWindow->attach(fBackendType, DisplayParams());
jvanverth9f372462016-04-06 06:08:59 -0700101
102 // register callbacks
brianosman622c8d52016-05-10 06:50:49 -0700103 fCommands.attach(fWindow);
jvanverth9f372462016-04-06 06:08:59 -0700104 fWindow->registerPaintFunc(on_paint_handler, this);
liyuqiand3cdbca2016-05-17 12:44:20 -0700105 fWindow->registerTouchFunc(on_touch_handler, this);
liyuqiane5a6cd92016-05-27 08:52:52 -0700106 fWindow->registerUIStateChangedFunc(on_ui_state_changed_handler, this);
jvanverth9f372462016-04-06 06:08:59 -0700107
brianosman622c8d52016-05-10 06:50:49 -0700108 // add key-bindings
109 fCommands.addCommand('s', "Overlays", "Toggle stats display", [this]() {
110 this->fDisplayStats = !this->fDisplayStats;
111 fWindow->inval();
112 });
113 fCommands.addCommand('c', "Modes", "Toggle sRGB color mode", [this]() {
114 DisplayParams params = fWindow->getDisplayParams();
115 params.fProfileType = (kLinear_SkColorProfileType == params.fProfileType)
116 ? kSRGB_SkColorProfileType : kLinear_SkColorProfileType;
117 fWindow->setDisplayParams(params);
118 this->updateTitle();
119 fWindow->inval();
120 });
121 fCommands.addCommand(Window::Key::kRight, "Right", "Navigation", "Next slide", [this]() {
122 int previousSlide = fCurrentSlide;
123 fCurrentSlide++;
124 if (fCurrentSlide >= fSlides.count()) {
125 fCurrentSlide = 0;
126 }
127 this->setupCurrentSlide(previousSlide);
128 });
129 fCommands.addCommand(Window::Key::kLeft, "Left", "Navigation", "Previous slide", [this]() {
130 int previousSlide = fCurrentSlide;
131 fCurrentSlide--;
132 if (fCurrentSlide < 0) {
133 fCurrentSlide = fSlides.count() - 1;
134 }
135 this->setupCurrentSlide(previousSlide);
136 });
137 fCommands.addCommand(Window::Key::kUp, "Up", "Transform", "Zoom in", [this]() {
138 this->changeZoomLevel(1.f / 32.f);
139 fWindow->inval();
140 });
141 fCommands.addCommand(Window::Key::kDown, "Down", "Transform", "Zoom out", [this]() {
142 this->changeZoomLevel(-1.f / 32.f);
143 fWindow->inval();
144 });
jvanverth85f758c2016-05-27 06:47:08 -0700145#if 0 // this doesn't seem to work on any platform right now
jvanverthaf236b52016-05-20 06:01:06 -0700146#ifndef SK_BUILD_FOR_ANDROID
147 fCommands.addCommand('d', "Modes", "Change rendering backend", [this]() {
148 fWindow->detach();
149
150 if (sk_app::Window::kVulkan_BackendType == fBackendType) {
151 fBackendType = sk_app::Window::kNativeGL_BackendType;
152 }
jvanverth85f758c2016-05-27 06:47:08 -0700153 // TODO: get Vulkan -> OpenGL working on Windows without swapchain creation failure
jvanverthaf236b52016-05-20 06:01:06 -0700154 //else if (sk_app::Window::kNativeGL_BackendType == fBackendType) {
155 // fBackendType = sk_app::Window::kVulkan_BackendType;
156 //}
157
158 fWindow->attach(fBackendType, DisplayParams());
159 this->updateTitle();
jvanverth85f758c2016-05-27 06:47:08 -0700160 fWindow->inval();
jvanverthaf236b52016-05-20 06:01:06 -0700161 });
162#endif
jvanverth85f758c2016-05-27 06:47:08 -0700163#endif
brianosman622c8d52016-05-10 06:50:49 -0700164
jvanverth2bb3b6d2016-04-08 07:24:09 -0700165 // set up slides
166 this->initSlides();
167
djsollen12d62a72016-04-21 07:59:44 -0700168 fAnimTimer.run();
169
jvanverth2bb3b6d2016-04-08 07:24:09 -0700170 // set up first frame
jvanverth2bb3b6d2016-04-08 07:24:09 -0700171 fCurrentSlide = 0;
jvanverthc265a922016-04-08 12:51:45 -0700172 setupCurrentSlide(-1);
jvanverthc265a922016-04-08 12:51:45 -0700173
jvanverth9f372462016-04-06 06:08:59 -0700174 fWindow->show();
175}
176
jvanverth34524262016-05-04 13:49:13 -0700177void Viewer::initSlides() {
liyuqian1f508fd2016-06-07 06:57:40 -0700178 fAllSlideNames = Json::Value(Json::arrayValue);
179
jvanverth2bb3b6d2016-04-08 07:24:09 -0700180 const skiagm::GMRegistry* gms(skiagm::GMRegistry::Head());
181 while (gms) {
182 SkAutoTDelete<skiagm::GM> gm(gms->factory()(nullptr));
183
184 if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, gm->getName())) {
185 sk_sp<Slide> slide(new GMSlide(gm.release()));
186 fSlides.push_back(slide);
187 }
188
189 gms = gms->next();
190 }
191
192 // reverse array
193 for (int i = 0; i < fSlides.count()/2; ++i) {
194 sk_sp<Slide> temp = fSlides[i];
195 fSlides[i] = fSlides[fSlides.count() - i - 1];
196 fSlides[fSlides.count() - i - 1] = temp;
197 }
198
jvanverth76963e72016-06-13 09:31:26 -0700199 // samples
200 const SkViewRegister* reg = SkViewRegister::Head();
201 while (reg) {
202 sk_sp<Slide> slide(new SampleSlide(reg->factory()));
203 fSlides.push_back(slide);
204 reg = reg->next();
205 }
206
jvanverth2bb3b6d2016-04-08 07:24:09 -0700207 // SKPs
208 for (int i = 0; i < FLAGS_skps.count(); i++) {
209 if (SkStrEndsWith(FLAGS_skps[i], ".skp")) {
jvanverthc265a922016-04-08 12:51:45 -0700210 if (SkCommandLineFlags::ShouldSkip(FLAGS_match, FLAGS_skps[i])) {
211 continue;
212 }
213
jvanverth2bb3b6d2016-04-08 07:24:09 -0700214 SkString path(FLAGS_skps[i]);
jvanverthc265a922016-04-08 12:51:45 -0700215 sk_sp<SKPSlide> slide(new SKPSlide(SkOSPath::Basename(path.c_str()), path));
jvanverth2bb3b6d2016-04-08 07:24:09 -0700216 if (slide) {
217 fSlides.push_back(slide);
218 }
219 } else {
220 SkOSFile::Iter it(FLAGS_skps[i], ".skp");
jvanverthc265a922016-04-08 12:51:45 -0700221 SkString skpName;
222 while (it.next(&skpName)) {
223 if (SkCommandLineFlags::ShouldSkip(FLAGS_match, skpName.c_str())) {
224 continue;
225 }
226
227 SkString path = SkOSPath::Join(FLAGS_skps[i], skpName.c_str());
228 sk_sp<SKPSlide> slide(new SKPSlide(skpName, path));
jvanverth2bb3b6d2016-04-08 07:24:09 -0700229 if (slide) {
230 fSlides.push_back(slide);
231 }
232 }
233 }
234 }
235}
236
237
jvanverth34524262016-05-04 13:49:13 -0700238Viewer::~Viewer() {
jvanverth9f372462016-04-06 06:08:59 -0700239 fWindow->detach();
240 delete fWindow;
241}
242
brianosman05de2162016-05-06 13:28:57 -0700243void Viewer::updateTitle() {
jvanverth34524262016-05-04 13:49:13 -0700244 SkString title("Viewer: ");
jvanverthc265a922016-04-08 12:51:45 -0700245 title.append(fSlides[fCurrentSlide]->getName());
brianosman05de2162016-05-06 13:28:57 -0700246 if (kSRGB_SkColorProfileType == fWindow->getDisplayParams().fProfileType) {
247 title.append(" sRGB");
248 }
jvanverthaf236b52016-05-20 06:01:06 -0700249 title.append(kBackendTypeStrings[fBackendType]);
brianosman05de2162016-05-06 13:28:57 -0700250 fWindow->setTitle(title.c_str());
251}
252
253void Viewer::setupCurrentSlide(int previousSlide) {
liyuqiane5a6cd92016-05-27 08:52:52 -0700254 if (fCurrentSlide == previousSlide) {
255 return; // no change; do nothing
256 }
257
liyuqiane46e4f02016-05-20 07:32:19 -0700258 fGesture.reset();
259 fDefaultMatrix.reset();
260 fDefaultMatrixInv.reset();
261
262 if (fWindow->supportsContentRect() && fWindow->scaleContentToFit()) {
263 const SkRect contentRect = fWindow->getContentRect();
264 const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions();
265 const SkRect slideBounds = SkRect::MakeIWH(slideSize.width(), slideSize.height());
266 if (contentRect.width() > 0 && contentRect.height() > 0) {
267 fDefaultMatrix.setRectToRect(slideBounds, contentRect, SkMatrix::kStart_ScaleToFit);
liyuqianbeb1c672016-05-20 11:41:01 -0700268 SkAssertResult(fDefaultMatrix.invert(&fDefaultMatrixInv));
liyuqiane46e4f02016-05-20 07:32:19 -0700269 }
270 }
271
272 if (fWindow->supportsContentRect()) {
273 const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions();
274 SkRect windowRect = fWindow->getContentRect();
275 fDefaultMatrixInv.mapRect(&windowRect);
jvanverth1e305ba2016-06-01 09:39:15 -0700276 fGesture.setTransLimit(SkRect::MakeWH(SkIntToScalar(slideSize.width()),
277 SkIntToScalar(slideSize.height())),
278 windowRect);
liyuqiane46e4f02016-05-20 07:32:19 -0700279 }
280
brianosman05de2162016-05-06 13:28:57 -0700281 this->updateTitle();
liyuqiane5a6cd92016-05-27 08:52:52 -0700282 this->updateUIState();
jvanverth76963e72016-06-13 09:31:26 -0700283 fSlides[fCurrentSlide]->load(SkIntToScalar(fWindow->width()), SkIntToScalar(fWindow->height()));
jvanverthc265a922016-04-08 12:51:45 -0700284 if (previousSlide >= 0) {
285 fSlides[previousSlide]->unload();
286 }
jvanverthc265a922016-04-08 12:51:45 -0700287 fWindow->inval();
288}
289
290#define MAX_ZOOM_LEVEL 8
291#define MIN_ZOOM_LEVEL -8
292
jvanverth34524262016-05-04 13:49:13 -0700293void Viewer::changeZoomLevel(float delta) {
jvanverthc265a922016-04-08 12:51:45 -0700294 fZoomLevel += delta;
295 if (fZoomLevel > 0) {
296 fZoomLevel = SkMinScalar(fZoomLevel, MAX_ZOOM_LEVEL);
297 fZoomScale = fZoomLevel + SK_Scalar1;
298 } else if (fZoomLevel < 0) {
299 fZoomLevel = SkMaxScalar(fZoomLevel, MIN_ZOOM_LEVEL);
300 fZoomScale = SK_Scalar1 / (SK_Scalar1 - fZoomLevel);
301 } else {
302 fZoomScale = SK_Scalar1;
303 }
jvanverthc265a922016-04-08 12:51:45 -0700304}
305
liyuqiand3cdbca2016-05-17 12:44:20 -0700306SkMatrix Viewer::computeMatrix() {
jvanverthc265a922016-04-08 12:51:45 -0700307 SkMatrix m;
308 m.reset();
309
310 if (fZoomLevel) {
311 SkPoint center;
312 //m = this->getLocalMatrix();//.invert(&m);
313 m.mapXY(fZoomCenterX, fZoomCenterY, &center);
314 SkScalar cx = center.fX;
315 SkScalar cy = center.fY;
316
317 m.setTranslate(-cx, -cy);
318 m.postScale(fZoomScale, fZoomScale);
319 m.postTranslate(cx, cy);
320 }
321
liyuqiand3cdbca2016-05-17 12:44:20 -0700322 m.preConcat(fGesture.localM());
323 m.preConcat(fGesture.globalM());
jvanverthc265a922016-04-08 12:51:45 -0700324
liyuqiand3cdbca2016-05-17 12:44:20 -0700325 return m;
jvanverthc265a922016-04-08 12:51:45 -0700326}
327
jvanverth34524262016-05-04 13:49:13 -0700328void Viewer::onPaint(SkCanvas* canvas) {
jvanverthc265a922016-04-08 12:51:45 -0700329 int count = canvas->save();
djsollen12d62a72016-04-21 07:59:44 -0700330
331 if (fWindow->supportsContentRect()) {
332 SkRect contentRect = fWindow->getContentRect();
333 canvas->clipRect(contentRect);
334 canvas->translate(contentRect.fLeft, contentRect.fTop);
335 }
336
337 canvas->clear(SK_ColorWHITE);
liyuqiane46e4f02016-05-20 07:32:19 -0700338 canvas->concat(fDefaultMatrix);
liyuqiand3cdbca2016-05-17 12:44:20 -0700339 canvas->concat(computeMatrix());
jvanverth3d6ed3a2016-04-07 11:09:51 -0700340
jvanverthc265a922016-04-08 12:51:45 -0700341 fSlides[fCurrentSlide]->draw(canvas);
342 canvas->restoreToCount(count);
343
344 if (fDisplayStats) {
345 drawStats(canvas);
346 }
brianosman622c8d52016-05-10 06:50:49 -0700347 fCommands.drawHelp(canvas);
jvanverth3d6ed3a2016-04-07 11:09:51 -0700348}
349
jvanverth814e38d2016-06-06 08:48:47 -0700350bool Viewer::onTouch(intptr_t owner, Window::InputState state, float x, float y) {
liyuqiand3cdbca2016-05-17 12:44:20 -0700351 void* castedOwner = reinterpret_cast<void*>(owner);
liyuqiane46e4f02016-05-20 07:32:19 -0700352 SkPoint touchPoint = fDefaultMatrixInv.mapXY(x, y);
liyuqiand3cdbca2016-05-17 12:44:20 -0700353 switch (state) {
354 case Window::kUp_InputState: {
355 fGesture.touchEnd(castedOwner);
356 break;
357 }
358 case Window::kDown_InputState: {
liyuqiane46e4f02016-05-20 07:32:19 -0700359 fGesture.touchBegin(castedOwner, touchPoint.fX, touchPoint.fY);
liyuqiand3cdbca2016-05-17 12:44:20 -0700360 break;
361 }
362 case Window::kMove_InputState: {
liyuqiane46e4f02016-05-20 07:32:19 -0700363 fGesture.touchMoved(castedOwner, touchPoint.fX, touchPoint.fY);
liyuqiand3cdbca2016-05-17 12:44:20 -0700364 break;
365 }
366 }
367 fWindow->inval();
368 return true;
369}
370
jvanverth34524262016-05-04 13:49:13 -0700371void Viewer::drawStats(SkCanvas* canvas) {
jvanverth3d6ed3a2016-04-07 11:09:51 -0700372 static const float kPixelPerMS = 2.0f;
373 static const int kDisplayWidth = 130;
374 static const int kDisplayHeight = 100;
375 static const int kDisplayPadding = 10;
376 static const int kGraphPadding = 3;
377 static const SkScalar kBaseMS = 1000.f / 60.f; // ms/frame to hit 60 fps
378
379 SkISize canvasSize = canvas->getDeviceSize();
380 SkRect rect = SkRect::MakeXYWH(SkIntToScalar(canvasSize.fWidth-kDisplayWidth-kDisplayPadding),
381 SkIntToScalar(kDisplayPadding),
382 SkIntToScalar(kDisplayWidth), SkIntToScalar(kDisplayHeight));
383 SkPaint paint;
384 canvas->save();
385
djsollen12d62a72016-04-21 07:59:44 -0700386 if (fWindow->supportsContentRect()) {
387 SkRect contentRect = fWindow->getContentRect();
388 canvas->clipRect(contentRect);
389 canvas->translate(contentRect.fLeft, contentRect.fTop);
390 }
391
jvanverth3d6ed3a2016-04-07 11:09:51 -0700392 canvas->clipRect(rect);
393 paint.setColor(SK_ColorBLACK);
394 canvas->drawRect(rect, paint);
395 // draw the 16ms line
396 paint.setColor(SK_ColorLTGRAY);
397 canvas->drawLine(rect.fLeft, rect.fBottom - kBaseMS*kPixelPerMS,
398 rect.fRight, rect.fBottom - kBaseMS*kPixelPerMS, paint);
399 paint.setColor(SK_ColorRED);
400 paint.setStyle(SkPaint::kStroke_Style);
401 canvas->drawRect(rect, paint);
402
403 int x = SkScalarTruncToInt(rect.fLeft) + kGraphPadding;
404 const int xStep = 2;
405 const int startY = SkScalarTruncToInt(rect.fBottom);
406 int i = fCurrentMeasurement;
407 do {
408 int endY = startY - (int)(fMeasurements[i] * kPixelPerMS + 0.5); // round to nearest value
409 canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
410 SkIntToScalar(x), SkIntToScalar(endY), paint);
411 i++;
412 i &= (kMeasurementCount - 1); // fast mod
413 x += xStep;
414 } while (i != fCurrentMeasurement);
jvanverth9f372462016-04-06 06:08:59 -0700415
416 canvas->restore();
417}
418
jvanverth34524262016-05-04 13:49:13 -0700419void Viewer::onIdle(double ms) {
jvanverth3d6ed3a2016-04-07 11:09:51 -0700420 // Record measurements
421 fMeasurements[fCurrentMeasurement++] = ms;
422 fCurrentMeasurement &= (kMeasurementCount - 1); // fast mod
423 SkASSERT(fCurrentMeasurement < kMeasurementCount);
424
jvanverthc265a922016-04-08 12:51:45 -0700425 fAnimTimer.updateTime();
jvanverth9d5e47f2016-04-26 08:01:33 -0700426 if (fSlides[fCurrentSlide]->animate(fAnimTimer) || fDisplayStats) {
jvanverthc265a922016-04-08 12:51:45 -0700427 fWindow->inval();
liyuqian1f508fd2016-06-07 06:57:40 -0700428 updateUIState(); // Update the FPS
jvanverthc265a922016-04-08 12:51:45 -0700429 }
jvanverth9f372462016-04-06 06:08:59 -0700430}
liyuqiane5a6cd92016-05-27 08:52:52 -0700431
432void Viewer::updateUIState() {
liyuqianb73c24b2016-06-03 08:47:23 -0700433 // Slide state
liyuqiane5a6cd92016-05-27 08:52:52 -0700434 Json::Value slideState(Json::objectValue);
435 slideState[kName] = kSlideStateName;
436 slideState[kValue] = fSlides[fCurrentSlide]->getName().c_str();
liyuqian1f508fd2016-06-07 06:57:40 -0700437 if (fAllSlideNames.size() == 0) {
438 for(auto slide : fSlides) {
439 fAllSlideNames.append(Json::Value(slide->getName().c_str()));
440 }
liyuqiane5a6cd92016-05-27 08:52:52 -0700441 }
liyuqian1f508fd2016-06-07 06:57:40 -0700442 slideState[kOptions] = fAllSlideNames;
liyuqiane5a6cd92016-05-27 08:52:52 -0700443
liyuqianb73c24b2016-06-03 08:47:23 -0700444 // Backend state
liyuqiane5a6cd92016-05-27 08:52:52 -0700445 Json::Value backendState(Json::objectValue);
446 backendState[kName] = kBackendStateName;
liyuqian6cb70252016-06-02 12:16:25 -0700447 backendState[kValue] = kBackendTypeStrings[fBackendType];
liyuqiane5a6cd92016-05-27 08:52:52 -0700448 backendState[kOptions] = Json::Value(Json::arrayValue);
liyuqianb73c24b2016-06-03 08:47:23 -0700449 for (auto str : kBackendTypeStrings) {
liyuqian6cb70252016-06-02 12:16:25 -0700450 backendState[kOptions].append(Json::Value(str));
451 }
liyuqiane5a6cd92016-05-27 08:52:52 -0700452
liyuqianb73c24b2016-06-03 08:47:23 -0700453 // Softkey state
454 Json::Value softkeyState(Json::objectValue);
455 softkeyState[kName] = kSoftkeyStateName;
456 softkeyState[kValue] = kSoftkeyHint;
457 softkeyState[kOptions] = Json::Value(Json::arrayValue);
458 softkeyState[kOptions].append(kSoftkeyHint);
459 for (const auto& softkey : fCommands.getCommandsAsSoftkeys()) {
460 softkeyState[kOptions].append(Json::Value(softkey.c_str()));
461 }
462
liyuqian1f508fd2016-06-07 06:57:40 -0700463 // FPS state
464 Json::Value fpsState(Json::objectValue);
465 fpsState[kName] = kFpsStateName;
466 double measurement = fMeasurements[
467 (fCurrentMeasurement + (kMeasurementCount-1)) % kMeasurementCount
468 ];
469 fpsState[kValue] = SkStringPrintf("%8.3lf ms", measurement).c_str();
470 fpsState[kOptions] = Json::Value(Json::arrayValue);
471
liyuqiane5a6cd92016-05-27 08:52:52 -0700472 Json::Value state(Json::arrayValue);
473 state.append(slideState);
474 state.append(backendState);
liyuqianb73c24b2016-06-03 08:47:23 -0700475 state.append(softkeyState);
liyuqian1f508fd2016-06-07 06:57:40 -0700476 state.append(fpsState);
liyuqiane5a6cd92016-05-27 08:52:52 -0700477
478 fWindow->setUIState(state);
479}
480
481void Viewer::onUIStateChanged(const SkString& stateName, const SkString& stateValue) {
liyuqian6cb70252016-06-02 12:16:25 -0700482 // For those who will add more features to handle the state change in this function:
483 // After the change, please call updateUIState no notify the frontend (e.g., Android app).
484 // For example, after slide change, updateUIState is called inside setupCurrentSlide;
485 // after backend change, updateUIState is called in this function.
liyuqiane5a6cd92016-05-27 08:52:52 -0700486 if (stateName.equals(kSlideStateName)) {
487 int previousSlide = fCurrentSlide;
488 fCurrentSlide = 0;
489 for(auto slide : fSlides) {
490 if (slide->getName().equals(stateValue)) {
491 setupCurrentSlide(previousSlide);
492 break;
493 }
494 fCurrentSlide++;
495 }
496 if (fCurrentSlide >= fSlides.count()) {
497 fCurrentSlide = previousSlide;
498 SkDebugf("Slide not found: %s", stateValue.c_str());
499 }
liyuqian6cb70252016-06-02 12:16:25 -0700500 } else if (stateName.equals(kBackendStateName)) {
501 for (int i = 0; i < sk_app::Window::kBackendTypeCount; i++) {
502 if (stateValue.equals(kBackendTypeStrings[i])) {
503 if (fBackendType != i) {
504 fBackendType = (sk_app::Window::BackendType)i;
505 fWindow->detach();
506 fWindow->attach(fBackendType, DisplayParams());
507 fWindow->inval();
508 updateTitle();
509 updateUIState();
510 }
511 break;
512 }
513 }
liyuqianb73c24b2016-06-03 08:47:23 -0700514 } else if (stateName.equals(kSoftkeyStateName)) {
515 if (!stateValue.equals(kSoftkeyHint)) {
516 fCommands.onSoftkey(stateValue);
517 updateUIState(); // This is still needed to reset the value to kSoftkeyHint
518 }
liyuqiane5a6cd92016-05-27 08:52:52 -0700519 } else {
520 SkDebugf("Unknown stateName: %s", stateName.c_str());
521 }
522}