Mercurial > hg > orthanc-stone
annotate Platforms/Wasm/Defaults.cpp @ 427:3f9017db1738 am-vsol-upgrade-radiography-export
wip
author | am@osimis.io |
---|---|
date | Fri, 23 Nov 2018 16:06:23 +0100 |
parents | c23df8b3433b |
children | 26b90b110719 |
rev | line source |
---|---|
222 | 1 #include "Defaults.h" |
2 | |
223 | 3 #include "WasmWebService.h" |
4 #include <Framework/dev.h> | |
5 #include "Framework/Widgets/TestCairoWidget.h" | |
6 #include <Framework/Viewport/WidgetViewport.h> | |
228 | 7 #include <algorithm> |
242 | 8 #include "Applications/Wasm/StartupParametersBuilder.h" |
307 | 9 #include "Platforms/Wasm/WasmPlatformApplicationAdapter.h" |
223 | 10 |
11 static unsigned int width_ = 0; | |
12 static unsigned int height_ = 0; | |
13 | |
14 /**********************************/ | |
15 | |
288 | 16 static std::unique_ptr<OrthancStone::IStoneApplication> application; |
307 | 17 static std::unique_ptr<OrthancStone::WasmPlatformApplicationAdapter> applicationWasmAdapter = NULL; |
288 | 18 static std::unique_ptr<OrthancStone::StoneApplicationContext> context; |
242 | 19 static OrthancStone::StartupParametersBuilder startupParametersBuilder; |
253 | 20 static OrthancStone::MessageBroker broker; |
242 | 21 |
385
6cc3ce74dc05
using message broker in widgets
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
327
diff
changeset
|
22 static OrthancStone::ViewportContentChangedObserver viewportContentChangedObserver_(broker); |
223 | 23 static OrthancStone::StatusBar statusBar_; |
24 | |
227 | 25 static std::list<std::shared_ptr<OrthancStone::WidgetViewport>> viewports_; |
26 | |
228 | 27 std::shared_ptr<OrthancStone::WidgetViewport> FindViewportSharedPtr(ViewportHandle viewport) { |
28 for (const auto& v : viewports_) { | |
29 if (v.get() == viewport) { | |
30 return v; | |
31 } | |
32 } | |
229 | 33 assert(false); |
34 return std::shared_ptr<OrthancStone::WidgetViewport>(); | |
228 | 35 } |
36 | |
223 | 37 #ifdef __cplusplus |
38 extern "C" { | |
39 #endif | |
40 | |
41 using namespace OrthancStone; | |
227 | 42 |
43 // when WASM needs a C++ viewport | |
44 ViewportHandle EMSCRIPTEN_KEEPALIVE CreateCppViewport() { | |
45 | |
385
6cc3ce74dc05
using message broker in widgets
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
327
diff
changeset
|
46 std::shared_ptr<OrthancStone::WidgetViewport> viewport(new OrthancStone::WidgetViewport(broker)); |
287 | 47 printf("viewport %x\n", (int)viewport.get()); |
227 | 48 |
49 viewports_.push_back(viewport); | |
50 | |
51 printf("There are now %d viewports in C++\n", viewports_.size()); | |
52 | |
53 viewport->SetStatusBar(statusBar_); | |
385
6cc3ce74dc05
using message broker in widgets
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
327
diff
changeset
|
54 |
6cc3ce74dc05
using message broker in widgets
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
327
diff
changeset
|
55 viewport->RegisterObserverCallback( |
6cc3ce74dc05
using message broker in widgets
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
327
diff
changeset
|
56 new Callable<ViewportContentChangedObserver, IViewport::ViewportChangedMessage> |
6cc3ce74dc05
using message broker in widgets
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
327
diff
changeset
|
57 (viewportContentChangedObserver_, &ViewportContentChangedObserver::OnViewportChanged)); |
227 | 58 |
59 return viewport.get(); | |
60 } | |
61 | |
62 // when WASM does not need a viewport anymore, it should release it | |
63 void EMSCRIPTEN_KEEPALIVE ReleaseCppViewport(ViewportHandle viewport) { | |
64 viewports_.remove_if([viewport](const std::shared_ptr<OrthancStone::WidgetViewport>& v) { return v.get() == viewport;}); | |
65 | |
66 printf("There are now %d viewports in C++\n", viewports_.size()); | |
67 } | |
68 | |
69 void EMSCRIPTEN_KEEPALIVE CreateWasmApplication(ViewportHandle viewport) { | |
223 | 70 |
71 printf("CreateWasmApplication\n"); | |
72 | |
253 | 73 application.reset(CreateUserApplication(broker)); |
307 | 74 applicationWasmAdapter.reset(CreateWasmApplicationAdapter(broker, application.get())); |
255 | 75 WasmWebService::SetBroker(broker); |
223 | 76 |
242 | 77 startupParametersBuilder.Clear(); |
223 | 78 } |
79 | |
80 void EMSCRIPTEN_KEEPALIVE SetStartupParameter(const char* keyc, | |
81 const char* value) { | |
242 | 82 startupParametersBuilder.SetStartupParameter(keyc, value); |
223 | 83 } |
84 | |
418 | 85 void EMSCRIPTEN_KEEPALIVE StartWasmApplication(const char* baseUri) { |
223 | 86 |
87 printf("StartWasmApplication\n"); | |
88 | |
89 // recreate a command line from uri arguments and parse it | |
90 boost::program_options::variables_map parameters; | |
242 | 91 boost::program_options::options_description options; |
92 application->DeclareStartupOptions(options); | |
93 startupParametersBuilder.GetStartupParameters(parameters, options); | |
223 | 94 |
418 | 95 context.reset(new OrthancStone::StoneApplicationContext(broker)); |
96 context->SetOrthancBaseUrl(baseUri); | |
97 printf("Base URL to Orthanc API: [%s]\n", baseUri); | |
98 context->SetWebService(OrthancStone::WasmWebService::GetInstance()); | |
242 | 99 application->Initialize(context.get(), statusBar_, parameters); |
100 application->InitializeWasm(); | |
223 | 101 |
231
5027cb2feb51
viewport is now part of the Application itself and not global anymore
am@osimis.io
parents:
229
diff
changeset
|
102 // viewport->SetSize(width_, height_); |
223 | 103 printf("StartWasmApplication - completed\n"); |
104 } | |
105 | |
386
e33659decec5
renamed UpdateContent() as DoAnimation()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
385
diff
changeset
|
106 void EMSCRIPTEN_KEEPALIVE WasmDoAnimation() |
223 | 107 { |
228 | 108 for (auto viewport : viewports_) { |
386
e33659decec5
renamed UpdateContent() as DoAnimation()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
385
diff
changeset
|
109 // TODO Only launch the JavaScript timer if "HasAnimation()" |
e33659decec5
renamed UpdateContent() as DoAnimation()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
385
diff
changeset
|
110 if (viewport->HasAnimation()) |
228 | 111 { |
386
e33659decec5
renamed UpdateContent() as DoAnimation()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
385
diff
changeset
|
112 viewport->DoAnimation(); |
228 | 113 } |
114 | |
223 | 115 } |
116 | |
117 } | |
118 | |
119 | |
228 | 120 void EMSCRIPTEN_KEEPALIVE ViewportSetSize(ViewportHandle viewport, unsigned int width, unsigned int height) |
223 | 121 { |
122 width_ = width; | |
123 height_ = height; | |
124 | |
228 | 125 viewport->SetSize(width, height); |
223 | 126 } |
127 | |
228 | 128 int EMSCRIPTEN_KEEPALIVE ViewportRender(ViewportHandle viewport, |
227 | 129 unsigned int width, |
223 | 130 unsigned int height, |
131 uint8_t* data) | |
132 { | |
278 | 133 viewportContentChangedObserver_.Reset(); |
223 | 134 |
135 //printf("ViewportRender called %dx%d\n", width, height); | |
136 if (width == 0 || | |
137 height == 0) | |
138 { | |
139 return 1; | |
140 } | |
141 | |
142 Orthanc::ImageAccessor surface; | |
143 surface.AssignWritable(Orthanc::PixelFormat_BGRA32, width, height, 4 * width, data); | |
144 | |
227 | 145 viewport->Render(surface); |
223 | 146 |
147 // Convert from BGRA32 memory layout (only color mode supported by | |
148 // Cairo, which corresponds to CAIRO_FORMAT_ARGB32) to RGBA32 (as | |
149 // expected by HTML5 canvas). This simply amounts to swapping the | |
150 // B and R channels. | |
151 uint8_t* p = data; | |
152 for (unsigned int y = 0; y < height; y++) { | |
153 for (unsigned int x = 0; x < width; x++) { | |
154 uint8_t tmp = p[0]; | |
155 p[0] = p[2]; | |
156 p[2] = tmp; | |
157 | |
158 p += 4; | |
159 } | |
160 } | |
161 | |
162 return 1; | |
163 } | |
164 | |
165 | |
228 | 166 void EMSCRIPTEN_KEEPALIVE ViewportMouseDown(ViewportHandle viewport, |
167 unsigned int rawButton, | |
223 | 168 int x, |
169 int y, | |
170 unsigned int rawModifiers) | |
171 { | |
172 OrthancStone::MouseButton button; | |
173 switch (rawButton) | |
174 { | |
175 case 0: | |
176 button = OrthancStone::MouseButton_Left; | |
177 break; | |
178 | |
179 case 1: | |
180 button = OrthancStone::MouseButton_Middle; | |
181 break; | |
182 | |
183 case 2: | |
184 button = OrthancStone::MouseButton_Right; | |
185 break; | |
186 | |
187 default: | |
188 return; // Unknown button | |
189 } | |
190 | |
228 | 191 viewport->MouseDown(button, x, y, OrthancStone::KeyboardModifiers_None /* TODO */); |
223 | 192 } |
193 | |
194 | |
228 | 195 void EMSCRIPTEN_KEEPALIVE ViewportMouseWheel(ViewportHandle viewport, |
196 int deltaY, | |
223 | 197 int x, |
198 int y, | |
199 int isControl) | |
200 { | |
228 | 201 if (deltaY != 0) |
223 | 202 { |
203 OrthancStone::MouseWheelDirection direction = (deltaY < 0 ? | |
204 OrthancStone::MouseWheelDirection_Up : | |
205 OrthancStone::MouseWheelDirection_Down); | |
206 OrthancStone::KeyboardModifiers modifiers = OrthancStone::KeyboardModifiers_None; | |
207 | |
208 if (isControl != 0) | |
209 { | |
210 modifiers = OrthancStone::KeyboardModifiers_Control; | |
211 } | |
212 | |
228 | 213 viewport->MouseWheel(direction, x, y, modifiers); |
223 | 214 } |
215 } | |
216 | |
217 | |
228 | 218 void EMSCRIPTEN_KEEPALIVE ViewportMouseMove(ViewportHandle viewport, |
219 int x, | |
223 | 220 int y) |
221 { | |
228 | 222 viewport->MouseMove(x, y); |
223 | 223 } |
224 | |
228 | 225 void EMSCRIPTEN_KEEPALIVE ViewportKeyPressed(ViewportHandle viewport, |
327 | 226 int key, |
227 const char* keyChar, | |
223 | 228 bool isShiftPressed, |
229 bool isControlPressed, | |
230 bool isAltPressed) | |
231 | |
232 { | |
228 | 233 OrthancStone::KeyboardModifiers modifiers = OrthancStone::KeyboardModifiers_None; |
234 if (isShiftPressed) { | |
235 modifiers = static_cast<OrthancStone::KeyboardModifiers>(modifiers + OrthancStone::KeyboardModifiers_Shift); | |
223 | 236 } |
228 | 237 if (isControlPressed) { |
238 modifiers = static_cast<OrthancStone::KeyboardModifiers>(modifiers + OrthancStone::KeyboardModifiers_Control); | |
239 } | |
240 if (isAltPressed) { | |
241 modifiers = static_cast<OrthancStone::KeyboardModifiers>(modifiers + OrthancStone::KeyboardModifiers_Alt); | |
242 } | |
327 | 243 |
244 char c = 0; | |
245 if (keyChar != NULL && key == OrthancStone::KeyboardKeys_Generic) { | |
246 c = keyChar[0]; | |
247 } | |
248 viewport->KeyPressed(static_cast<OrthancStone::KeyboardKeys>(key), c, modifiers); | |
223 | 249 } |
250 | |
251 | |
228 | 252 void EMSCRIPTEN_KEEPALIVE ViewportMouseUp(ViewportHandle viewport) |
223 | 253 { |
228 | 254 viewport->MouseUp(); |
223 | 255 } |
256 | |
257 | |
228 | 258 void EMSCRIPTEN_KEEPALIVE ViewportMouseEnter(ViewportHandle viewport) |
223 | 259 { |
228 | 260 viewport->MouseEnter(); |
223 | 261 } |
262 | |
263 | |
228 | 264 void EMSCRIPTEN_KEEPALIVE ViewportMouseLeave(ViewportHandle viewport) |
223 | 265 { |
228 | 266 viewport->MouseLeave(); |
223 | 267 } |
268 | |
287 | 269 const char* EMSCRIPTEN_KEEPALIVE SendMessageToStoneApplication(const char* message) |
270 { | |
271 static std::string output; // we don't want the string to be deallocated when we return to JS code so we always use the same string (this is fine since JS is single-thread) | |
272 | |
307 | 273 printf("SendMessageToStoneApplication\n"); |
309 | 274 printf("%s", message); |
307 | 275 |
276 if (applicationWasmAdapter.get() != NULL) { | |
277 printf("sending message to C++\n"); | |
278 applicationWasmAdapter->HandleMessageFromWeb(output, std::string(message)); | |
287 | 279 return output.c_str(); |
280 } | |
307 | 281 printf("This stone application does not have a Web Adapter"); |
282 return NULL; | |
287 | 283 } |
284 | |
223 | 285 |
286 #ifdef __cplusplus | |
287 } | |
288 #endif |