comparison OrthancStone/Sources/Viewport/WebAssemblyCairoViewport.cpp @ 1512:244ad1e4e76a

reorganization of folders
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 07 Jul 2020 16:21:02 +0200
parents Framework/Viewport/WebAssemblyCairoViewport.cpp@4de884c95cd8
children c54bc5bffd01
comparison
equal deleted inserted replaced
1511:9dfeee74c1e6 1512:244ad1e4e76a
1 /**
2 * Stone of Orthanc
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2020 Osimis S.A., Belgium
6 *
7 * This program is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU Affero General Public License
9 * as published by the Free Software Foundation, either version 3 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 **/
20
21
22 #include "WebAssemblyCairoViewport.h"
23
24 #include "../Scene2D/CairoCompositor.h"
25
26 #include <Images/Image.h>
27
28 #include <boost/math/special_functions/round.hpp>
29
30 namespace OrthancStone
31 {
32 void WebAssemblyCairoViewport::GetCanvasSize(unsigned int& width,
33 unsigned int& height)
34 {
35 double w, h;
36 emscripten_get_element_css_size(GetCanvasCssSelector().c_str(), &w, &h);
37
38 /**
39 * Emscripten has the function emscripten_get_element_css_size()
40 * to query the width and height of a named HTML element. I'm
41 * calling this first to get the initial size of the canvas DOM
42 * element, and then call emscripten_set_canvas_size() to
43 * initialize the framebuffer size of the canvas to the same
44 * size as its DOM element.
45 * https://floooh.github.io/2017/02/22/emsc-html.html
46 **/
47 if (w > 0 &&
48 h > 0)
49 {
50 width = static_cast<unsigned int>(boost::math::iround(w));
51 height = static_cast<unsigned int>(boost::math::iround(h));
52 }
53 else
54 {
55 width = 0;
56 height = 0;
57 }
58 }
59
60
61 void WebAssemblyCairoViewport::Paint(ICompositor& compositor,
62 ViewportController& controller)
63 {
64 compositor.Refresh(controller.GetScene());
65
66 // Create a temporary memory buffer for the canvas in JavaScript
67 Orthanc::ImageAccessor cairo;
68 dynamic_cast<CairoCompositor&>(compositor).GetCanvas().GetReadOnlyAccessor(cairo);
69
70 const unsigned int width = cairo.GetWidth();
71 const unsigned int height = cairo.GetHeight();
72
73 if (javascript_.get() == NULL ||
74 javascript_->GetWidth() != width ||
75 javascript_->GetHeight() != height)
76 {
77 javascript_.reset(new Orthanc::Image(Orthanc::PixelFormat_RGBA32, width, height,
78 true /* force minimal pitch */));
79 }
80
81 // Convert from BGRA32 memory layout (only color mode supported
82 // by Cairo, which corresponds to CAIRO_FORMAT_ARGB32) to RGBA32
83 // (as expected by HTML5 canvas). This simply amounts to
84 // swapping the B and R channels. Alpha channel is also set to
85 // full opacity (255).
86 uint8_t* q = reinterpret_cast<uint8_t*>(javascript_->GetBuffer());
87 for (unsigned int y = 0; y < height; y++)
88 {
89 const uint8_t* p = reinterpret_cast<const uint8_t*>(cairo.GetConstRow(y));
90 for (unsigned int x = 0; x < width; x++)
91 {
92 q[0] = p[2]; // R
93 q[1] = p[1]; // G
94 q[2] = p[0]; // B
95 q[3] = 255; // A
96
97 p += 4;
98 q += 4;
99 }
100 }
101
102 // Execute JavaScript commands to blit the image buffer onto the
103 // 2D drawing context of the HTML5 canvas
104 EM_ASM({
105 const data = new Uint8ClampedArray(Module.HEAP8.buffer, $1, 4 * $2 * $3);
106 const img = new ImageData(data, $2, $3);
107 const ctx = document.getElementById(UTF8ToString($0)).getContext('2d');
108 ctx.putImageData(img, 0, 0);
109 },
110 GetCanvasId().c_str(), // $0
111 javascript_->GetBuffer(), // $1
112 javascript_->GetWidth(), // $2
113 javascript_->GetHeight()); // $3
114 }
115
116
117 void WebAssemblyCairoViewport::UpdateSize(ICompositor& compositor)
118 {
119 unsigned int width, height;
120 GetCanvasSize(width, height);
121 emscripten_set_canvas_element_size(GetCanvasCssSelector().c_str(), width, height);
122
123 dynamic_cast<CairoCompositor&>(compositor).UpdateSize(width, height);
124 }
125
126
127 WebAssemblyCairoViewport::WebAssemblyCairoViewport(
128 const std::string& canvasId) :
129 WebAssemblyViewport(canvasId)
130 {
131 unsigned int width, height;
132 GetCanvasSize(width, height);
133 emscripten_set_canvas_element_size(GetCanvasCssSelector().c_str(),
134 width,
135 height);
136
137 AcquireCompositor(new CairoCompositor(width, height));
138 }
139 }