| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 1 | /* |
| 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 | |
| jvanverth | 3452426 | 2016-05-04 13:49:13 -0700 | [diff] [blame] | 8 | #include "Viewer.h" |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 9 | |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 10 | #include "GMSlide.h" |
| liyuqian | 6f163d2 | 2016-06-13 12:26:45 -0700 | [diff] [blame] | 11 | #include "ImageSlide.h" |
| Greg Daniel | 9fcc743 | 2016-11-29 16:35:19 -0500 | [diff] [blame] | 12 | #include "Resources.h" |
| jvanverth | c7027ab | 2016-06-16 09:52:35 -0700 | [diff] [blame] | 13 | #include "SampleSlide.h" |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 14 | #include "SKPSlide.h" |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 15 | |
| Greg Daniel | 285db44 | 2016-10-14 09:12:53 -0400 | [diff] [blame] | 16 | #include "SkATrace.h" |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 17 | #include "SkCanvas.h" |
| Brian Osman | 2dd9693 | 2016-10-18 15:33:53 -0400 | [diff] [blame] | 18 | #include "SkCommandLineFlags.h" |
| liyuqian | 74959a1 | 2016-06-16 14:10:34 -0700 | [diff] [blame] | 19 | #include "SkDashPathEffect.h" |
| Greg Daniel | 285db44 | 2016-10-14 09:12:53 -0400 | [diff] [blame] | 20 | #include "SkGraphics.h" |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 21 | #include "SkImagePriv.h" |
| liyuqian | 6f163d2 | 2016-06-13 12:26:45 -0700 | [diff] [blame] | 22 | #include "SkMetaData.h" |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 23 | #include "SkOSFile.h" |
| Ben Wagner | bf111d7 | 2016-11-07 18:05:29 -0500 | [diff] [blame] | 24 | #include "SkOSPath.h" |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 25 | #include "SkRandom.h" |
| 26 | #include "SkStream.h" |
| liyuqian | 74959a1 | 2016-06-16 14:10:34 -0700 | [diff] [blame] | 27 | #include "SkSurface.h" |
| liyuqian | 2edb0f4 | 2016-07-06 14:11:32 -0700 | [diff] [blame] | 28 | #include "SkTime.h" |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 29 | |
| jvanverth | 3452426 | 2016-05-04 13:49:13 -0700 | [diff] [blame] | 30 | using namespace sk_app; |
| 31 | |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 32 | Application* Application::Create(int argc, char** argv, void* platformData) { |
| jvanverth | 3452426 | 2016-05-04 13:49:13 -0700 | [diff] [blame] | 33 | return new Viewer(argc, argv, platformData); |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 34 | } |
| 35 | |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 36 | static void on_paint_handler(SkCanvas* canvas, void* userData) { |
| jvanverth | 3452426 | 2016-05-04 13:49:13 -0700 | [diff] [blame] | 37 | Viewer* vv = reinterpret_cast<Viewer*>(userData); |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 38 | |
| 39 | return vv->onPaint(canvas); |
| 40 | } |
| 41 | |
| jvanverth | 814e38d | 2016-06-06 08:48:47 -0700 | [diff] [blame] | 42 | static bool on_touch_handler(intptr_t owner, Window::InputState state, float x, float y, void* userData) |
| liyuqian | d3cdbca | 2016-05-17 12:44:20 -0700 | [diff] [blame] | 43 | { |
| 44 | Viewer* viewer = reinterpret_cast<Viewer*>(userData); |
| 45 | |
| 46 | return viewer->onTouch(owner, state, x, y); |
| 47 | } |
| 48 | |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 49 | static void on_ui_state_changed_handler(const SkString& stateName, const SkString& stateValue, void* userData) { |
| 50 | Viewer* viewer = reinterpret_cast<Viewer*>(userData); |
| 51 | |
| 52 | return viewer->onUIStateChanged(stateName, stateValue); |
| 53 | } |
| 54 | |
| Brian Osman | 2dd9693 | 2016-10-18 15:33:53 -0400 | [diff] [blame] | 55 | static DEFINE_bool2(fullscreen, f, true, "Run fullscreen."); |
| Brian Osman | 16adfa3 | 2016-10-18 14:42:44 -0400 | [diff] [blame] | 56 | |
| Brian Osman | 2dd9693 | 2016-10-18 15:33:53 -0400 | [diff] [blame] | 57 | static DEFINE_string2(match, m, nullptr, |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 58 | "[~][^]substring[$] [...] of bench name to run.\n" |
| 59 | "Multiple matches may be separated by spaces.\n" |
| 60 | "~ causes a matching bench to always be skipped\n" |
| 61 | "^ requires the start of the bench to match\n" |
| 62 | "$ requires the end of the bench to match\n" |
| 63 | "^ and $ requires an exact match\n" |
| 64 | "If a bench does not match any list entry,\n" |
| 65 | "it is skipped unless some list entry starts with ~"); |
| bsalomon | 6c471f7 | 2016-07-26 12:56:32 -0700 | [diff] [blame] | 66 | |
| 67 | #ifdef SK_VULKAN |
| jvanverth | b8794cc | 2016-07-27 14:29:18 -0700 | [diff] [blame] | 68 | # define BACKENDS_STR "\"sw\", \"gl\", and \"vk\"" |
| bsalomon | 6c471f7 | 2016-07-26 12:56:32 -0700 | [diff] [blame] | 69 | #else |
| 70 | # define BACKENDS_STR "\"sw\" and \"gl\"" |
| 71 | #endif |
| 72 | |
| liyuqian | 71491dc | 2016-06-09 12:02:34 -0700 | [diff] [blame] | 73 | #ifdef SK_BUILD_FOR_ANDROID |
| Brian Osman | 2dd9693 | 2016-10-18 15:33:53 -0400 | [diff] [blame] | 74 | static DEFINE_string(skps, "/data/local/tmp/skia", "Directory to read skps from."); |
| 75 | static DEFINE_string(jpgs, "/data/local/tmp/skia", "Directory to read jpgs from."); |
| liyuqian | 71491dc | 2016-06-09 12:02:34 -0700 | [diff] [blame] | 76 | #else |
| Brian Osman | 2dd9693 | 2016-10-18 15:33:53 -0400 | [diff] [blame] | 77 | static DEFINE_string(skps, "skps", "Directory to read skps from."); |
| 78 | static DEFINE_string(jpgs, "jpgs", "Directory to read jpgs from."); |
| liyuqian | 71491dc | 2016-06-09 12:02:34 -0700 | [diff] [blame] | 79 | #endif |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 80 | |
| Brian Osman | 2dd9693 | 2016-10-18 15:33:53 -0400 | [diff] [blame] | 81 | static DEFINE_string2(backend, b, "sw", "Backend to use. Allowed values are " BACKENDS_STR "."); |
| bsalomon | 6c471f7 | 2016-07-26 12:56:32 -0700 | [diff] [blame] | 82 | |
| Brian Osman | 2dd9693 | 2016-10-18 15:33:53 -0400 | [diff] [blame] | 83 | static DEFINE_bool(atrace, false, "Enable support for using ATrace. ATrace is only supported on Android."); |
| Greg Daniel | 285db44 | 2016-10-14 09:12:53 -0400 | [diff] [blame] | 84 | |
| jvanverth | af236b5 | 2016-05-20 06:01:06 -0700 | [diff] [blame] | 85 | const char *kBackendTypeStrings[sk_app::Window::kBackendTypeCount] = { |
| 86 | " [OpenGL]", |
| jvanverth | 063ece7 | 2016-06-17 09:29:14 -0700 | [diff] [blame] | 87 | #ifdef SK_VULKAN |
| liyuqian | d94ad58 | 2016-06-07 14:22:37 -0700 | [diff] [blame] | 88 | " [Vulkan]", |
| jvanverth | 063ece7 | 2016-06-17 09:29:14 -0700 | [diff] [blame] | 89 | #endif |
| liyuqian | d94ad58 | 2016-06-07 14:22:37 -0700 | [diff] [blame] | 90 | " [Raster]" |
| jvanverth | af236b5 | 2016-05-20 06:01:06 -0700 | [diff] [blame] | 91 | }; |
| 92 | |
| bsalomon | 6c471f7 | 2016-07-26 12:56:32 -0700 | [diff] [blame] | 93 | static sk_app::Window::BackendType get_backend_type(const char* str) { |
| 94 | #ifdef SK_VULKAN |
| 95 | if (0 == strcmp(str, "vk")) { |
| 96 | return sk_app::Window::kVulkan_BackendType; |
| 97 | } else |
| 98 | #endif |
| 99 | if (0 == strcmp(str, "gl")) { |
| 100 | return sk_app::Window::kNativeGL_BackendType; |
| 101 | } else if (0 == strcmp(str, "sw")) { |
| 102 | return sk_app::Window::kRaster_BackendType; |
| 103 | } else { |
| 104 | SkDebugf("Unknown backend type, %s, defaulting to sw.", str); |
| 105 | return sk_app::Window::kRaster_BackendType; |
| 106 | } |
| 107 | } |
| 108 | |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 109 | const char* kName = "name"; |
| 110 | const char* kValue = "value"; |
| 111 | const char* kOptions = "options"; |
| 112 | const char* kSlideStateName = "Slide"; |
| 113 | const char* kBackendStateName = "Backend"; |
| liyuqian | b73c24b | 2016-06-03 08:47:23 -0700 | [diff] [blame] | 114 | const char* kSoftkeyStateName = "Softkey"; |
| 115 | const char* kSoftkeyHint = "Please select a softkey"; |
| liyuqian | 1f508fd | 2016-06-07 06:57:40 -0700 | [diff] [blame] | 116 | const char* kFpsStateName = "FPS"; |
| liyuqian | 6f163d2 | 2016-06-13 12:26:45 -0700 | [diff] [blame] | 117 | const char* kON = "ON"; |
| 118 | const char* kOFF = "OFF"; |
| liyuqian | 2edb0f4 | 2016-07-06 14:11:32 -0700 | [diff] [blame] | 119 | const char* kRefreshStateName = "Refresh"; |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 120 | |
| jvanverth | 3452426 | 2016-05-04 13:49:13 -0700 | [diff] [blame] | 121 | Viewer::Viewer(int argc, char** argv, void* platformData) |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 122 | : fCurrentMeasurement(0) |
| 123 | , fDisplayStats(false) |
| liyuqian | 2edb0f4 | 2016-07-06 14:11:32 -0700 | [diff] [blame] | 124 | , fRefresh(false) |
| jvanverth | 063ece7 | 2016-06-17 09:29:14 -0700 | [diff] [blame] | 125 | , fBackendType(sk_app::Window::kNativeGL_BackendType) |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 126 | , fColorType(kN32_SkColorType) |
| 127 | , fColorSpace(nullptr) |
| egdaniel | 2a0bb0a | 2016-04-11 08:30:40 -0700 | [diff] [blame] | 128 | , fZoomCenterX(0.0f) |
| 129 | , fZoomCenterY(0.0f) |
| 130 | , fZoomLevel(0.0f) |
| 131 | , fZoomScale(SK_Scalar1) |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 132 | { |
| Greg Daniel | 285db44 | 2016-10-14 09:12:53 -0400 | [diff] [blame] | 133 | SkGraphics::Init(); |
| jvanverth | 3d6ed3a | 2016-04-07 11:09:51 -0700 | [diff] [blame] | 134 | memset(fMeasurements, 0, sizeof(fMeasurements)); |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 135 | |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 136 | SkDebugf("Command line arguments: "); |
| 137 | for (int i = 1; i < argc; ++i) { |
| 138 | SkDebugf("%s ", argv[i]); |
| 139 | } |
| 140 | SkDebugf("\n"); |
| 141 | |
| 142 | SkCommandLineFlags::Parse(argc, argv); |
| Greg Daniel | 9fcc743 | 2016-11-29 16:35:19 -0500 | [diff] [blame] | 143 | #ifdef SK_BUILD_FOR_ANDROID |
| 144 | SetResourcePath("/data/local/tmp/skia"); |
| 145 | #endif |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 146 | |
| Greg Daniel | 285db44 | 2016-10-14 09:12:53 -0400 | [diff] [blame] | 147 | if (FLAGS_atrace) { |
| 148 | SkEventTracer::SetInstance(new SkATrace()); |
| 149 | } |
| 150 | |
| bsalomon | 6c471f7 | 2016-07-26 12:56:32 -0700 | [diff] [blame] | 151 | fBackendType = get_backend_type(FLAGS_backend[0]); |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 152 | fWindow = Window::CreateNativeWindow(platformData); |
| jvanverth | af236b5 | 2016-05-20 06:01:06 -0700 | [diff] [blame] | 153 | fWindow->attach(fBackendType, DisplayParams()); |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 154 | |
| 155 | // register callbacks |
| brianosman | 622c8d5 | 2016-05-10 06:50:49 -0700 | [diff] [blame] | 156 | fCommands.attach(fWindow); |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 157 | fWindow->registerPaintFunc(on_paint_handler, this); |
| liyuqian | d3cdbca | 2016-05-17 12:44:20 -0700 | [diff] [blame] | 158 | fWindow->registerTouchFunc(on_touch_handler, this); |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 159 | fWindow->registerUIStateChangedFunc(on_ui_state_changed_handler, this); |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 160 | |
| brianosman | 622c8d5 | 2016-05-10 06:50:49 -0700 | [diff] [blame] | 161 | // add key-bindings |
| 162 | fCommands.addCommand('s', "Overlays", "Toggle stats display", [this]() { |
| 163 | this->fDisplayStats = !this->fDisplayStats; |
| 164 | fWindow->inval(); |
| 165 | }); |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 166 | fCommands.addCommand('c', "Modes", "Cycle color mode", [this]() { |
| 167 | if (!fColorSpace) { |
| 168 | // Legacy -> sRGB |
| 169 | this->setColorMode(kN32_SkColorType, SkColorSpace::MakeSRGB()); |
| 170 | } else if (kN32_SkColorType == fColorType) { |
| 171 | // sRGB -> F16 sRGB |
| 172 | this->setColorMode(kRGBA_F16_SkColorType, SkColorSpace::MakeSRGBLinear()); |
| 173 | } else { |
| 174 | // F16 sRGB -> Legacy |
| 175 | this->setColorMode(kN32_SkColorType, nullptr); |
| 176 | } |
| brianosman | 622c8d5 | 2016-05-10 06:50:49 -0700 | [diff] [blame] | 177 | }); |
| 178 | fCommands.addCommand(Window::Key::kRight, "Right", "Navigation", "Next slide", [this]() { |
| 179 | int previousSlide = fCurrentSlide; |
| 180 | fCurrentSlide++; |
| 181 | if (fCurrentSlide >= fSlides.count()) { |
| 182 | fCurrentSlide = 0; |
| 183 | } |
| 184 | this->setupCurrentSlide(previousSlide); |
| 185 | }); |
| 186 | fCommands.addCommand(Window::Key::kLeft, "Left", "Navigation", "Previous slide", [this]() { |
| 187 | int previousSlide = fCurrentSlide; |
| 188 | fCurrentSlide--; |
| 189 | if (fCurrentSlide < 0) { |
| 190 | fCurrentSlide = fSlides.count() - 1; |
| 191 | } |
| 192 | this->setupCurrentSlide(previousSlide); |
| 193 | }); |
| 194 | fCommands.addCommand(Window::Key::kUp, "Up", "Transform", "Zoom in", [this]() { |
| 195 | this->changeZoomLevel(1.f / 32.f); |
| 196 | fWindow->inval(); |
| 197 | }); |
| 198 | fCommands.addCommand(Window::Key::kDown, "Down", "Transform", "Zoom out", [this]() { |
| 199 | this->changeZoomLevel(-1.f / 32.f); |
| 200 | fWindow->inval(); |
| 201 | }); |
| jvanverth | af236b5 | 2016-05-20 06:01:06 -0700 | [diff] [blame] | 202 | fCommands.addCommand('d', "Modes", "Change rendering backend", [this]() { |
| Jim Van Verth | d63c102 | 2017-01-05 13:50:49 -0500 | [diff] [blame] | 203 | #if defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC) |
| jvanverth | b8794cc | 2016-07-27 14:29:18 -0700 | [diff] [blame] | 204 | if (sk_app::Window::kRaster_BackendType == fBackendType) { |
| 205 | fBackendType = sk_app::Window::kNativeGL_BackendType; |
| 206 | #ifdef SK_VULKAN |
| 207 | } else if (sk_app::Window::kNativeGL_BackendType == fBackendType) { |
| 208 | fBackendType = sk_app::Window::kVulkan_BackendType; |
| 209 | #endif |
| 210 | } else { |
| 211 | fBackendType = sk_app::Window::kRaster_BackendType; |
| 212 | } |
| Jim Van Verth | d63c102 | 2017-01-05 13:50:49 -0500 | [diff] [blame] | 213 | #elif defined(SK_BUILD_FOR_UNIX) |
| 214 | // Switching to and from Vulkan is problematic on Linux so disabled for now |
| 215 | if (sk_app::Window::kRaster_BackendType == fBackendType) { |
| 216 | fBackendType = sk_app::Window::kNativeGL_BackendType; |
| 217 | } else if (sk_app::Window::kNativeGL_BackendType == fBackendType) { |
| 218 | fBackendType = sk_app::Window::kRaster_BackendType; |
| 219 | } |
| 220 | #endif |
| jvanverth | af236b5 | 2016-05-20 06:01:06 -0700 | [diff] [blame] | 221 | fWindow->detach(); |
| 222 | |
| Jim Van Verth | d63c102 | 2017-01-05 13:50:49 -0500 | [diff] [blame] | 223 | #if defined(SK_BUILD_FOR_WIN) && defined(SK_VULKAN) |
| 224 | // Switching from OpenGL to Vulkan in the same window is problematic at this point on |
| 225 | // Windows, so we just delete the window and recreate it. |
| jvanverth | af236b5 | 2016-05-20 06:01:06 -0700 | [diff] [blame] | 226 | if (sk_app::Window::kVulkan_BackendType == fBackendType) { |
| jvanverth | b8794cc | 2016-07-27 14:29:18 -0700 | [diff] [blame] | 227 | delete fWindow; |
| 228 | fWindow = Window::CreateNativeWindow(nullptr); |
| jvanverth | af236b5 | 2016-05-20 06:01:06 -0700 | [diff] [blame] | 229 | |
| jvanverth | b8794cc | 2016-07-27 14:29:18 -0700 | [diff] [blame] | 230 | // re-register callbacks |
| 231 | fCommands.attach(fWindow); |
| 232 | fWindow->registerPaintFunc(on_paint_handler, this); |
| 233 | fWindow->registerTouchFunc(on_touch_handler, this); |
| 234 | fWindow->registerUIStateChangedFunc(on_ui_state_changed_handler, this); |
| 235 | } |
| 236 | #endif |
| jvanverth | af236b5 | 2016-05-20 06:01:06 -0700 | [diff] [blame] | 237 | fWindow->attach(fBackendType, DisplayParams()); |
| jvanverth | b8794cc | 2016-07-27 14:29:18 -0700 | [diff] [blame] | 238 | |
| jvanverth | af236b5 | 2016-05-20 06:01:06 -0700 | [diff] [blame] | 239 | this->updateTitle(); |
| jvanverth | 85f758c | 2016-05-27 06:47:08 -0700 | [diff] [blame] | 240 | fWindow->inval(); |
| jvanverth | b8794cc | 2016-07-27 14:29:18 -0700 | [diff] [blame] | 241 | fWindow->show(); |
| jvanverth | af236b5 | 2016-05-20 06:01:06 -0700 | [diff] [blame] | 242 | }); |
| brianosman | 622c8d5 | 2016-05-10 06:50:49 -0700 | [diff] [blame] | 243 | |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 244 | // set up slides |
| 245 | this->initSlides(); |
| 246 | |
| djsollen | 12d62a7 | 2016-04-21 07:59:44 -0700 | [diff] [blame] | 247 | fAnimTimer.run(); |
| 248 | |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 249 | // set up first frame |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 250 | fCurrentSlide = 0; |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 251 | setupCurrentSlide(-1); |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 252 | |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 253 | fWindow->show(); |
| 254 | } |
| 255 | |
| jvanverth | 3452426 | 2016-05-04 13:49:13 -0700 | [diff] [blame] | 256 | void Viewer::initSlides() { |
| liyuqian | 1f508fd | 2016-06-07 06:57:40 -0700 | [diff] [blame] | 257 | fAllSlideNames = Json::Value(Json::arrayValue); |
| 258 | |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 259 | const skiagm::GMRegistry* gms(skiagm::GMRegistry::Head()); |
| 260 | while (gms) { |
| Ben Wagner | 145dbcd | 2016-11-03 14:40:50 -0400 | [diff] [blame] | 261 | std::unique_ptr<skiagm::GM> gm(gms->factory()(nullptr)); |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 262 | |
| 263 | if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, gm->getName())) { |
| 264 | sk_sp<Slide> slide(new GMSlide(gm.release())); |
| 265 | fSlides.push_back(slide); |
| 266 | } |
| 267 | |
| 268 | gms = gms->next(); |
| 269 | } |
| 270 | |
| 271 | // reverse array |
| 272 | for (int i = 0; i < fSlides.count()/2; ++i) { |
| 273 | sk_sp<Slide> temp = fSlides[i]; |
| 274 | fSlides[i] = fSlides[fSlides.count() - i - 1]; |
| 275 | fSlides[fSlides.count() - i - 1] = temp; |
| 276 | } |
| 277 | |
| jvanverth | c7027ab | 2016-06-16 09:52:35 -0700 | [diff] [blame] | 278 | // samples |
| 279 | const SkViewRegister* reg = SkViewRegister::Head(); |
| 280 | while (reg) { |
| 281 | sk_sp<Slide> slide(new SampleSlide(reg->factory())); |
| brianosman | e1d2007 | 2016-07-12 09:07:33 -0700 | [diff] [blame] | 282 | if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, slide->getName().c_str())) { |
| 283 | fSlides.push_back(slide); |
| 284 | } |
| jvanverth | c7027ab | 2016-06-16 09:52:35 -0700 | [diff] [blame] | 285 | reg = reg->next(); |
| 286 | } |
| 287 | |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 288 | // SKPs |
| 289 | for (int i = 0; i < FLAGS_skps.count(); i++) { |
| 290 | if (SkStrEndsWith(FLAGS_skps[i], ".skp")) { |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 291 | if (SkCommandLineFlags::ShouldSkip(FLAGS_match, FLAGS_skps[i])) { |
| 292 | continue; |
| 293 | } |
| 294 | |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 295 | SkString path(FLAGS_skps[i]); |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 296 | sk_sp<SKPSlide> slide(new SKPSlide(SkOSPath::Basename(path.c_str()), path)); |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 297 | if (slide) { |
| 298 | fSlides.push_back(slide); |
| 299 | } |
| 300 | } else { |
| 301 | SkOSFile::Iter it(FLAGS_skps[i], ".skp"); |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 302 | SkString skpName; |
| 303 | while (it.next(&skpName)) { |
| 304 | if (SkCommandLineFlags::ShouldSkip(FLAGS_match, skpName.c_str())) { |
| 305 | continue; |
| 306 | } |
| 307 | |
| 308 | SkString path = SkOSPath::Join(FLAGS_skps[i], skpName.c_str()); |
| 309 | sk_sp<SKPSlide> slide(new SKPSlide(skpName, path)); |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 310 | if (slide) { |
| 311 | fSlides.push_back(slide); |
| 312 | } |
| 313 | } |
| 314 | } |
| 315 | } |
| liyuqian | 6f163d2 | 2016-06-13 12:26:45 -0700 | [diff] [blame] | 316 | |
| 317 | // JPGs |
| 318 | for (int i = 0; i < FLAGS_jpgs.count(); i++) { |
| 319 | SkOSFile::Iter it(FLAGS_jpgs[i], ".jpg"); |
| 320 | SkString jpgName; |
| 321 | while (it.next(&jpgName)) { |
| brianosman | e1d2007 | 2016-07-12 09:07:33 -0700 | [diff] [blame] | 322 | if (SkCommandLineFlags::ShouldSkip(FLAGS_match, jpgName.c_str())) { |
| 323 | continue; |
| 324 | } |
| 325 | |
| liyuqian | 6f163d2 | 2016-06-13 12:26:45 -0700 | [diff] [blame] | 326 | SkString path = SkOSPath::Join(FLAGS_jpgs[i], jpgName.c_str()); |
| 327 | sk_sp<ImageSlide> slide(new ImageSlide(jpgName, path)); |
| 328 | if (slide) { |
| 329 | fSlides.push_back(slide); |
| 330 | } |
| 331 | } |
| 332 | } |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 333 | } |
| 334 | |
| 335 | |
| jvanverth | 3452426 | 2016-05-04 13:49:13 -0700 | [diff] [blame] | 336 | Viewer::~Viewer() { |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 337 | fWindow->detach(); |
| 338 | delete fWindow; |
| 339 | } |
| 340 | |
| brianosman | 05de216 | 2016-05-06 13:28:57 -0700 | [diff] [blame] | 341 | void Viewer::updateTitle() { |
| jvanverth | 3452426 | 2016-05-04 13:49:13 -0700 | [diff] [blame] | 342 | SkString title("Viewer: "); |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 343 | title.append(fSlides[fCurrentSlide]->getName()); |
| brianosman | b109b8c | 2016-06-16 13:03:24 -0700 | [diff] [blame] | 344 | |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 345 | title.appendf(" %s", sk_tool_utils::colortype_name(fColorType)); |
| 346 | |
| 347 | // TODO: Find a short string to describe the gamut of the color space? |
| 348 | if (fColorSpace) { |
| 349 | title.append(" ColorManaged"); |
| brianosman | 05de216 | 2016-05-06 13:28:57 -0700 | [diff] [blame] | 350 | } |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 351 | |
| jvanverth | af236b5 | 2016-05-20 06:01:06 -0700 | [diff] [blame] | 352 | title.append(kBackendTypeStrings[fBackendType]); |
| brianosman | 05de216 | 2016-05-06 13:28:57 -0700 | [diff] [blame] | 353 | fWindow->setTitle(title.c_str()); |
| 354 | } |
| 355 | |
| 356 | void Viewer::setupCurrentSlide(int previousSlide) { |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 357 | if (fCurrentSlide == previousSlide) { |
| 358 | return; // no change; do nothing |
| 359 | } |
| 360 | |
| liyuqian | 6f163d2 | 2016-06-13 12:26:45 -0700 | [diff] [blame] | 361 | // prepare dimensions for image slides |
| jvanverth | c7027ab | 2016-06-16 09:52:35 -0700 | [diff] [blame] | 362 | fSlides[fCurrentSlide]->load(SkIntToScalar(fWindow->width()), SkIntToScalar(fWindow->height())); |
| liyuqian | 6f163d2 | 2016-06-13 12:26:45 -0700 | [diff] [blame] | 363 | |
| liyuqian | e46e4f0 | 2016-05-20 07:32:19 -0700 | [diff] [blame] | 364 | fGesture.reset(); |
| 365 | fDefaultMatrix.reset(); |
| 366 | fDefaultMatrixInv.reset(); |
| 367 | |
| 368 | if (fWindow->supportsContentRect() && fWindow->scaleContentToFit()) { |
| 369 | const SkRect contentRect = fWindow->getContentRect(); |
| 370 | const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions(); |
| 371 | const SkRect slideBounds = SkRect::MakeIWH(slideSize.width(), slideSize.height()); |
| 372 | if (contentRect.width() > 0 && contentRect.height() > 0) { |
| 373 | fDefaultMatrix.setRectToRect(slideBounds, contentRect, SkMatrix::kStart_ScaleToFit); |
| liyuqian | beb1c67 | 2016-05-20 11:41:01 -0700 | [diff] [blame] | 374 | SkAssertResult(fDefaultMatrix.invert(&fDefaultMatrixInv)); |
| liyuqian | e46e4f0 | 2016-05-20 07:32:19 -0700 | [diff] [blame] | 375 | } |
| 376 | } |
| 377 | |
| 378 | if (fWindow->supportsContentRect()) { |
| 379 | const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions(); |
| 380 | SkRect windowRect = fWindow->getContentRect(); |
| 381 | fDefaultMatrixInv.mapRect(&windowRect); |
| jvanverth | 1e305ba | 2016-06-01 09:39:15 -0700 | [diff] [blame] | 382 | fGesture.setTransLimit(SkRect::MakeWH(SkIntToScalar(slideSize.width()), |
| 383 | SkIntToScalar(slideSize.height())), |
| 384 | windowRect); |
| liyuqian | e46e4f0 | 2016-05-20 07:32:19 -0700 | [diff] [blame] | 385 | } |
| 386 | |
| brianosman | 05de216 | 2016-05-06 13:28:57 -0700 | [diff] [blame] | 387 | this->updateTitle(); |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 388 | this->updateUIState(); |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 389 | if (previousSlide >= 0) { |
| 390 | fSlides[previousSlide]->unload(); |
| 391 | } |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 392 | fWindow->inval(); |
| 393 | } |
| 394 | |
| 395 | #define MAX_ZOOM_LEVEL 8 |
| 396 | #define MIN_ZOOM_LEVEL -8 |
| 397 | |
| jvanverth | 3452426 | 2016-05-04 13:49:13 -0700 | [diff] [blame] | 398 | void Viewer::changeZoomLevel(float delta) { |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 399 | fZoomLevel += delta; |
| 400 | if (fZoomLevel > 0) { |
| 401 | fZoomLevel = SkMinScalar(fZoomLevel, MAX_ZOOM_LEVEL); |
| 402 | fZoomScale = fZoomLevel + SK_Scalar1; |
| 403 | } else if (fZoomLevel < 0) { |
| 404 | fZoomLevel = SkMaxScalar(fZoomLevel, MIN_ZOOM_LEVEL); |
| 405 | fZoomScale = SK_Scalar1 / (SK_Scalar1 - fZoomLevel); |
| 406 | } else { |
| 407 | fZoomScale = SK_Scalar1; |
| 408 | } |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 409 | } |
| 410 | |
| liyuqian | d3cdbca | 2016-05-17 12:44:20 -0700 | [diff] [blame] | 411 | SkMatrix Viewer::computeMatrix() { |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 412 | SkMatrix m; |
| 413 | m.reset(); |
| 414 | |
| 415 | if (fZoomLevel) { |
| 416 | SkPoint center; |
| 417 | //m = this->getLocalMatrix();//.invert(&m); |
| 418 | m.mapXY(fZoomCenterX, fZoomCenterY, ¢er); |
| 419 | SkScalar cx = center.fX; |
| 420 | SkScalar cy = center.fY; |
| 421 | |
| 422 | m.setTranslate(-cx, -cy); |
| 423 | m.postScale(fZoomScale, fZoomScale); |
| 424 | m.postTranslate(cx, cy); |
| 425 | } |
| 426 | |
| liyuqian | d3cdbca | 2016-05-17 12:44:20 -0700 | [diff] [blame] | 427 | m.preConcat(fGesture.localM()); |
| 428 | m.preConcat(fGesture.globalM()); |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 429 | |
| liyuqian | d3cdbca | 2016-05-17 12:44:20 -0700 | [diff] [blame] | 430 | return m; |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 431 | } |
| 432 | |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 433 | void Viewer::setColorMode(SkColorType colorType, sk_sp<SkColorSpace> colorSpace) { |
| 434 | fColorType = colorType; |
| 435 | fColorSpace = std::move(colorSpace); |
| liyuqian | 6f163d2 | 2016-06-13 12:26:45 -0700 | [diff] [blame] | 436 | |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 437 | // When we're in color managed mode, we tag our window surface as sRGB. If we've switched into |
| 438 | // or out of legacy mode, we need to update our window configuration. |
| 439 | DisplayParams params = fWindow->getDisplayParams(); |
| 440 | if (SkToBool(fColorSpace) != SkToBool(params.fColorSpace)) { |
| 441 | params.fColorSpace = fColorSpace ? SkColorSpace::MakeSRGB() : nullptr; |
| 442 | fWindow->setDisplayParams(params); |
| 443 | } |
| 444 | |
| 445 | this->updateTitle(); |
| 446 | fWindow->inval(); |
| 447 | } |
| 448 | |
| 449 | void Viewer::drawSlide(SkCanvas* canvas) { |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 450 | int count = canvas->save(); |
| djsollen | 12d62a7 | 2016-04-21 07:59:44 -0700 | [diff] [blame] | 451 | if (fWindow->supportsContentRect()) { |
| 452 | SkRect contentRect = fWindow->getContentRect(); |
| 453 | canvas->clipRect(contentRect); |
| 454 | canvas->translate(contentRect.fLeft, contentRect.fTop); |
| 455 | } |
| 456 | |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 457 | // By default, we render directly into the window's surface/canvas |
| 458 | SkCanvas* slideCanvas = canvas; |
| jvanverth | 3d6ed3a | 2016-04-07 11:09:51 -0700 | [diff] [blame] | 459 | |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 460 | // ... but if we're in F16, or the gamut isn't sRGB, we need to render offscreen |
| 461 | sk_sp<SkSurface> offscreenSurface = nullptr; |
| Brian Osman | 462334e | 2017-02-09 11:22:57 -0500 | [diff] [blame^] | 462 | if (kRGBA_F16_SkColorType == fColorType || |
| 463 | (fColorSpace && fColorSpace != SkColorSpace::MakeSRGB())) { |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 464 | SkImageInfo info = SkImageInfo::Make(fWindow->width(), fWindow->height(), fColorType, |
| 465 | kPremul_SkAlphaType, fColorSpace); |
| 466 | offscreenSurface = canvas->makeSurface(info); |
| 467 | slideCanvas = offscreenSurface->getCanvas(); |
| 468 | } |
| 469 | |
| 470 | slideCanvas->clear(SK_ColorWHITE); |
| 471 | slideCanvas->concat(fDefaultMatrix); |
| 472 | slideCanvas->concat(computeMatrix()); |
| 473 | |
| 474 | fSlides[fCurrentSlide]->draw(slideCanvas); |
| 475 | |
| 476 | // If we rendered offscreen, snap an image and push the results to the window's canvas |
| 477 | if (offscreenSurface) { |
| 478 | auto slideImage = offscreenSurface->makeImageSnapshot(); |
| 479 | |
| 480 | // Tag the image with the sRGB gamut, so no further color space conversion happens |
| 481 | sk_sp<SkColorSpace> cs = (kRGBA_F16_SkColorType == fColorType) |
| 482 | ? SkColorSpace::MakeSRGBLinear() : SkColorSpace::MakeSRGB(); |
| 483 | auto retaggedImage = SkImageMakeRasterCopyAndAssignColorSpace(slideImage.get(), cs.get()); |
| 484 | canvas->drawImage(retaggedImage, 0, 0); |
| liyuqian | 74959a1 | 2016-06-16 14:10:34 -0700 | [diff] [blame] | 485 | } |
| 486 | |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 487 | canvas->restoreToCount(count); |
| liyuqian | 6f163d2 | 2016-06-13 12:26:45 -0700 | [diff] [blame] | 488 | } |
| 489 | |
| 490 | void Viewer::onPaint(SkCanvas* canvas) { |
| liyuqian | 2edb0f4 | 2016-07-06 14:11:32 -0700 | [diff] [blame] | 491 | // Record measurements |
| 492 | double startTime = SkTime::GetMSecs(); |
| 493 | |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 494 | drawSlide(canvas); |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 495 | |
| 496 | if (fDisplayStats) { |
| 497 | drawStats(canvas); |
| 498 | } |
| brianosman | 622c8d5 | 2016-05-10 06:50:49 -0700 | [diff] [blame] | 499 | fCommands.drawHelp(canvas); |
| liyuqian | 2edb0f4 | 2016-07-06 14:11:32 -0700 | [diff] [blame] | 500 | |
| 501 | fMeasurements[fCurrentMeasurement++] = SkTime::GetMSecs() - startTime; |
| 502 | fCurrentMeasurement &= (kMeasurementCount - 1); // fast mod |
| 503 | SkASSERT(fCurrentMeasurement < kMeasurementCount); |
| 504 | updateUIState(); // Update the FPS |
| jvanverth | 3d6ed3a | 2016-04-07 11:09:51 -0700 | [diff] [blame] | 505 | } |
| 506 | |
| jvanverth | 814e38d | 2016-06-06 08:48:47 -0700 | [diff] [blame] | 507 | bool Viewer::onTouch(intptr_t owner, Window::InputState state, float x, float y) { |
| liyuqian | d3cdbca | 2016-05-17 12:44:20 -0700 | [diff] [blame] | 508 | void* castedOwner = reinterpret_cast<void*>(owner); |
| liyuqian | e46e4f0 | 2016-05-20 07:32:19 -0700 | [diff] [blame] | 509 | SkPoint touchPoint = fDefaultMatrixInv.mapXY(x, y); |
| liyuqian | d3cdbca | 2016-05-17 12:44:20 -0700 | [diff] [blame] | 510 | switch (state) { |
| 511 | case Window::kUp_InputState: { |
| 512 | fGesture.touchEnd(castedOwner); |
| 513 | break; |
| 514 | } |
| 515 | case Window::kDown_InputState: { |
| liyuqian | e46e4f0 | 2016-05-20 07:32:19 -0700 | [diff] [blame] | 516 | fGesture.touchBegin(castedOwner, touchPoint.fX, touchPoint.fY); |
| liyuqian | d3cdbca | 2016-05-17 12:44:20 -0700 | [diff] [blame] | 517 | break; |
| 518 | } |
| 519 | case Window::kMove_InputState: { |
| liyuqian | e46e4f0 | 2016-05-20 07:32:19 -0700 | [diff] [blame] | 520 | fGesture.touchMoved(castedOwner, touchPoint.fX, touchPoint.fY); |
| liyuqian | d3cdbca | 2016-05-17 12:44:20 -0700 | [diff] [blame] | 521 | break; |
| 522 | } |
| 523 | } |
| 524 | fWindow->inval(); |
| 525 | return true; |
| 526 | } |
| 527 | |
| jvanverth | 3452426 | 2016-05-04 13:49:13 -0700 | [diff] [blame] | 528 | void Viewer::drawStats(SkCanvas* canvas) { |
| jvanverth | 3d6ed3a | 2016-04-07 11:09:51 -0700 | [diff] [blame] | 529 | static const float kPixelPerMS = 2.0f; |
| 530 | static const int kDisplayWidth = 130; |
| 531 | static const int kDisplayHeight = 100; |
| 532 | static const int kDisplayPadding = 10; |
| 533 | static const int kGraphPadding = 3; |
| 534 | static const SkScalar kBaseMS = 1000.f / 60.f; // ms/frame to hit 60 fps |
| 535 | |
| 536 | SkISize canvasSize = canvas->getDeviceSize(); |
| 537 | SkRect rect = SkRect::MakeXYWH(SkIntToScalar(canvasSize.fWidth-kDisplayWidth-kDisplayPadding), |
| 538 | SkIntToScalar(kDisplayPadding), |
| 539 | SkIntToScalar(kDisplayWidth), SkIntToScalar(kDisplayHeight)); |
| 540 | SkPaint paint; |
| 541 | canvas->save(); |
| 542 | |
| djsollen | 12d62a7 | 2016-04-21 07:59:44 -0700 | [diff] [blame] | 543 | if (fWindow->supportsContentRect()) { |
| 544 | SkRect contentRect = fWindow->getContentRect(); |
| 545 | canvas->clipRect(contentRect); |
| 546 | canvas->translate(contentRect.fLeft, contentRect.fTop); |
| 547 | } |
| 548 | |
| jvanverth | 3d6ed3a | 2016-04-07 11:09:51 -0700 | [diff] [blame] | 549 | canvas->clipRect(rect); |
| 550 | paint.setColor(SK_ColorBLACK); |
| 551 | canvas->drawRect(rect, paint); |
| 552 | // draw the 16ms line |
| 553 | paint.setColor(SK_ColorLTGRAY); |
| 554 | canvas->drawLine(rect.fLeft, rect.fBottom - kBaseMS*kPixelPerMS, |
| 555 | rect.fRight, rect.fBottom - kBaseMS*kPixelPerMS, paint); |
| 556 | paint.setColor(SK_ColorRED); |
| 557 | paint.setStyle(SkPaint::kStroke_Style); |
| 558 | canvas->drawRect(rect, paint); |
| 559 | |
| 560 | int x = SkScalarTruncToInt(rect.fLeft) + kGraphPadding; |
| 561 | const int xStep = 2; |
| 562 | const int startY = SkScalarTruncToInt(rect.fBottom); |
| 563 | int i = fCurrentMeasurement; |
| 564 | do { |
| 565 | int endY = startY - (int)(fMeasurements[i] * kPixelPerMS + 0.5); // round to nearest value |
| 566 | canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY), |
| 567 | SkIntToScalar(x), SkIntToScalar(endY), paint); |
| 568 | i++; |
| 569 | i &= (kMeasurementCount - 1); // fast mod |
| 570 | x += xStep; |
| 571 | } while (i != fCurrentMeasurement); |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 572 | |
| 573 | canvas->restore(); |
| 574 | } |
| 575 | |
| liyuqian | 2edb0f4 | 2016-07-06 14:11:32 -0700 | [diff] [blame] | 576 | void Viewer::onIdle() { |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 577 | fAnimTimer.updateTime(); |
| liyuqian | 2edb0f4 | 2016-07-06 14:11:32 -0700 | [diff] [blame] | 578 | if (fSlides[fCurrentSlide]->animate(fAnimTimer) || fDisplayStats || fRefresh) { |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 579 | fWindow->inval(); |
| 580 | } |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 581 | } |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 582 | |
| 583 | void Viewer::updateUIState() { |
| liyuqian | b73c24b | 2016-06-03 08:47:23 -0700 | [diff] [blame] | 584 | // Slide state |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 585 | Json::Value slideState(Json::objectValue); |
| 586 | slideState[kName] = kSlideStateName; |
| 587 | slideState[kValue] = fSlides[fCurrentSlide]->getName().c_str(); |
| liyuqian | 1f508fd | 2016-06-07 06:57:40 -0700 | [diff] [blame] | 588 | if (fAllSlideNames.size() == 0) { |
| 589 | for(auto slide : fSlides) { |
| 590 | fAllSlideNames.append(Json::Value(slide->getName().c_str())); |
| 591 | } |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 592 | } |
| liyuqian | 1f508fd | 2016-06-07 06:57:40 -0700 | [diff] [blame] | 593 | slideState[kOptions] = fAllSlideNames; |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 594 | |
| liyuqian | b73c24b | 2016-06-03 08:47:23 -0700 | [diff] [blame] | 595 | // Backend state |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 596 | Json::Value backendState(Json::objectValue); |
| 597 | backendState[kName] = kBackendStateName; |
| liyuqian | 6cb7025 | 2016-06-02 12:16:25 -0700 | [diff] [blame] | 598 | backendState[kValue] = kBackendTypeStrings[fBackendType]; |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 599 | backendState[kOptions] = Json::Value(Json::arrayValue); |
| liyuqian | b73c24b | 2016-06-03 08:47:23 -0700 | [diff] [blame] | 600 | for (auto str : kBackendTypeStrings) { |
| liyuqian | 6cb7025 | 2016-06-02 12:16:25 -0700 | [diff] [blame] | 601 | backendState[kOptions].append(Json::Value(str)); |
| 602 | } |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 603 | |
| liyuqian | b73c24b | 2016-06-03 08:47:23 -0700 | [diff] [blame] | 604 | // Softkey state |
| 605 | Json::Value softkeyState(Json::objectValue); |
| 606 | softkeyState[kName] = kSoftkeyStateName; |
| 607 | softkeyState[kValue] = kSoftkeyHint; |
| 608 | softkeyState[kOptions] = Json::Value(Json::arrayValue); |
| 609 | softkeyState[kOptions].append(kSoftkeyHint); |
| 610 | for (const auto& softkey : fCommands.getCommandsAsSoftkeys()) { |
| 611 | softkeyState[kOptions].append(Json::Value(softkey.c_str())); |
| 612 | } |
| 613 | |
| liyuqian | 1f508fd | 2016-06-07 06:57:40 -0700 | [diff] [blame] | 614 | // FPS state |
| 615 | Json::Value fpsState(Json::objectValue); |
| 616 | fpsState[kName] = kFpsStateName; |
| 617 | double measurement = fMeasurements[ |
| 618 | (fCurrentMeasurement + (kMeasurementCount-1)) % kMeasurementCount |
| 619 | ]; |
| 620 | fpsState[kValue] = SkStringPrintf("%8.3lf ms", measurement).c_str(); |
| 621 | fpsState[kOptions] = Json::Value(Json::arrayValue); |
| 622 | |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 623 | Json::Value state(Json::arrayValue); |
| 624 | state.append(slideState); |
| 625 | state.append(backendState); |
| liyuqian | b73c24b | 2016-06-03 08:47:23 -0700 | [diff] [blame] | 626 | state.append(softkeyState); |
| liyuqian | 1f508fd | 2016-06-07 06:57:40 -0700 | [diff] [blame] | 627 | state.append(fpsState); |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 628 | |
| 629 | fWindow->setUIState(state); |
| 630 | } |
| 631 | |
| 632 | void Viewer::onUIStateChanged(const SkString& stateName, const SkString& stateValue) { |
| liyuqian | 6cb7025 | 2016-06-02 12:16:25 -0700 | [diff] [blame] | 633 | // For those who will add more features to handle the state change in this function: |
| 634 | // After the change, please call updateUIState no notify the frontend (e.g., Android app). |
| 635 | // For example, after slide change, updateUIState is called inside setupCurrentSlide; |
| 636 | // after backend change, updateUIState is called in this function. |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 637 | if (stateName.equals(kSlideStateName)) { |
| 638 | int previousSlide = fCurrentSlide; |
| 639 | fCurrentSlide = 0; |
| 640 | for(auto slide : fSlides) { |
| 641 | if (slide->getName().equals(stateValue)) { |
| 642 | setupCurrentSlide(previousSlide); |
| 643 | break; |
| 644 | } |
| 645 | fCurrentSlide++; |
| 646 | } |
| 647 | if (fCurrentSlide >= fSlides.count()) { |
| 648 | fCurrentSlide = previousSlide; |
| 649 | SkDebugf("Slide not found: %s", stateValue.c_str()); |
| 650 | } |
| liyuqian | 6cb7025 | 2016-06-02 12:16:25 -0700 | [diff] [blame] | 651 | } else if (stateName.equals(kBackendStateName)) { |
| 652 | for (int i = 0; i < sk_app::Window::kBackendTypeCount; i++) { |
| 653 | if (stateValue.equals(kBackendTypeStrings[i])) { |
| 654 | if (fBackendType != i) { |
| 655 | fBackendType = (sk_app::Window::BackendType)i; |
| 656 | fWindow->detach(); |
| 657 | fWindow->attach(fBackendType, DisplayParams()); |
| 658 | fWindow->inval(); |
| 659 | updateTitle(); |
| 660 | updateUIState(); |
| 661 | } |
| 662 | break; |
| 663 | } |
| 664 | } |
| liyuqian | b73c24b | 2016-06-03 08:47:23 -0700 | [diff] [blame] | 665 | } else if (stateName.equals(kSoftkeyStateName)) { |
| 666 | if (!stateValue.equals(kSoftkeyHint)) { |
| 667 | fCommands.onSoftkey(stateValue); |
| 668 | updateUIState(); // This is still needed to reset the value to kSoftkeyHint |
| 669 | } |
| liyuqian | 2edb0f4 | 2016-07-06 14:11:32 -0700 | [diff] [blame] | 670 | } else if (stateName.equals(kRefreshStateName)) { |
| 671 | // This state is actually NOT in the UI state. |
| 672 | // We use this to allow Android to quickly set bool fRefresh. |
| 673 | fRefresh = stateValue.equals(kON); |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 674 | } else { |
| 675 | SkDebugf("Unknown stateName: %s", stateName.c_str()); |
| 676 | } |
| 677 | } |