| 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" |
| Brian Osman | 79086b9 | 2017-02-10 13:36:16 -0500 | [diff] [blame] | 28 | #include "SkSwizzle.h" |
| csmartdalton | 29d8715 | 2017-02-10 17:05:14 -0500 | [diff] [blame] | 29 | #include "SkTaskGroup.h" |
| liyuqian | 2edb0f4 | 2016-07-06 14:11:32 -0700 | [diff] [blame] | 30 | #include "SkTime.h" |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 31 | |
| Brian Osman | 79086b9 | 2017-02-10 13:36:16 -0500 | [diff] [blame] | 32 | #include "imgui.h" |
| 33 | |
| jvanverth | 3452426 | 2016-05-04 13:49:13 -0700 | [diff] [blame] | 34 | using namespace sk_app; |
| 35 | |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 36 | Application* Application::Create(int argc, char** argv, void* platformData) { |
| jvanverth | 3452426 | 2016-05-04 13:49:13 -0700 | [diff] [blame] | 37 | return new Viewer(argc, argv, platformData); |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 38 | } |
| 39 | |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 40 | static void on_paint_handler(SkCanvas* canvas, void* userData) { |
| jvanverth | 3452426 | 2016-05-04 13:49:13 -0700 | [diff] [blame] | 41 | Viewer* vv = reinterpret_cast<Viewer*>(userData); |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 42 | |
| 43 | return vv->onPaint(canvas); |
| 44 | } |
| 45 | |
| jvanverth | 814e38d | 2016-06-06 08:48:47 -0700 | [diff] [blame] | 46 | 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] | 47 | { |
| 48 | Viewer* viewer = reinterpret_cast<Viewer*>(userData); |
| 49 | |
| 50 | return viewer->onTouch(owner, state, x, y); |
| 51 | } |
| 52 | |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 53 | static void on_ui_state_changed_handler(const SkString& stateName, const SkString& stateValue, void* userData) { |
| 54 | Viewer* viewer = reinterpret_cast<Viewer*>(userData); |
| 55 | |
| 56 | return viewer->onUIStateChanged(stateName, stateValue); |
| 57 | } |
| 58 | |
| Brian Osman | 79086b9 | 2017-02-10 13:36:16 -0500 | [diff] [blame] | 59 | static bool on_mouse_handler(int x, int y, Window::InputState state, uint32_t modifiers, |
| 60 | void* userData) { |
| 61 | ImGuiIO& io = ImGui::GetIO(); |
| 62 | io.MousePos.x = static_cast<float>(x); |
| 63 | io.MousePos.y = static_cast<float>(y); |
| 64 | if (Window::kDown_InputState == state) { |
| 65 | io.MouseDown[0] = true; |
| 66 | } else if (Window::kUp_InputState == state) { |
| 67 | io.MouseDown[0] = false; |
| 68 | } |
| 69 | return true; |
| 70 | } |
| 71 | |
| 72 | static bool on_mouse_wheel_handler(float delta, uint32_t modifiers, void* userData) { |
| 73 | ImGuiIO& io = ImGui::GetIO(); |
| 74 | io.MouseWheel += delta; |
| 75 | return true; |
| 76 | } |
| 77 | |
| 78 | static bool on_key_handler(Window::Key key, Window::InputState state, uint32_t modifiers, |
| 79 | void* userData) { |
| 80 | ImGuiIO& io = ImGui::GetIO(); |
| 81 | io.KeysDown[static_cast<int>(key)] = (Window::kDown_InputState == state); |
| 82 | |
| 83 | if (io.WantCaptureKeyboard) { |
| 84 | return true; |
| 85 | } else { |
| 86 | Viewer* viewer = reinterpret_cast<Viewer*>(userData); |
| 87 | return viewer->onKey(key, state, modifiers); |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | static bool on_char_handler(SkUnichar c, uint32_t modifiers, void* userData) { |
| 92 | ImGuiIO& io = ImGui::GetIO(); |
| 93 | if (io.WantTextInput) { |
| 94 | if (c > 0 && c < 0x10000) { |
| 95 | io.AddInputCharacter(c); |
| 96 | } |
| 97 | return true; |
| 98 | } else { |
| 99 | Viewer* viewer = reinterpret_cast<Viewer*>(userData); |
| 100 | return viewer->onChar(c, modifiers); |
| 101 | } |
| 102 | } |
| 103 | |
| Brian Osman | 2dd9693 | 2016-10-18 15:33:53 -0400 | [diff] [blame] | 104 | static DEFINE_bool2(fullscreen, f, true, "Run fullscreen."); |
| Brian Osman | 16adfa3 | 2016-10-18 14:42:44 -0400 | [diff] [blame] | 105 | |
| Brian Osman | 2dd9693 | 2016-10-18 15:33:53 -0400 | [diff] [blame] | 106 | static DEFINE_string2(match, m, nullptr, |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 107 | "[~][^]substring[$] [...] of bench name to run.\n" |
| 108 | "Multiple matches may be separated by spaces.\n" |
| 109 | "~ causes a matching bench to always be skipped\n" |
| 110 | "^ requires the start of the bench to match\n" |
| 111 | "$ requires the end of the bench to match\n" |
| 112 | "^ and $ requires an exact match\n" |
| 113 | "If a bench does not match any list entry,\n" |
| 114 | "it is skipped unless some list entry starts with ~"); |
| bsalomon | 6c471f7 | 2016-07-26 12:56:32 -0700 | [diff] [blame] | 115 | |
| 116 | #ifdef SK_VULKAN |
| jvanverth | b8794cc | 2016-07-27 14:29:18 -0700 | [diff] [blame] | 117 | # define BACKENDS_STR "\"sw\", \"gl\", and \"vk\"" |
| bsalomon | 6c471f7 | 2016-07-26 12:56:32 -0700 | [diff] [blame] | 118 | #else |
| 119 | # define BACKENDS_STR "\"sw\" and \"gl\"" |
| 120 | #endif |
| 121 | |
| liyuqian | 71491dc | 2016-06-09 12:02:34 -0700 | [diff] [blame] | 122 | #ifdef SK_BUILD_FOR_ANDROID |
| Brian Osman | 2dd9693 | 2016-10-18 15:33:53 -0400 | [diff] [blame] | 123 | static DEFINE_string(skps, "/data/local/tmp/skia", "Directory to read skps from."); |
| 124 | static DEFINE_string(jpgs, "/data/local/tmp/skia", "Directory to read jpgs from."); |
| liyuqian | 71491dc | 2016-06-09 12:02:34 -0700 | [diff] [blame] | 125 | #else |
| Brian Osman | 2dd9693 | 2016-10-18 15:33:53 -0400 | [diff] [blame] | 126 | static DEFINE_string(skps, "skps", "Directory to read skps from."); |
| 127 | static DEFINE_string(jpgs, "jpgs", "Directory to read jpgs from."); |
| liyuqian | 71491dc | 2016-06-09 12:02:34 -0700 | [diff] [blame] | 128 | #endif |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 129 | |
| Brian Osman | 2dd9693 | 2016-10-18 15:33:53 -0400 | [diff] [blame] | 130 | 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] | 131 | |
| Brian Osman | 2dd9693 | 2016-10-18 15:33:53 -0400 | [diff] [blame] | 132 | 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] | 133 | |
| jvanverth | af236b5 | 2016-05-20 06:01:06 -0700 | [diff] [blame] | 134 | const char *kBackendTypeStrings[sk_app::Window::kBackendTypeCount] = { |
| 135 | " [OpenGL]", |
| jvanverth | 063ece7 | 2016-06-17 09:29:14 -0700 | [diff] [blame] | 136 | #ifdef SK_VULKAN |
| liyuqian | d94ad58 | 2016-06-07 14:22:37 -0700 | [diff] [blame] | 137 | " [Vulkan]", |
| jvanverth | 063ece7 | 2016-06-17 09:29:14 -0700 | [diff] [blame] | 138 | #endif |
| liyuqian | d94ad58 | 2016-06-07 14:22:37 -0700 | [diff] [blame] | 139 | " [Raster]" |
| jvanverth | af236b5 | 2016-05-20 06:01:06 -0700 | [diff] [blame] | 140 | }; |
| 141 | |
| bsalomon | 6c471f7 | 2016-07-26 12:56:32 -0700 | [diff] [blame] | 142 | static sk_app::Window::BackendType get_backend_type(const char* str) { |
| 143 | #ifdef SK_VULKAN |
| 144 | if (0 == strcmp(str, "vk")) { |
| 145 | return sk_app::Window::kVulkan_BackendType; |
| 146 | } else |
| 147 | #endif |
| 148 | if (0 == strcmp(str, "gl")) { |
| 149 | return sk_app::Window::kNativeGL_BackendType; |
| 150 | } else if (0 == strcmp(str, "sw")) { |
| 151 | return sk_app::Window::kRaster_BackendType; |
| 152 | } else { |
| 153 | SkDebugf("Unknown backend type, %s, defaulting to sw.", str); |
| 154 | return sk_app::Window::kRaster_BackendType; |
| 155 | } |
| 156 | } |
| 157 | |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 158 | const char* kName = "name"; |
| 159 | const char* kValue = "value"; |
| 160 | const char* kOptions = "options"; |
| 161 | const char* kSlideStateName = "Slide"; |
| 162 | const char* kBackendStateName = "Backend"; |
| liyuqian | b73c24b | 2016-06-03 08:47:23 -0700 | [diff] [blame] | 163 | const char* kSoftkeyStateName = "Softkey"; |
| 164 | const char* kSoftkeyHint = "Please select a softkey"; |
| liyuqian | 1f508fd | 2016-06-07 06:57:40 -0700 | [diff] [blame] | 165 | const char* kFpsStateName = "FPS"; |
| liyuqian | 6f163d2 | 2016-06-13 12:26:45 -0700 | [diff] [blame] | 166 | const char* kON = "ON"; |
| 167 | const char* kOFF = "OFF"; |
| liyuqian | 2edb0f4 | 2016-07-06 14:11:32 -0700 | [diff] [blame] | 168 | const char* kRefreshStateName = "Refresh"; |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 169 | |
| jvanverth | 3452426 | 2016-05-04 13:49:13 -0700 | [diff] [blame] | 170 | Viewer::Viewer(int argc, char** argv, void* platformData) |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 171 | : fCurrentMeasurement(0) |
| 172 | , fDisplayStats(false) |
| liyuqian | 2edb0f4 | 2016-07-06 14:11:32 -0700 | [diff] [blame] | 173 | , fRefresh(false) |
| Brian Osman | 79086b9 | 2017-02-10 13:36:16 -0500 | [diff] [blame] | 174 | , fShowImGuiDebugWindow(false) |
| 175 | , fShowImGuiTestWindow(false) |
| Brian Osman | f687709 | 2017-02-13 09:39:57 -0500 | [diff] [blame] | 176 | , fShowZoomWindow(false) |
| 177 | , fLastImage(nullptr) |
| jvanverth | 063ece7 | 2016-06-17 09:29:14 -0700 | [diff] [blame] | 178 | , fBackendType(sk_app::Window::kNativeGL_BackendType) |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 179 | , fColorType(kN32_SkColorType) |
| 180 | , fColorSpace(nullptr) |
| egdaniel | 2a0bb0a | 2016-04-11 08:30:40 -0700 | [diff] [blame] | 181 | , fZoomCenterX(0.0f) |
| 182 | , fZoomCenterY(0.0f) |
| 183 | , fZoomLevel(0.0f) |
| 184 | , fZoomScale(SK_Scalar1) |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 185 | { |
| csmartdalton | 29d8715 | 2017-02-10 17:05:14 -0500 | [diff] [blame] | 186 | static SkTaskGroup::Enabler kTaskGroupEnabler; |
| Greg Daniel | 285db44 | 2016-10-14 09:12:53 -0400 | [diff] [blame] | 187 | SkGraphics::Init(); |
| Brian Osman | 1df161a | 2017-02-09 12:10:20 -0500 | [diff] [blame] | 188 | memset(fPaintTimes, 0, sizeof(fPaintTimes)); |
| 189 | memset(fFlushTimes, 0, sizeof(fFlushTimes)); |
| 190 | memset(fAnimateTimes, 0, sizeof(fAnimateTimes)); |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 191 | |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 192 | SkDebugf("Command line arguments: "); |
| 193 | for (int i = 1; i < argc; ++i) { |
| 194 | SkDebugf("%s ", argv[i]); |
| 195 | } |
| 196 | SkDebugf("\n"); |
| 197 | |
| 198 | SkCommandLineFlags::Parse(argc, argv); |
| Greg Daniel | 9fcc743 | 2016-11-29 16:35:19 -0500 | [diff] [blame] | 199 | #ifdef SK_BUILD_FOR_ANDROID |
| 200 | SetResourcePath("/data/local/tmp/skia"); |
| 201 | #endif |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 202 | |
| Greg Daniel | 285db44 | 2016-10-14 09:12:53 -0400 | [diff] [blame] | 203 | if (FLAGS_atrace) { |
| 204 | SkEventTracer::SetInstance(new SkATrace()); |
| 205 | } |
| 206 | |
| bsalomon | 6c471f7 | 2016-07-26 12:56:32 -0700 | [diff] [blame] | 207 | fBackendType = get_backend_type(FLAGS_backend[0]); |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 208 | fWindow = Window::CreateNativeWindow(platformData); |
| jvanverth | af236b5 | 2016-05-20 06:01:06 -0700 | [diff] [blame] | 209 | fWindow->attach(fBackendType, DisplayParams()); |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 210 | |
| 211 | // register callbacks |
| brianosman | 622c8d5 | 2016-05-10 06:50:49 -0700 | [diff] [blame] | 212 | fCommands.attach(fWindow); |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 213 | fWindow->registerPaintFunc(on_paint_handler, this); |
| liyuqian | d3cdbca | 2016-05-17 12:44:20 -0700 | [diff] [blame] | 214 | fWindow->registerTouchFunc(on_touch_handler, this); |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 215 | fWindow->registerUIStateChangedFunc(on_ui_state_changed_handler, this); |
| Brian Osman | 79086b9 | 2017-02-10 13:36:16 -0500 | [diff] [blame] | 216 | fWindow->registerMouseFunc(on_mouse_handler, this); |
| 217 | fWindow->registerMouseWheelFunc(on_mouse_wheel_handler, this); |
| 218 | fWindow->registerKeyFunc(on_key_handler, this); |
| 219 | fWindow->registerCharFunc(on_char_handler, this); |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 220 | |
| brianosman | 622c8d5 | 2016-05-10 06:50:49 -0700 | [diff] [blame] | 221 | // add key-bindings |
| Brian Osman | 79086b9 | 2017-02-10 13:36:16 -0500 | [diff] [blame] | 222 | fCommands.addCommand(' ', "GUI", "Toggle Debug GUI", [this]() { |
| 223 | this->fShowImGuiDebugWindow = !this->fShowImGuiDebugWindow; |
| 224 | fWindow->inval(); |
| 225 | }); |
| 226 | fCommands.addCommand('g', "GUI", "Toggle GUI Demo", [this]() { |
| 227 | this->fShowImGuiTestWindow = !this->fShowImGuiTestWindow; |
| 228 | fWindow->inval(); |
| 229 | }); |
| Brian Osman | f687709 | 2017-02-13 09:39:57 -0500 | [diff] [blame] | 230 | fCommands.addCommand('z', "GUI", "Toggle zoom window", [this]() { |
| 231 | this->fShowZoomWindow = !this->fShowZoomWindow; |
| 232 | fWindow->inval(); |
| 233 | }); |
| brianosman | 622c8d5 | 2016-05-10 06:50:49 -0700 | [diff] [blame] | 234 | fCommands.addCommand('s', "Overlays", "Toggle stats display", [this]() { |
| 235 | this->fDisplayStats = !this->fDisplayStats; |
| 236 | fWindow->inval(); |
| 237 | }); |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 238 | fCommands.addCommand('c', "Modes", "Cycle color mode", [this]() { |
| 239 | if (!fColorSpace) { |
| 240 | // Legacy -> sRGB |
| 241 | this->setColorMode(kN32_SkColorType, SkColorSpace::MakeSRGB()); |
| 242 | } else if (kN32_SkColorType == fColorType) { |
| 243 | // sRGB -> F16 sRGB |
| 244 | this->setColorMode(kRGBA_F16_SkColorType, SkColorSpace::MakeSRGBLinear()); |
| 245 | } else { |
| 246 | // F16 sRGB -> Legacy |
| 247 | this->setColorMode(kN32_SkColorType, nullptr); |
| 248 | } |
| brianosman | 622c8d5 | 2016-05-10 06:50:49 -0700 | [diff] [blame] | 249 | }); |
| 250 | fCommands.addCommand(Window::Key::kRight, "Right", "Navigation", "Next slide", [this]() { |
| 251 | int previousSlide = fCurrentSlide; |
| 252 | fCurrentSlide++; |
| 253 | if (fCurrentSlide >= fSlides.count()) { |
| 254 | fCurrentSlide = 0; |
| 255 | } |
| 256 | this->setupCurrentSlide(previousSlide); |
| 257 | }); |
| 258 | fCommands.addCommand(Window::Key::kLeft, "Left", "Navigation", "Previous slide", [this]() { |
| 259 | int previousSlide = fCurrentSlide; |
| 260 | fCurrentSlide--; |
| 261 | if (fCurrentSlide < 0) { |
| 262 | fCurrentSlide = fSlides.count() - 1; |
| 263 | } |
| 264 | this->setupCurrentSlide(previousSlide); |
| 265 | }); |
| 266 | fCommands.addCommand(Window::Key::kUp, "Up", "Transform", "Zoom in", [this]() { |
| 267 | this->changeZoomLevel(1.f / 32.f); |
| 268 | fWindow->inval(); |
| 269 | }); |
| 270 | fCommands.addCommand(Window::Key::kDown, "Down", "Transform", "Zoom out", [this]() { |
| 271 | this->changeZoomLevel(-1.f / 32.f); |
| 272 | fWindow->inval(); |
| 273 | }); |
| jvanverth | af236b5 | 2016-05-20 06:01:06 -0700 | [diff] [blame] | 274 | fCommands.addCommand('d', "Modes", "Change rendering backend", [this]() { |
| Jim Van Verth | d63c102 | 2017-01-05 13:50:49 -0500 | [diff] [blame] | 275 | #if defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC) |
| jvanverth | b8794cc | 2016-07-27 14:29:18 -0700 | [diff] [blame] | 276 | if (sk_app::Window::kRaster_BackendType == fBackendType) { |
| 277 | fBackendType = sk_app::Window::kNativeGL_BackendType; |
| 278 | #ifdef SK_VULKAN |
| 279 | } else if (sk_app::Window::kNativeGL_BackendType == fBackendType) { |
| 280 | fBackendType = sk_app::Window::kVulkan_BackendType; |
| 281 | #endif |
| 282 | } else { |
| 283 | fBackendType = sk_app::Window::kRaster_BackendType; |
| 284 | } |
| Jim Van Verth | d63c102 | 2017-01-05 13:50:49 -0500 | [diff] [blame] | 285 | #elif defined(SK_BUILD_FOR_UNIX) |
| 286 | // Switching to and from Vulkan is problematic on Linux so disabled for now |
| 287 | if (sk_app::Window::kRaster_BackendType == fBackendType) { |
| 288 | fBackendType = sk_app::Window::kNativeGL_BackendType; |
| 289 | } else if (sk_app::Window::kNativeGL_BackendType == fBackendType) { |
| 290 | fBackendType = sk_app::Window::kRaster_BackendType; |
| 291 | } |
| 292 | #endif |
| jvanverth | af236b5 | 2016-05-20 06:01:06 -0700 | [diff] [blame] | 293 | fWindow->detach(); |
| 294 | |
| Jim Van Verth | d63c102 | 2017-01-05 13:50:49 -0500 | [diff] [blame] | 295 | #if defined(SK_BUILD_FOR_WIN) && defined(SK_VULKAN) |
| 296 | // Switching from OpenGL to Vulkan in the same window is problematic at this point on |
| 297 | // Windows, so we just delete the window and recreate it. |
| jvanverth | af236b5 | 2016-05-20 06:01:06 -0700 | [diff] [blame] | 298 | if (sk_app::Window::kVulkan_BackendType == fBackendType) { |
| jvanverth | b8794cc | 2016-07-27 14:29:18 -0700 | [diff] [blame] | 299 | delete fWindow; |
| 300 | fWindow = Window::CreateNativeWindow(nullptr); |
| jvanverth | af236b5 | 2016-05-20 06:01:06 -0700 | [diff] [blame] | 301 | |
| jvanverth | b8794cc | 2016-07-27 14:29:18 -0700 | [diff] [blame] | 302 | // re-register callbacks |
| 303 | fCommands.attach(fWindow); |
| 304 | fWindow->registerPaintFunc(on_paint_handler, this); |
| 305 | fWindow->registerTouchFunc(on_touch_handler, this); |
| 306 | fWindow->registerUIStateChangedFunc(on_ui_state_changed_handler, this); |
| Brian Osman | 79086b9 | 2017-02-10 13:36:16 -0500 | [diff] [blame] | 307 | fWindow->registerMouseFunc(on_mouse_handler, this); |
| 308 | fWindow->registerMouseWheelFunc(on_mouse_wheel_handler, this); |
| 309 | fWindow->registerKeyFunc(on_key_handler, this); |
| 310 | fWindow->registerCharFunc(on_char_handler, this); |
| jvanverth | b8794cc | 2016-07-27 14:29:18 -0700 | [diff] [blame] | 311 | } |
| 312 | #endif |
| jvanverth | af236b5 | 2016-05-20 06:01:06 -0700 | [diff] [blame] | 313 | fWindow->attach(fBackendType, DisplayParams()); |
| jvanverth | b8794cc | 2016-07-27 14:29:18 -0700 | [diff] [blame] | 314 | |
| jvanverth | af236b5 | 2016-05-20 06:01:06 -0700 | [diff] [blame] | 315 | this->updateTitle(); |
| jvanverth | 85f758c | 2016-05-27 06:47:08 -0700 | [diff] [blame] | 316 | fWindow->inval(); |
| jvanverth | b8794cc | 2016-07-27 14:29:18 -0700 | [diff] [blame] | 317 | fWindow->show(); |
| jvanverth | af236b5 | 2016-05-20 06:01:06 -0700 | [diff] [blame] | 318 | }); |
| brianosman | 622c8d5 | 2016-05-10 06:50:49 -0700 | [diff] [blame] | 319 | |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 320 | // set up slides |
| 321 | this->initSlides(); |
| 322 | |
| djsollen | 12d62a7 | 2016-04-21 07:59:44 -0700 | [diff] [blame] | 323 | fAnimTimer.run(); |
| 324 | |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 325 | // set up first frame |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 326 | fCurrentSlide = 0; |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 327 | setupCurrentSlide(-1); |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 328 | |
| Brian Osman | 79086b9 | 2017-02-10 13:36:16 -0500 | [diff] [blame] | 329 | // ImGui initialization: |
| 330 | ImGuiIO& io = ImGui::GetIO(); |
| 331 | io.DisplaySize.x = static_cast<float>(fWindow->width()); |
| 332 | io.DisplaySize.y = static_cast<float>(fWindow->height()); |
| 333 | |
| 334 | // Keymap... |
| 335 | io.KeyMap[ImGuiKey_Tab] = (int)Window::Key::kTab; |
| 336 | io.KeyMap[ImGuiKey_LeftArrow] = (int)Window::Key::kLeft; |
| 337 | io.KeyMap[ImGuiKey_RightArrow] = (int)Window::Key::kRight; |
| 338 | io.KeyMap[ImGuiKey_UpArrow] = (int)Window::Key::kUp; |
| 339 | io.KeyMap[ImGuiKey_DownArrow] = (int)Window::Key::kDown; |
| 340 | io.KeyMap[ImGuiKey_PageUp] = (int)Window::Key::kPageUp; |
| 341 | io.KeyMap[ImGuiKey_PageDown] = (int)Window::Key::kPageDown; |
| 342 | io.KeyMap[ImGuiKey_Home] = (int)Window::Key::kHome; |
| 343 | io.KeyMap[ImGuiKey_End] = (int)Window::Key::kEnd; |
| 344 | io.KeyMap[ImGuiKey_Delete] = (int)Window::Key::kDelete; |
| 345 | io.KeyMap[ImGuiKey_Backspace] = (int)Window::Key::kBack; |
| 346 | io.KeyMap[ImGuiKey_Enter] = (int)Window::Key::kOK; |
| 347 | io.KeyMap[ImGuiKey_Escape] = (int)Window::Key::kEscape; |
| 348 | io.KeyMap[ImGuiKey_A] = (int)Window::Key::kA; |
| 349 | io.KeyMap[ImGuiKey_C] = (int)Window::Key::kC; |
| 350 | io.KeyMap[ImGuiKey_V] = (int)Window::Key::kV; |
| 351 | io.KeyMap[ImGuiKey_X] = (int)Window::Key::kX; |
| 352 | io.KeyMap[ImGuiKey_Y] = (int)Window::Key::kY; |
| 353 | io.KeyMap[ImGuiKey_Z] = (int)Window::Key::kZ; |
| 354 | |
| 355 | int w, h; |
| 356 | unsigned char* pixels; |
| 357 | io.Fonts->GetTexDataAsAlpha8(&pixels, &w, &h); |
| 358 | SkImageInfo info = SkImageInfo::MakeA8(w, h); |
| 359 | SkPixmap pmap(info, pixels, info.minRowBytes()); |
| Brian Osman | f687709 | 2017-02-13 09:39:57 -0500 | [diff] [blame] | 360 | SkMatrix localMatrix = SkMatrix::MakeScale(1.0f / w, 1.0f / h); |
| 361 | auto fontImage = SkImage::MakeFromRaster(pmap, nullptr, nullptr); |
| 362 | auto fontShader = fontImage->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, |
| 363 | &localMatrix); |
| 364 | fImGuiFontPaint.setShader(fontShader); |
| 365 | fImGuiFontPaint.setColor(SK_ColorWHITE); |
| 366 | fImGuiFontPaint.setFilterQuality(kLow_SkFilterQuality); |
| 367 | io.Fonts->TexID = &fImGuiFontPaint; |
| Brian Osman | 79086b9 | 2017-02-10 13:36:16 -0500 | [diff] [blame] | 368 | |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 369 | fWindow->show(); |
| 370 | } |
| 371 | |
| jvanverth | 3452426 | 2016-05-04 13:49:13 -0700 | [diff] [blame] | 372 | void Viewer::initSlides() { |
| liyuqian | 1f508fd | 2016-06-07 06:57:40 -0700 | [diff] [blame] | 373 | fAllSlideNames = Json::Value(Json::arrayValue); |
| 374 | |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 375 | const skiagm::GMRegistry* gms(skiagm::GMRegistry::Head()); |
| 376 | while (gms) { |
| Ben Wagner | 145dbcd | 2016-11-03 14:40:50 -0400 | [diff] [blame] | 377 | std::unique_ptr<skiagm::GM> gm(gms->factory()(nullptr)); |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 378 | |
| 379 | if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, gm->getName())) { |
| 380 | sk_sp<Slide> slide(new GMSlide(gm.release())); |
| 381 | fSlides.push_back(slide); |
| 382 | } |
| 383 | |
| 384 | gms = gms->next(); |
| 385 | } |
| 386 | |
| 387 | // reverse array |
| 388 | for (int i = 0; i < fSlides.count()/2; ++i) { |
| 389 | sk_sp<Slide> temp = fSlides[i]; |
| 390 | fSlides[i] = fSlides[fSlides.count() - i - 1]; |
| 391 | fSlides[fSlides.count() - i - 1] = temp; |
| 392 | } |
| 393 | |
| jvanverth | c7027ab | 2016-06-16 09:52:35 -0700 | [diff] [blame] | 394 | // samples |
| 395 | const SkViewRegister* reg = SkViewRegister::Head(); |
| 396 | while (reg) { |
| 397 | sk_sp<Slide> slide(new SampleSlide(reg->factory())); |
| brianosman | e1d2007 | 2016-07-12 09:07:33 -0700 | [diff] [blame] | 398 | if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, slide->getName().c_str())) { |
| 399 | fSlides.push_back(slide); |
| 400 | } |
| jvanverth | c7027ab | 2016-06-16 09:52:35 -0700 | [diff] [blame] | 401 | reg = reg->next(); |
| 402 | } |
| 403 | |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 404 | // SKPs |
| 405 | for (int i = 0; i < FLAGS_skps.count(); i++) { |
| 406 | if (SkStrEndsWith(FLAGS_skps[i], ".skp")) { |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 407 | if (SkCommandLineFlags::ShouldSkip(FLAGS_match, FLAGS_skps[i])) { |
| 408 | continue; |
| 409 | } |
| 410 | |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 411 | SkString path(FLAGS_skps[i]); |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 412 | sk_sp<SKPSlide> slide(new SKPSlide(SkOSPath::Basename(path.c_str()), path)); |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 413 | if (slide) { |
| 414 | fSlides.push_back(slide); |
| 415 | } |
| 416 | } else { |
| 417 | SkOSFile::Iter it(FLAGS_skps[i], ".skp"); |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 418 | SkString skpName; |
| 419 | while (it.next(&skpName)) { |
| 420 | if (SkCommandLineFlags::ShouldSkip(FLAGS_match, skpName.c_str())) { |
| 421 | continue; |
| 422 | } |
| 423 | |
| 424 | SkString path = SkOSPath::Join(FLAGS_skps[i], skpName.c_str()); |
| 425 | sk_sp<SKPSlide> slide(new SKPSlide(skpName, path)); |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 426 | if (slide) { |
| 427 | fSlides.push_back(slide); |
| 428 | } |
| 429 | } |
| 430 | } |
| 431 | } |
| liyuqian | 6f163d2 | 2016-06-13 12:26:45 -0700 | [diff] [blame] | 432 | |
| 433 | // JPGs |
| 434 | for (int i = 0; i < FLAGS_jpgs.count(); i++) { |
| 435 | SkOSFile::Iter it(FLAGS_jpgs[i], ".jpg"); |
| 436 | SkString jpgName; |
| 437 | while (it.next(&jpgName)) { |
| brianosman | e1d2007 | 2016-07-12 09:07:33 -0700 | [diff] [blame] | 438 | if (SkCommandLineFlags::ShouldSkip(FLAGS_match, jpgName.c_str())) { |
| 439 | continue; |
| 440 | } |
| 441 | |
| liyuqian | 6f163d2 | 2016-06-13 12:26:45 -0700 | [diff] [blame] | 442 | SkString path = SkOSPath::Join(FLAGS_jpgs[i], jpgName.c_str()); |
| 443 | sk_sp<ImageSlide> slide(new ImageSlide(jpgName, path)); |
| 444 | if (slide) { |
| 445 | fSlides.push_back(slide); |
| 446 | } |
| 447 | } |
| 448 | } |
| jvanverth | 2bb3b6d | 2016-04-08 07:24:09 -0700 | [diff] [blame] | 449 | } |
| 450 | |
| 451 | |
| jvanverth | 3452426 | 2016-05-04 13:49:13 -0700 | [diff] [blame] | 452 | Viewer::~Viewer() { |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 453 | fWindow->detach(); |
| 454 | delete fWindow; |
| 455 | } |
| 456 | |
| brianosman | 05de216 | 2016-05-06 13:28:57 -0700 | [diff] [blame] | 457 | void Viewer::updateTitle() { |
| jvanverth | 3452426 | 2016-05-04 13:49:13 -0700 | [diff] [blame] | 458 | SkString title("Viewer: "); |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 459 | title.append(fSlides[fCurrentSlide]->getName()); |
| brianosman | b109b8c | 2016-06-16 13:03:24 -0700 | [diff] [blame] | 460 | |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 461 | title.appendf(" %s", sk_tool_utils::colortype_name(fColorType)); |
| 462 | |
| 463 | // TODO: Find a short string to describe the gamut of the color space? |
| 464 | if (fColorSpace) { |
| 465 | title.append(" ColorManaged"); |
| brianosman | 05de216 | 2016-05-06 13:28:57 -0700 | [diff] [blame] | 466 | } |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 467 | |
| jvanverth | af236b5 | 2016-05-20 06:01:06 -0700 | [diff] [blame] | 468 | title.append(kBackendTypeStrings[fBackendType]); |
| brianosman | 05de216 | 2016-05-06 13:28:57 -0700 | [diff] [blame] | 469 | fWindow->setTitle(title.c_str()); |
| 470 | } |
| 471 | |
| 472 | void Viewer::setupCurrentSlide(int previousSlide) { |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 473 | if (fCurrentSlide == previousSlide) { |
| 474 | return; // no change; do nothing |
| 475 | } |
| 476 | |
| liyuqian | 6f163d2 | 2016-06-13 12:26:45 -0700 | [diff] [blame] | 477 | // prepare dimensions for image slides |
| jvanverth | c7027ab | 2016-06-16 09:52:35 -0700 | [diff] [blame] | 478 | fSlides[fCurrentSlide]->load(SkIntToScalar(fWindow->width()), SkIntToScalar(fWindow->height())); |
| liyuqian | 6f163d2 | 2016-06-13 12:26:45 -0700 | [diff] [blame] | 479 | |
| liyuqian | e46e4f0 | 2016-05-20 07:32:19 -0700 | [diff] [blame] | 480 | fGesture.reset(); |
| 481 | fDefaultMatrix.reset(); |
| 482 | fDefaultMatrixInv.reset(); |
| 483 | |
| 484 | if (fWindow->supportsContentRect() && fWindow->scaleContentToFit()) { |
| 485 | const SkRect contentRect = fWindow->getContentRect(); |
| 486 | const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions(); |
| 487 | const SkRect slideBounds = SkRect::MakeIWH(slideSize.width(), slideSize.height()); |
| 488 | if (contentRect.width() > 0 && contentRect.height() > 0) { |
| 489 | fDefaultMatrix.setRectToRect(slideBounds, contentRect, SkMatrix::kStart_ScaleToFit); |
| liyuqian | beb1c67 | 2016-05-20 11:41:01 -0700 | [diff] [blame] | 490 | SkAssertResult(fDefaultMatrix.invert(&fDefaultMatrixInv)); |
| liyuqian | e46e4f0 | 2016-05-20 07:32:19 -0700 | [diff] [blame] | 491 | } |
| 492 | } |
| 493 | |
| 494 | if (fWindow->supportsContentRect()) { |
| 495 | const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions(); |
| 496 | SkRect windowRect = fWindow->getContentRect(); |
| 497 | fDefaultMatrixInv.mapRect(&windowRect); |
| jvanverth | 1e305ba | 2016-06-01 09:39:15 -0700 | [diff] [blame] | 498 | fGesture.setTransLimit(SkRect::MakeWH(SkIntToScalar(slideSize.width()), |
| 499 | SkIntToScalar(slideSize.height())), |
| 500 | windowRect); |
| liyuqian | e46e4f0 | 2016-05-20 07:32:19 -0700 | [diff] [blame] | 501 | } |
| 502 | |
| brianosman | 05de216 | 2016-05-06 13:28:57 -0700 | [diff] [blame] | 503 | this->updateTitle(); |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 504 | this->updateUIState(); |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 505 | if (previousSlide >= 0) { |
| 506 | fSlides[previousSlide]->unload(); |
| 507 | } |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 508 | fWindow->inval(); |
| 509 | } |
| 510 | |
| 511 | #define MAX_ZOOM_LEVEL 8 |
| 512 | #define MIN_ZOOM_LEVEL -8 |
| 513 | |
| jvanverth | 3452426 | 2016-05-04 13:49:13 -0700 | [diff] [blame] | 514 | void Viewer::changeZoomLevel(float delta) { |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 515 | fZoomLevel += delta; |
| 516 | if (fZoomLevel > 0) { |
| 517 | fZoomLevel = SkMinScalar(fZoomLevel, MAX_ZOOM_LEVEL); |
| 518 | fZoomScale = fZoomLevel + SK_Scalar1; |
| 519 | } else if (fZoomLevel < 0) { |
| 520 | fZoomLevel = SkMaxScalar(fZoomLevel, MIN_ZOOM_LEVEL); |
| 521 | fZoomScale = SK_Scalar1 / (SK_Scalar1 - fZoomLevel); |
| 522 | } else { |
| 523 | fZoomScale = SK_Scalar1; |
| 524 | } |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 525 | } |
| 526 | |
| liyuqian | d3cdbca | 2016-05-17 12:44:20 -0700 | [diff] [blame] | 527 | SkMatrix Viewer::computeMatrix() { |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 528 | SkMatrix m; |
| 529 | m.reset(); |
| 530 | |
| 531 | if (fZoomLevel) { |
| 532 | SkPoint center; |
| 533 | //m = this->getLocalMatrix();//.invert(&m); |
| 534 | m.mapXY(fZoomCenterX, fZoomCenterY, ¢er); |
| 535 | SkScalar cx = center.fX; |
| 536 | SkScalar cy = center.fY; |
| 537 | |
| 538 | m.setTranslate(-cx, -cy); |
| 539 | m.postScale(fZoomScale, fZoomScale); |
| 540 | m.postTranslate(cx, cy); |
| 541 | } |
| 542 | |
| liyuqian | d3cdbca | 2016-05-17 12:44:20 -0700 | [diff] [blame] | 543 | m.preConcat(fGesture.localM()); |
| 544 | m.preConcat(fGesture.globalM()); |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 545 | |
| liyuqian | d3cdbca | 2016-05-17 12:44:20 -0700 | [diff] [blame] | 546 | return m; |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 547 | } |
| 548 | |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 549 | void Viewer::setColorMode(SkColorType colorType, sk_sp<SkColorSpace> colorSpace) { |
| 550 | fColorType = colorType; |
| 551 | fColorSpace = std::move(colorSpace); |
| liyuqian | 6f163d2 | 2016-06-13 12:26:45 -0700 | [diff] [blame] | 552 | |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 553 | // When we're in color managed mode, we tag our window surface as sRGB. If we've switched into |
| 554 | // or out of legacy mode, we need to update our window configuration. |
| 555 | DisplayParams params = fWindow->getDisplayParams(); |
| 556 | if (SkToBool(fColorSpace) != SkToBool(params.fColorSpace)) { |
| 557 | params.fColorSpace = fColorSpace ? SkColorSpace::MakeSRGB() : nullptr; |
| 558 | fWindow->setDisplayParams(params); |
| 559 | } |
| 560 | |
| 561 | this->updateTitle(); |
| 562 | fWindow->inval(); |
| 563 | } |
| 564 | |
| 565 | void Viewer::drawSlide(SkCanvas* canvas) { |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 566 | int count = canvas->save(); |
| djsollen | 12d62a7 | 2016-04-21 07:59:44 -0700 | [diff] [blame] | 567 | if (fWindow->supportsContentRect()) { |
| 568 | SkRect contentRect = fWindow->getContentRect(); |
| 569 | canvas->clipRect(contentRect); |
| 570 | canvas->translate(contentRect.fLeft, contentRect.fTop); |
| 571 | } |
| 572 | |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 573 | // By default, we render directly into the window's surface/canvas |
| 574 | SkCanvas* slideCanvas = canvas; |
| Brian Osman | f687709 | 2017-02-13 09:39:57 -0500 | [diff] [blame] | 575 | fLastImage.reset(); |
| jvanverth | 3d6ed3a | 2016-04-07 11:09:51 -0700 | [diff] [blame] | 576 | |
| Brian Osman | f687709 | 2017-02-13 09:39:57 -0500 | [diff] [blame] | 577 | // If we're in F16, or the gamut isn't sRGB, or we're zooming, we need to render offscreen |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 578 | sk_sp<SkSurface> offscreenSurface = nullptr; |
| Brian Osman | f687709 | 2017-02-13 09:39:57 -0500 | [diff] [blame] | 579 | if (kRGBA_F16_SkColorType == fColorType || fShowZoomWindow || |
| Brian Osman | 462334e | 2017-02-09 11:22:57 -0500 | [diff] [blame] | 580 | (fColorSpace && fColorSpace != SkColorSpace::MakeSRGB())) { |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 581 | SkImageInfo info = SkImageInfo::Make(fWindow->width(), fWindow->height(), fColorType, |
| 582 | kPremul_SkAlphaType, fColorSpace); |
| 583 | offscreenSurface = canvas->makeSurface(info); |
| 584 | slideCanvas = offscreenSurface->getCanvas(); |
| 585 | } |
| 586 | |
| 587 | slideCanvas->clear(SK_ColorWHITE); |
| 588 | slideCanvas->concat(fDefaultMatrix); |
| 589 | slideCanvas->concat(computeMatrix()); |
| 590 | |
| Brian Osman | 1df161a | 2017-02-09 12:10:20 -0500 | [diff] [blame] | 591 | // Time the painting logic of the slide |
| 592 | double startTime = SkTime::GetMSecs(); |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 593 | fSlides[fCurrentSlide]->draw(slideCanvas); |
| Brian Osman | 1df161a | 2017-02-09 12:10:20 -0500 | [diff] [blame] | 594 | fPaintTimes[fCurrentMeasurement] = SkTime::GetMSecs() - startTime; |
| 595 | |
| 596 | // Force a flush so we can time that, too |
| 597 | startTime = SkTime::GetMSecs(); |
| 598 | slideCanvas->flush(); |
| 599 | fFlushTimes[fCurrentMeasurement] = SkTime::GetMSecs() - startTime; |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 600 | |
| 601 | // If we rendered offscreen, snap an image and push the results to the window's canvas |
| 602 | if (offscreenSurface) { |
| Brian Osman | f687709 | 2017-02-13 09:39:57 -0500 | [diff] [blame] | 603 | fLastImage = offscreenSurface->makeImageSnapshot(); |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 604 | |
| 605 | // Tag the image with the sRGB gamut, so no further color space conversion happens |
| 606 | sk_sp<SkColorSpace> cs = (kRGBA_F16_SkColorType == fColorType) |
| 607 | ? SkColorSpace::MakeSRGBLinear() : SkColorSpace::MakeSRGB(); |
| Brian Osman | f687709 | 2017-02-13 09:39:57 -0500 | [diff] [blame] | 608 | auto retaggedImage = SkImageMakeRasterCopyAndAssignColorSpace(fLastImage.get(), cs.get()); |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 609 | canvas->drawImage(retaggedImage, 0, 0); |
| liyuqian | 74959a1 | 2016-06-16 14:10:34 -0700 | [diff] [blame] | 610 | } |
| 611 | |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 612 | canvas->restoreToCount(count); |
| liyuqian | 6f163d2 | 2016-06-13 12:26:45 -0700 | [diff] [blame] | 613 | } |
| 614 | |
| 615 | void Viewer::onPaint(SkCanvas* canvas) { |
| Brian Osman | 79086b9 | 2017-02-10 13:36:16 -0500 | [diff] [blame] | 616 | // Update ImGui input |
| 617 | ImGuiIO& io = ImGui::GetIO(); |
| 618 | io.DeltaTime = 1.0f / 60.0f; |
| 619 | io.DisplaySize.x = static_cast<float>(fWindow->width()); |
| 620 | io.DisplaySize.y = static_cast<float>(fWindow->height()); |
| 621 | |
| 622 | io.KeyAlt = io.KeysDown[static_cast<int>(Window::Key::kOption)]; |
| 623 | io.KeyCtrl = io.KeysDown[static_cast<int>(Window::Key::kCtrl)]; |
| 624 | io.KeyShift = io.KeysDown[static_cast<int>(Window::Key::kShift)]; |
| 625 | |
| 626 | ImGui::NewFrame(); |
| 627 | |
| Brian Osman | f750fbc | 2017-02-08 10:47:28 -0500 | [diff] [blame] | 628 | drawSlide(canvas); |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 629 | |
| Brian Osman | 1df161a | 2017-02-09 12:10:20 -0500 | [diff] [blame] | 630 | // Advance our timing bookkeeping |
| 631 | fCurrentMeasurement = (fCurrentMeasurement + 1) & (kMeasurementCount - 1); |
| 632 | SkASSERT(fCurrentMeasurement < kMeasurementCount); |
| 633 | |
| 634 | // Draw any overlays or UI that we don't want timed |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 635 | if (fDisplayStats) { |
| 636 | drawStats(canvas); |
| 637 | } |
| brianosman | 622c8d5 | 2016-05-10 06:50:49 -0700 | [diff] [blame] | 638 | fCommands.drawHelp(canvas); |
| liyuqian | 2edb0f4 | 2016-07-06 14:11:32 -0700 | [diff] [blame] | 639 | |
| Brian Osman | 79086b9 | 2017-02-10 13:36:16 -0500 | [diff] [blame] | 640 | drawImGui(canvas); |
| 641 | |
| Brian Osman | 1df161a | 2017-02-09 12:10:20 -0500 | [diff] [blame] | 642 | // Update the FPS |
| 643 | updateUIState(); |
| jvanverth | 3d6ed3a | 2016-04-07 11:09:51 -0700 | [diff] [blame] | 644 | } |
| 645 | |
| jvanverth | 814e38d | 2016-06-06 08:48:47 -0700 | [diff] [blame] | 646 | bool Viewer::onTouch(intptr_t owner, Window::InputState state, float x, float y) { |
| liyuqian | d3cdbca | 2016-05-17 12:44:20 -0700 | [diff] [blame] | 647 | void* castedOwner = reinterpret_cast<void*>(owner); |
| liyuqian | e46e4f0 | 2016-05-20 07:32:19 -0700 | [diff] [blame] | 648 | SkPoint touchPoint = fDefaultMatrixInv.mapXY(x, y); |
| liyuqian | d3cdbca | 2016-05-17 12:44:20 -0700 | [diff] [blame] | 649 | switch (state) { |
| 650 | case Window::kUp_InputState: { |
| 651 | fGesture.touchEnd(castedOwner); |
| 652 | break; |
| 653 | } |
| 654 | case Window::kDown_InputState: { |
| liyuqian | e46e4f0 | 2016-05-20 07:32:19 -0700 | [diff] [blame] | 655 | fGesture.touchBegin(castedOwner, touchPoint.fX, touchPoint.fY); |
| liyuqian | d3cdbca | 2016-05-17 12:44:20 -0700 | [diff] [blame] | 656 | break; |
| 657 | } |
| 658 | case Window::kMove_InputState: { |
| liyuqian | e46e4f0 | 2016-05-20 07:32:19 -0700 | [diff] [blame] | 659 | fGesture.touchMoved(castedOwner, touchPoint.fX, touchPoint.fY); |
| liyuqian | d3cdbca | 2016-05-17 12:44:20 -0700 | [diff] [blame] | 660 | break; |
| 661 | } |
| 662 | } |
| 663 | fWindow->inval(); |
| 664 | return true; |
| 665 | } |
| 666 | |
| jvanverth | 3452426 | 2016-05-04 13:49:13 -0700 | [diff] [blame] | 667 | void Viewer::drawStats(SkCanvas* canvas) { |
| jvanverth | 3d6ed3a | 2016-04-07 11:09:51 -0700 | [diff] [blame] | 668 | static const float kPixelPerMS = 2.0f; |
| 669 | static const int kDisplayWidth = 130; |
| 670 | static const int kDisplayHeight = 100; |
| 671 | static const int kDisplayPadding = 10; |
| 672 | static const int kGraphPadding = 3; |
| 673 | static const SkScalar kBaseMS = 1000.f / 60.f; // ms/frame to hit 60 fps |
| 674 | |
| 675 | SkISize canvasSize = canvas->getDeviceSize(); |
| 676 | SkRect rect = SkRect::MakeXYWH(SkIntToScalar(canvasSize.fWidth-kDisplayWidth-kDisplayPadding), |
| 677 | SkIntToScalar(kDisplayPadding), |
| 678 | SkIntToScalar(kDisplayWidth), SkIntToScalar(kDisplayHeight)); |
| 679 | SkPaint paint; |
| 680 | canvas->save(); |
| 681 | |
| djsollen | 12d62a7 | 2016-04-21 07:59:44 -0700 | [diff] [blame] | 682 | if (fWindow->supportsContentRect()) { |
| 683 | SkRect contentRect = fWindow->getContentRect(); |
| 684 | canvas->clipRect(contentRect); |
| 685 | canvas->translate(contentRect.fLeft, contentRect.fTop); |
| 686 | } |
| 687 | |
| jvanverth | 3d6ed3a | 2016-04-07 11:09:51 -0700 | [diff] [blame] | 688 | canvas->clipRect(rect); |
| 689 | paint.setColor(SK_ColorBLACK); |
| 690 | canvas->drawRect(rect, paint); |
| 691 | // draw the 16ms line |
| 692 | paint.setColor(SK_ColorLTGRAY); |
| 693 | canvas->drawLine(rect.fLeft, rect.fBottom - kBaseMS*kPixelPerMS, |
| 694 | rect.fRight, rect.fBottom - kBaseMS*kPixelPerMS, paint); |
| 695 | paint.setColor(SK_ColorRED); |
| 696 | paint.setStyle(SkPaint::kStroke_Style); |
| 697 | canvas->drawRect(rect, paint); |
| 698 | |
| 699 | int x = SkScalarTruncToInt(rect.fLeft) + kGraphPadding; |
| 700 | const int xStep = 2; |
| jvanverth | 3d6ed3a | 2016-04-07 11:09:51 -0700 | [diff] [blame] | 701 | int i = fCurrentMeasurement; |
| 702 | do { |
| Brian Osman | 1df161a | 2017-02-09 12:10:20 -0500 | [diff] [blame] | 703 | // Round to nearest values |
| 704 | int animateHeight = (int)(fAnimateTimes[i] * kPixelPerMS + 0.5); |
| 705 | int paintHeight = (int)(fPaintTimes[i] * kPixelPerMS + 0.5); |
| 706 | int flushHeight = (int)(fFlushTimes[i] * kPixelPerMS + 0.5); |
| 707 | int startY = SkScalarTruncToInt(rect.fBottom); |
| 708 | int endY = startY - flushHeight; |
| 709 | paint.setColor(SK_ColorRED); |
| 710 | canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY), |
| 711 | SkIntToScalar(x), SkIntToScalar(endY), paint); |
| 712 | startY = endY; |
| 713 | endY = startY - paintHeight; |
| 714 | paint.setColor(SK_ColorGREEN); |
| 715 | canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY), |
| 716 | SkIntToScalar(x), SkIntToScalar(endY), paint); |
| 717 | startY = endY; |
| 718 | endY = startY - animateHeight; |
| 719 | paint.setColor(SK_ColorMAGENTA); |
| jvanverth | 3d6ed3a | 2016-04-07 11:09:51 -0700 | [diff] [blame] | 720 | canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY), |
| 721 | SkIntToScalar(x), SkIntToScalar(endY), paint); |
| 722 | i++; |
| 723 | i &= (kMeasurementCount - 1); // fast mod |
| 724 | x += xStep; |
| 725 | } while (i != fCurrentMeasurement); |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 726 | |
| 727 | canvas->restore(); |
| 728 | } |
| 729 | |
| Brian Osman | 79086b9 | 2017-02-10 13:36:16 -0500 | [diff] [blame] | 730 | void Viewer::drawImGui(SkCanvas* canvas) { |
| 731 | // Support drawing the ImGui demo window. Superfluous, but gives a good idea of what's possible |
| 732 | if (fShowImGuiTestWindow) { |
| 733 | ImGui::ShowTestWindow(&fShowImGuiTestWindow); |
| 734 | } |
| 735 | |
| 736 | if (fShowImGuiDebugWindow) { |
| 737 | if (ImGui::Begin("Debug", &fShowImGuiDebugWindow)) { |
| 738 | if (ImGui::CollapsingHeader("Slide")) { |
| 739 | static ImGuiTextFilter filter; |
| 740 | filter.Draw(); |
| 741 | int previousSlide = fCurrentSlide; |
| 742 | fCurrentSlide = 0; |
| 743 | for (auto slide : fSlides) { |
| 744 | if (filter.PassFilter(slide->getName().c_str())) { |
| 745 | ImGui::BulletText("%s", slide->getName().c_str()); |
| 746 | if (ImGui::IsItemClicked()) { |
| 747 | setupCurrentSlide(previousSlide); |
| 748 | break; |
| 749 | } |
| 750 | } |
| 751 | ++fCurrentSlide; |
| 752 | } |
| 753 | if (fCurrentSlide >= fSlides.count()) { |
| 754 | fCurrentSlide = previousSlide; |
| 755 | } |
| 756 | } |
| 757 | } |
| 758 | |
| 759 | ImGui::End(); |
| 760 | } |
| 761 | |
| Brian Osman | f687709 | 2017-02-13 09:39:57 -0500 | [diff] [blame] | 762 | SkPaint zoomImagePaint; |
| 763 | if (fShowZoomWindow && fLastImage) { |
| 764 | if (ImGui::Begin("Zoom", &fShowZoomWindow, ImVec2(200, 200))) { |
| 765 | static int zoomFactor = 4; |
| 766 | ImGui::SliderInt("Scale", &zoomFactor, 1, 16); |
| 767 | |
| 768 | zoomImagePaint.setShader(fLastImage->makeShader(SkShader::kClamp_TileMode, |
| 769 | SkShader::kClamp_TileMode)); |
| 770 | zoomImagePaint.setColor(SK_ColorWHITE); |
| 771 | |
| 772 | // Zoom by shrinking the corner UVs towards the mouse cursor |
| 773 | ImVec2 mousePos = ImGui::GetMousePos(); |
| 774 | ImVec2 avail = ImGui::GetContentRegionAvail(); |
| 775 | |
| 776 | ImVec2 zoomHalfExtents = ImVec2((avail.x * 0.5f) / zoomFactor, |
| 777 | (avail.y * 0.5f) / zoomFactor); |
| 778 | ImGui::Image(&zoomImagePaint, avail, |
| 779 | ImVec2(mousePos.x - zoomHalfExtents.x, mousePos.y - zoomHalfExtents.y), |
| 780 | ImVec2(mousePos.x + zoomHalfExtents.x, mousePos.y + zoomHalfExtents.y)); |
| 781 | } |
| 782 | |
| 783 | ImGui::End(); |
| 784 | } |
| 785 | |
| Brian Osman | 79086b9 | 2017-02-10 13:36:16 -0500 | [diff] [blame] | 786 | // This causes ImGui to rebuild vertex/index data based on all immediate-mode commands |
| 787 | // (widgets, etc...) that have been issued |
| 788 | ImGui::Render(); |
| 789 | |
| 790 | // Then we fetch the most recent data, and convert it so we can render with Skia |
| 791 | const ImDrawData* drawData = ImGui::GetDrawData(); |
| 792 | SkTDArray<SkPoint> pos; |
| 793 | SkTDArray<SkPoint> uv; |
| 794 | SkTDArray<SkColor> color; |
| Brian Osman | 79086b9 | 2017-02-10 13:36:16 -0500 | [diff] [blame] | 795 | |
| 796 | for (int i = 0; i < drawData->CmdListsCount; ++i) { |
| 797 | const ImDrawList* drawList = drawData->CmdLists[i]; |
| 798 | |
| 799 | // De-interleave all vertex data (sigh), convert to Skia types |
| 800 | pos.rewind(); uv.rewind(); color.rewind(); |
| 801 | for (int i = 0; i < drawList->VtxBuffer.size(); ++i) { |
| 802 | const ImDrawVert& vert = drawList->VtxBuffer[i]; |
| 803 | pos.push(SkPoint::Make(vert.pos.x, vert.pos.y)); |
| 804 | uv.push(SkPoint::Make(vert.uv.x, vert.uv.y)); |
| 805 | color.push(vert.col); |
| 806 | } |
| 807 | // ImGui colors are RGBA |
| 808 | SkSwapRB(color.begin(), color.begin(), color.count()); |
| 809 | |
| 810 | int indexOffset = 0; |
| 811 | |
| 812 | // Draw everything with canvas.drawVertices... |
| 813 | for (int j = 0; j < drawList->CmdBuffer.size(); ++j) { |
| 814 | const ImDrawCmd* drawCmd = &drawList->CmdBuffer[j]; |
| 815 | |
| 816 | // TODO: Find min/max index for each draw, so we know how many vertices (sigh) |
| 817 | if (drawCmd->UserCallback) { |
| 818 | drawCmd->UserCallback(drawList, drawCmd); |
| 819 | } else { |
| Brian Osman | f687709 | 2017-02-13 09:39:57 -0500 | [diff] [blame] | 820 | SkPaint* paint = static_cast<SkPaint*>(drawCmd->TextureId); |
| 821 | SkASSERT(paint); |
| 822 | |
| Brian Osman | 79086b9 | 2017-02-10 13:36:16 -0500 | [diff] [blame] | 823 | canvas->save(); |
| 824 | canvas->clipRect(SkRect::MakeLTRB(drawCmd->ClipRect.x, drawCmd->ClipRect.y, |
| 825 | drawCmd->ClipRect.z, drawCmd->ClipRect.w)); |
| 826 | canvas->drawVertices(SkCanvas::kTriangles_VertexMode, drawList->VtxBuffer.size(), |
| 827 | pos.begin(), uv.begin(), color.begin(), |
| 828 | drawList->IdxBuffer.begin() + indexOffset, drawCmd->ElemCount, |
| Brian Osman | f687709 | 2017-02-13 09:39:57 -0500 | [diff] [blame] | 829 | *paint); |
| Brian Osman | 79086b9 | 2017-02-10 13:36:16 -0500 | [diff] [blame] | 830 | indexOffset += drawCmd->ElemCount; |
| 831 | canvas->restore(); |
| 832 | } |
| 833 | } |
| 834 | } |
| 835 | } |
| 836 | |
| liyuqian | 2edb0f4 | 2016-07-06 14:11:32 -0700 | [diff] [blame] | 837 | void Viewer::onIdle() { |
| Brian Osman | 1df161a | 2017-02-09 12:10:20 -0500 | [diff] [blame] | 838 | double startTime = SkTime::GetMSecs(); |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 839 | fAnimTimer.updateTime(); |
| Brian Osman | 1df161a | 2017-02-09 12:10:20 -0500 | [diff] [blame] | 840 | bool animateWantsInval = fSlides[fCurrentSlide]->animate(fAnimTimer); |
| 841 | fAnimateTimes[fCurrentMeasurement] = SkTime::GetMSecs() - startTime; |
| 842 | |
| Brian Osman | 79086b9 | 2017-02-10 13:36:16 -0500 | [diff] [blame] | 843 | ImGuiIO& io = ImGui::GetIO(); |
| 844 | if (animateWantsInval || fDisplayStats || fRefresh || io.MetricsActiveWindows) { |
| jvanverth | c265a92 | 2016-04-08 12:51:45 -0700 | [diff] [blame] | 845 | fWindow->inval(); |
| 846 | } |
| jvanverth | 9f37246 | 2016-04-06 06:08:59 -0700 | [diff] [blame] | 847 | } |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 848 | |
| 849 | void Viewer::updateUIState() { |
| liyuqian | b73c24b | 2016-06-03 08:47:23 -0700 | [diff] [blame] | 850 | // Slide state |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 851 | Json::Value slideState(Json::objectValue); |
| 852 | slideState[kName] = kSlideStateName; |
| 853 | slideState[kValue] = fSlides[fCurrentSlide]->getName().c_str(); |
| liyuqian | 1f508fd | 2016-06-07 06:57:40 -0700 | [diff] [blame] | 854 | if (fAllSlideNames.size() == 0) { |
| 855 | for(auto slide : fSlides) { |
| 856 | fAllSlideNames.append(Json::Value(slide->getName().c_str())); |
| 857 | } |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 858 | } |
| liyuqian | 1f508fd | 2016-06-07 06:57:40 -0700 | [diff] [blame] | 859 | slideState[kOptions] = fAllSlideNames; |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 860 | |
| liyuqian | b73c24b | 2016-06-03 08:47:23 -0700 | [diff] [blame] | 861 | // Backend state |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 862 | Json::Value backendState(Json::objectValue); |
| 863 | backendState[kName] = kBackendStateName; |
| liyuqian | 6cb7025 | 2016-06-02 12:16:25 -0700 | [diff] [blame] | 864 | backendState[kValue] = kBackendTypeStrings[fBackendType]; |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 865 | backendState[kOptions] = Json::Value(Json::arrayValue); |
| liyuqian | b73c24b | 2016-06-03 08:47:23 -0700 | [diff] [blame] | 866 | for (auto str : kBackendTypeStrings) { |
| liyuqian | 6cb7025 | 2016-06-02 12:16:25 -0700 | [diff] [blame] | 867 | backendState[kOptions].append(Json::Value(str)); |
| 868 | } |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 869 | |
| liyuqian | b73c24b | 2016-06-03 08:47:23 -0700 | [diff] [blame] | 870 | // Softkey state |
| 871 | Json::Value softkeyState(Json::objectValue); |
| 872 | softkeyState[kName] = kSoftkeyStateName; |
| 873 | softkeyState[kValue] = kSoftkeyHint; |
| 874 | softkeyState[kOptions] = Json::Value(Json::arrayValue); |
| 875 | softkeyState[kOptions].append(kSoftkeyHint); |
| 876 | for (const auto& softkey : fCommands.getCommandsAsSoftkeys()) { |
| 877 | softkeyState[kOptions].append(Json::Value(softkey.c_str())); |
| 878 | } |
| 879 | |
| liyuqian | 1f508fd | 2016-06-07 06:57:40 -0700 | [diff] [blame] | 880 | // FPS state |
| 881 | Json::Value fpsState(Json::objectValue); |
| 882 | fpsState[kName] = kFpsStateName; |
| Brian Osman | 1df161a | 2017-02-09 12:10:20 -0500 | [diff] [blame] | 883 | int idx = (fCurrentMeasurement + (kMeasurementCount - 1)) & (kMeasurementCount - 1); |
| 884 | fpsState[kValue] = SkStringPrintf("%8.3lf ms\n\nA %8.3lf\nP %8.3lf\nF%8.3lf", |
| 885 | fAnimateTimes[idx] + fPaintTimes[idx] + fFlushTimes[idx], |
| 886 | fAnimateTimes[idx], |
| 887 | fPaintTimes[idx], |
| 888 | fFlushTimes[idx]).c_str(); |
| liyuqian | 1f508fd | 2016-06-07 06:57:40 -0700 | [diff] [blame] | 889 | fpsState[kOptions] = Json::Value(Json::arrayValue); |
| 890 | |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 891 | Json::Value state(Json::arrayValue); |
| 892 | state.append(slideState); |
| 893 | state.append(backendState); |
| liyuqian | b73c24b | 2016-06-03 08:47:23 -0700 | [diff] [blame] | 894 | state.append(softkeyState); |
| liyuqian | 1f508fd | 2016-06-07 06:57:40 -0700 | [diff] [blame] | 895 | state.append(fpsState); |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 896 | |
| 897 | fWindow->setUIState(state); |
| 898 | } |
| 899 | |
| 900 | void Viewer::onUIStateChanged(const SkString& stateName, const SkString& stateValue) { |
| liyuqian | 6cb7025 | 2016-06-02 12:16:25 -0700 | [diff] [blame] | 901 | // For those who will add more features to handle the state change in this function: |
| 902 | // After the change, please call updateUIState no notify the frontend (e.g., Android app). |
| 903 | // For example, after slide change, updateUIState is called inside setupCurrentSlide; |
| 904 | // after backend change, updateUIState is called in this function. |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 905 | if (stateName.equals(kSlideStateName)) { |
| 906 | int previousSlide = fCurrentSlide; |
| 907 | fCurrentSlide = 0; |
| 908 | for(auto slide : fSlides) { |
| 909 | if (slide->getName().equals(stateValue)) { |
| 910 | setupCurrentSlide(previousSlide); |
| 911 | break; |
| 912 | } |
| 913 | fCurrentSlide++; |
| 914 | } |
| 915 | if (fCurrentSlide >= fSlides.count()) { |
| 916 | fCurrentSlide = previousSlide; |
| 917 | SkDebugf("Slide not found: %s", stateValue.c_str()); |
| 918 | } |
| liyuqian | 6cb7025 | 2016-06-02 12:16:25 -0700 | [diff] [blame] | 919 | } else if (stateName.equals(kBackendStateName)) { |
| 920 | for (int i = 0; i < sk_app::Window::kBackendTypeCount; i++) { |
| 921 | if (stateValue.equals(kBackendTypeStrings[i])) { |
| 922 | if (fBackendType != i) { |
| 923 | fBackendType = (sk_app::Window::BackendType)i; |
| 924 | fWindow->detach(); |
| 925 | fWindow->attach(fBackendType, DisplayParams()); |
| 926 | fWindow->inval(); |
| 927 | updateTitle(); |
| 928 | updateUIState(); |
| 929 | } |
| 930 | break; |
| 931 | } |
| 932 | } |
| liyuqian | b73c24b | 2016-06-03 08:47:23 -0700 | [diff] [blame] | 933 | } else if (stateName.equals(kSoftkeyStateName)) { |
| 934 | if (!stateValue.equals(kSoftkeyHint)) { |
| 935 | fCommands.onSoftkey(stateValue); |
| 936 | updateUIState(); // This is still needed to reset the value to kSoftkeyHint |
| 937 | } |
| liyuqian | 2edb0f4 | 2016-07-06 14:11:32 -0700 | [diff] [blame] | 938 | } else if (stateName.equals(kRefreshStateName)) { |
| 939 | // This state is actually NOT in the UI state. |
| 940 | // We use this to allow Android to quickly set bool fRefresh. |
| 941 | fRefresh = stateValue.equals(kON); |
| liyuqian | e5a6cd9 | 2016-05-27 08:52:52 -0700 | [diff] [blame] | 942 | } else { |
| 943 | SkDebugf("Unknown stateName: %s", stateName.c_str()); |
| 944 | } |
| 945 | } |
| Brian Osman | 79086b9 | 2017-02-10 13:36:16 -0500 | [diff] [blame] | 946 | |
| 947 | bool Viewer::onKey(sk_app::Window::Key key, sk_app::Window::InputState state, uint32_t modifiers) { |
| 948 | return fCommands.onKey(key, state, modifiers); |
| 949 | } |
| 950 | |
| 951 | bool Viewer::onChar(SkUnichar c, uint32_t modifiers) { |
| 952 | return fCommands.onChar(c, modifiers); |
| 953 | } |