# HG changeset patch # User Alain Mazy # Date 1563439859 -7200 # Node ID 64e5f3ff6360dd512dfdb2ccddfa1f7115aa3ed0 # Parent ef6e425dc79ffdc74067e57e459e0169a6391785# Parent a6c12fe88bcb9eed59c58859affbabb8a5c85355 Merge diff -r ef6e425dc79f -r 64e5f3ff6360 Applications/Generic/GuiAdapter.cpp --- a/Applications/Generic/GuiAdapter.cpp Wed Jul 17 15:33:07 2019 +0200 +++ b/Applications/Generic/GuiAdapter.cpp Thu Jul 18 10:50:59 2019 +0200 @@ -725,10 +725,13 @@ // SDL ONLY void GuiAdapter::Run() { +#if 0 + // TODO: MAKE THIS DYNAMIC !!! See SdlOpenGLViewport vs Cairo in ViewportWrapper # if ORTHANC_ENABLE_OPENGL == 1 && !defined(__APPLE__) glEnable(GL_DEBUG_OUTPUT); glDebugMessageCallback(OpenGLMessageCallback, 0); # endif +#endif // Uint32 SDL_GetWindowID(SDL_Window* window) // SDL_Window* SDL_GetWindowFromID(Uint32 id) // may return NULL diff -r ef6e425dc79f -r 64e5f3ff6360 Framework/Scene2D/CairoCompositor.cpp --- a/Framework/Scene2D/CairoCompositor.cpp Wed Jul 17 15:33:07 2019 +0200 +++ b/Framework/Scene2D/CairoCompositor.cpp Thu Jul 18 10:50:59 2019 +0200 @@ -91,9 +91,14 @@ unsigned int canvasHeight) : helper_(scene, *this) { + UpdateSize(canvasWidth, canvasHeight); + } + + void CairoCompositor::UpdateSize(unsigned int canvasWidth, + unsigned int canvasHeight) + { canvas_.SetSize(canvasWidth, canvasHeight, false); } - CairoCompositor::~CairoCompositor() { diff -r ef6e425dc79f -r 64e5f3ff6360 Framework/Scene2D/CairoCompositor.h --- a/Framework/Scene2D/CairoCompositor.h Wed Jul 17 15:33:07 2019 +0200 +++ b/Framework/Scene2D/CairoCompositor.h Thu Jul 18 10:50:59 2019 +0200 @@ -13,7 +13,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . **/ @@ -21,6 +21,7 @@ #pragma once +#include "ICompositor.h" #include "../Fonts/GlyphBitmapAlphabet.h" #include "../Wrappers/CairoContext.h" #include "Internals/CompositorHelper.h" @@ -29,9 +30,9 @@ namespace OrthancStone { class CairoCompositor : - public ICompositor, - private Internals::CompositorHelper::IRendererFactory, - private Internals::ICairoContextProvider + public ICompositor, + private Internals::CompositorHelper::IRendererFactory, + private Internals::ICairoContextProvider { private: typedef std::map Fonts; @@ -52,7 +53,7 @@ unsigned int canvasWidth, unsigned int canvasHeight); - ~CairoCompositor(); + virtual ~CairoCompositor(); const CairoSurface& GetCanvas() const { @@ -73,14 +74,17 @@ GlyphBitmapAlphabet* dict); // Takes ownership #if ORTHANC_ENABLE_LOCALE == 1 - void SetFont(size_t index, - Orthanc::EmbeddedResources::FileResourceId resource, - unsigned int fontSize, - Orthanc::Encoding codepage); + virtual void SetFont(size_t index, + Orthanc::EmbeddedResources::FileResourceId resource, + unsigned int fontSize, + Orthanc::Encoding codepage); #endif virtual void Refresh(); + void UpdateSize(unsigned int canvasWidth, + unsigned int canvasHeight); + Orthanc::ImageAccessor* RenderText(size_t fontIndex, const std::string& utf8) const; }; diff -r ef6e425dc79f -r 64e5f3ff6360 Framework/Scene2D/ICompositor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2D/ICompositor.h Thu Jul 18 10:50:59 2019 +0200 @@ -0,0 +1,29 @@ +#pragma once + +#include +#include +#include + +namespace OrthancStone +{ + class ICompositor : public boost::noncopyable + { + + public: + virtual ~ICompositor() {} + + virtual unsigned int GetCanvasWidth() const = 0; + + virtual unsigned int GetCanvasHeight() const = 0; + + virtual void Refresh() = 0; + +#if ORTHANC_ENABLE_LOCALE == 1 + virtual void SetFont(size_t index, + Orthanc::EmbeddedResources::FileResourceId resource, + unsigned int fontSize, + Orthanc::Encoding codepage) = 0; +#endif + + }; +} diff -r ef6e425dc79f -r 64e5f3ff6360 Framework/Scene2D/OpenGLCompositor.h --- a/Framework/Scene2D/OpenGLCompositor.h Wed Jul 17 15:33:07 2019 +0200 +++ b/Framework/Scene2D/OpenGLCompositor.h Thu Jul 18 10:50:59 2019 +0200 @@ -21,6 +21,7 @@ #pragma once +#include "ICompositor.h" #include "Internals/CompositorHelper.h" #include "Internals/OpenGLColorTextureProgram.h" #include "Internals/OpenGLFloatTextureProgram.h" @@ -29,7 +30,9 @@ namespace OrthancStone { - class OpenGLCompositor : private Internals::CompositorHelper::IRendererFactory + class OpenGLCompositor : + public ICompositor, + private Internals::CompositorHelper::IRendererFactory { private: class Font; @@ -54,9 +57,9 @@ OpenGLCompositor(OpenGL::IOpenGLContext& context, const Scene2D& scene); - ~OpenGLCompositor(); + virtual ~OpenGLCompositor(); - void Refresh(); + virtual void Refresh(); void SetFont(size_t index, const GlyphBitmapAlphabet& dict); @@ -68,12 +71,12 @@ Orthanc::Encoding codepage); #endif - unsigned int GetCanvasWidth() const + virtual unsigned int GetCanvasWidth() const { return canvasWidth_; } - unsigned int GetCanvasHeight() const + virtual unsigned int GetCanvasHeight() const { return canvasHeight_; } diff -r ef6e425dc79f -r 64e5f3ff6360 Framework/Scene2DViewport/AngleMeasureTool.cpp --- a/Framework/Scene2DViewport/AngleMeasureTool.cpp Wed Jul 17 15:33:07 2019 +0200 +++ b/Framework/Scene2DViewport/AngleMeasureTool.cpp Thu Jul 18 10:50:59 2019 +0200 @@ -43,7 +43,11 @@ AngleMeasureTool::AngleMeasureTool( MessageBroker& broker, boost::weak_ptr controllerW) : MeasureTool(broker, controllerW) +#if ORTHANC_STONE_ENABLE_OUTLINED_TEXT == 1 , layerHolder_(boost::make_shared(controllerW,1,5)) +#else + , layerHolder_(boost::make_shared(controllerW, 1, 1)) +#endif , angleHighlightArea_(AngleHighlightArea_None) { RefreshScene(); @@ -293,8 +297,13 @@ // http://www.ltg.ed.ac.uk/~richard/utf-8.cgi?input=00B0&mode=hex sprintf(buf, "%0.02f\xc2\xb0", angleDeg); +#if ORTHANC_STONE_ENABLE_OUTLINED_TEXT == 1 SetTextLayerOutlineProperties( - GetController()->GetScene(), layerHolder_, buf, ScenePoint2D(pointX, pointY)); + GetController()->GetScene(), layerHolder_, buf, ScenePoint2D(pointX, pointY), 0); +#else + SetTextLayerProperties( + GetController()->GetScene(), layerHolder_, buf, ScenePoint2D(pointX, pointY) , 0); +#endif #if 0 // TODO:make it togglable diff -r ef6e425dc79f -r 64e5f3ff6360 Framework/Scene2DViewport/LayerHolder.cpp --- a/Framework/Scene2DViewport/LayerHolder.cpp Wed Jul 17 15:33:07 2019 +0200 +++ b/Framework/Scene2DViewport/LayerHolder.cpp Thu Jul 18 10:50:59 2019 +0200 @@ -30,9 +30,11 @@ LayerHolder::LayerHolder( boost::weak_ptr controllerW, int polylineLayerCount, - int textLayerCount) + int textLayerCount, + int infoTextCount) : textLayerCount_(textLayerCount) , polylineLayerCount_(polylineLayerCount) + , infoTextCount_(infoTextCount) , controllerW_(controllerW) , baseLayerIndex_(-1) { diff -r ef6e425dc79f -r 64e5f3ff6360 Framework/Scene2DViewport/LayerHolder.h --- a/Framework/Scene2DViewport/LayerHolder.h Wed Jul 17 15:33:07 2019 +0200 +++ b/Framework/Scene2DViewport/LayerHolder.h Thu Jul 18 10:50:59 2019 +0200 @@ -44,7 +44,7 @@ */ LayerHolder( boost::weak_ptr controllerW, - int polylineLayerCount, int textLayerCount); + int polylineLayerCount, int textLayerCount, int infoTextCount = 0); /** This actually creates the layers @@ -86,13 +86,17 @@ */ TextSceneLayer* GetTextLayer(int index = 0); + //TextSceneLayer* GetTextLayer(int index = 0); + private: int GetPolylineLayerIndex(int index = 0); int GetTextLayerIndex(int index = 0); + int GetInfoTextLayerIndex(int index = 0); Scene2D& GetScene(); int textLayerCount_; int polylineLayerCount_; + int infoTextCount_; boost::weak_ptr controllerW_; int baseLayerIndex_; }; diff -r ef6e425dc79f -r 64e5f3ff6360 Framework/Scene2DViewport/LineMeasureTool.cpp --- a/Framework/Scene2DViewport/LineMeasureTool.cpp Wed Jul 17 15:33:07 2019 +0200 +++ b/Framework/Scene2DViewport/LineMeasureTool.cpp Thu Jul 18 10:50:59 2019 +0200 @@ -33,7 +33,11 @@ LineMeasureTool::LineMeasureTool( MessageBroker& broker, boost::weak_ptr controllerW) : MeasureTool(broker, controllerW) +#if ORTHANC_STONE_ENABLE_OUTLINED_TEXT == 1 , layerHolder_(boost::make_shared(controllerW, 1, 5)) +#else + , layerHolder_(boost::make_shared(controllerW, 1, 1)) +#endif , lineHighlightArea_(LineHighlightArea_None) { @@ -234,8 +238,13 @@ double midX = 0.5 * (end_.GetX() + start_.GetX()); double midY = 0.5 * (end_.GetY() + start_.GetY()); +#if ORTHANC_STONE_ENABLE_OUTLINED_TEXT == 1 SetTextLayerOutlineProperties( - GetController()->GetScene(), layerHolder_, buf, ScenePoint2D(midX, midY)); + GetController()->GetScene(), layerHolder_, buf, ScenePoint2D(midX, midY), 0); +#else + SetTextLayerProperties( + GetController()->GetScene(), layerHolder_, buf, ScenePoint2D(midX, midY), 0); +#endif } } else diff -r ef6e425dc79f -r 64e5f3ff6360 Framework/Scene2DViewport/MeasureToolsToolbox.cpp --- a/Framework/Scene2DViewport/MeasureToolsToolbox.cpp Wed Jul 17 15:33:07 2019 +0200 +++ b/Framework/Scene2DViewport/MeasureToolsToolbox.cpp Thu Jul 18 10:50:59 2019 +0200 @@ -282,6 +282,7 @@ } #endif +#if ORTHANC_STONE_ENABLE_OUTLINED_TEXT == 1 /** This utility function assumes that the layer holder contains 5 text layers and will use the first four ones for the text background and the fifth one @@ -307,7 +308,7 @@ ORTHANC_ASSERT(textLayer != NULL); textLayer->SetText(text); - if (i == 4) + if (i == startingLayerIndex + 4) { textLayer->SetColor(TEXT_COLOR_RED, TEXT_COLOR_GREEN, @@ -321,11 +322,35 @@ } ScenePoint2D textAnchor; + int offIndex = i - startingLayerIndex; + ORTHANC_ASSERT(offIndex >= 0 && offIndex < 5); textLayer->SetPosition( - p.GetX() + xoffsets[i] * pixelToScene, - p.GetY() + yoffsets[i] * pixelToScene); + p.GetX() + xoffsets[offIndex] * pixelToScene, + p.GetY() + yoffsets[offIndex] * pixelToScene); } } +#else + void SetTextLayerProperties( + Scene2D& scene + , boost::shared_ptr layerHolder + , const char* text + , ScenePoint2D p + , int layerIndex) + { + // get the scaling factor + const double pixelToScene = + scene.GetCanvasToSceneTransform().ComputeZoom(); + + TextSceneLayer* textLayer = layerHolder->GetTextLayer(layerIndex); + ORTHANC_ASSERT(textLayer != NULL); + textLayer->SetText(text); + + textLayer->SetColor(TEXT_COLOR_RED, TEXT_COLOR_GREEN, TEXT_COLOR_BLUE); + + ScenePoint2D textAnchor; + textLayer->SetPosition(p.GetX(), p.GetY()); + } +#endif std::ostream& operator<<(std::ostream& os, const ScenePoint2D& p) { diff -r ef6e425dc79f -r 64e5f3ff6360 Framework/Scene2DViewport/MeasureToolsToolbox.h --- a/Framework/Scene2DViewport/MeasureToolsToolbox.h Wed Jul 17 15:33:07 2019 +0200 +++ b/Framework/Scene2DViewport/MeasureToolsToolbox.h Thu Jul 18 10:50:59 2019 +0200 @@ -170,6 +170,7 @@ , const double d); +#if ORTHANC_STONE_ENABLE_OUTLINED_TEXT == 1 /** This helper is used when drawing text with an outline. It set the properties for several text layers at once : first the @@ -177,14 +178,22 @@ layer. The five text layers are supposed to already exist in the scene, starting - from layerIndex, up to (and not including) layerIndex+5. + from startingLayerIndex, up to (and not including) startingLayerIndex+5. */ void SetTextLayerOutlineProperties( Scene2D& scene , boost::shared_ptr layerHolder , const char* text , ScenePoint2D p - , int startingLayerIndex = 0); + , int startingLayerIndex); +#else + void SetTextLayerProperties( + Scene2D& scene + , boost::shared_ptr layerHolder + , const char* text + , ScenePoint2D p + , int layerIndex); +#endif std::ostream& operator<<(std::ostream& os, const ScenePoint2D& p); } diff -r ef6e425dc79f -r 64e5f3ff6360 Framework/Scene2DViewport/ViewportController.cpp --- a/Framework/Scene2DViewport/ViewportController.cpp Wed Jul 17 15:33:07 2019 +0200 +++ b/Framework/Scene2DViewport/ViewportController.cpp Thu Jul 18 10:50:59 2019 +0200 @@ -51,27 +51,59 @@ void ViewportController::PushCommand(boost::shared_ptr command) { - GetUndoStack()->PushCommand(command); + boost::shared_ptr undoStack = undoStackW_.lock(); + if(undoStack.get() != NULL) + undoStack->PushCommand(command); + else + { + LOG(ERROR) << "Internal error: no undo stack in the viewport controller!"; + } } void ViewportController::Undo() { - GetUndoStack()->Undo(); + boost::shared_ptr undoStack = undoStackW_.lock(); + if (undoStack.get() != NULL) + undoStack->Undo(); + else + { + LOG(ERROR) << "Internal error: no undo stack in the viewport controller!"; + } } void ViewportController::Redo() { - GetUndoStack()->Redo(); + boost::shared_ptr undoStack = undoStackW_.lock(); + if (undoStack.get() != NULL) + undoStack->Redo(); + else + { + LOG(ERROR) << "Internal error: no undo stack in the viewport controller!"; + } } bool ViewportController::CanUndo() const { - return GetUndoStack()->CanUndo(); + boost::shared_ptr undoStack = undoStackW_.lock(); + if (undoStack.get() != NULL) + return undoStack->CanUndo(); + else + { + LOG(ERROR) << "Internal error: no undo stack in the viewport controller!"; + return false; + } } bool ViewportController::CanRedo() const { - return GetUndoStack()->CanRedo(); + boost::shared_ptr undoStack = undoStackW_.lock(); + if (undoStack.get() != NULL) + return undoStack->CanRedo(); + else + { + LOG(ERROR) << "Internal error: no undo stack in the viewport controller!"; + return false; + } } bool ViewportController::HandlePointerEvent(PointerEvent e) diff -r ef6e425dc79f -r 64e5f3ff6360 Framework/Viewport/IViewport.h --- a/Framework/Viewport/IViewport.h Wed Jul 17 15:33:07 2019 +0200 +++ b/Framework/Viewport/IViewport.h Thu Jul 18 10:50:59 2019 +0200 @@ -20,6 +20,7 @@ #pragma once +#include "../Scene2D/ICompositor.h" #include "../Scene2D/Scene2D.h" #include "../Scene2D/ScenePoint2D.h" @@ -48,5 +49,13 @@ virtual const std::string& GetCanvasIdentifier() const = 0; virtual ScenePoint2D GetPixelCenterCoordinates(int x, int y) const = 0; + + virtual ICompositor& GetCompositor() = 0; + + virtual const ICompositor& GetCompositor() const + { + IViewport* self = const_cast(this); + return self->GetCompositor(); + } }; } diff -r ef6e425dc79f -r 64e5f3ff6360 Framework/Viewport/SdlViewport.cpp --- a/Framework/Viewport/SdlViewport.cpp Wed Jul 17 15:33:07 2019 +0200 +++ b/Framework/Viewport/SdlViewport.cpp Thu Jul 18 10:50:59 2019 +0200 @@ -26,24 +26,78 @@ namespace OrthancStone { - SdlViewport::SdlViewport(const char* title, - unsigned int width, - unsigned int height, - bool allowDpiScaling) : - ViewportBase(title), + SdlOpenGLViewport::SdlOpenGLViewport(const char* title, + unsigned int width, + unsigned int height, + bool allowDpiScaling) : + SdlViewport(title), + context_(title, width, height, allowDpiScaling), + compositor_(context_, GetScene()) + { + } + + SdlOpenGLViewport::SdlOpenGLViewport(const char* title, + unsigned int width, + unsigned int height, + boost::shared_ptr& scene, + bool allowDpiScaling) : + SdlViewport(title, scene), context_(title, width, height, allowDpiScaling), compositor_(context_, GetScene()) { } - SdlViewport::SdlViewport(const char* title, - unsigned int width, - unsigned int height, - boost::shared_ptr& scene, - bool allowDpiScaling) : - ViewportBase(title, scene), - context_(title, width, height, allowDpiScaling), - compositor_(context_, GetScene()) + + SdlCairoViewport::SdlCairoViewport(const char* title, + unsigned int width, + unsigned int height, + bool allowDpiScaling) : + SdlViewport(title), + window_(title, width, height, false /* enable OpenGL */, allowDpiScaling), + compositor_(GetScene(), width, height) + { + UpdateSdlSurfaceSize(width, height); + } + + + SdlCairoViewport::~SdlCairoViewport() + { + if (sdlSurface_) + { + SDL_FreeSurface(sdlSurface_); + } + } + + + void SdlCairoViewport::Refresh() { + GetCompositor().Refresh(); + window_.Render(sdlSurface_); } + + void SdlCairoViewport::UpdateSize(unsigned int width, + unsigned int height) + { + compositor_.UpdateSize(width, height); + UpdateSdlSurfaceSize(width, height); + Refresh(); + } + + + void SdlCairoViewport::UpdateSdlSurfaceSize(unsigned int width, + unsigned int height) + { + static const uint32_t rmask = 0x00ff0000; + static const uint32_t gmask = 0x0000ff00; + static const uint32_t bmask = 0x000000ff; + + sdlSurface_ = SDL_CreateRGBSurfaceFrom((void*)(compositor_.GetCanvas().GetBuffer()), width, height, 32, + compositor_.GetCanvas().GetPitch(), rmask, gmask, bmask, 0); + if (!sdlSurface_) + { + LOG(ERROR) << "Cannot create a SDL surface from a Cairo surface"; + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + } + } diff -r ef6e425dc79f -r 64e5f3ff6360 Framework/Viewport/SdlViewport.h --- a/Framework/Viewport/SdlViewport.h Wed Jul 17 15:33:07 2019 +0200 +++ b/Framework/Viewport/SdlViewport.h Thu Jul 18 10:50:59 2019 +0200 @@ -38,51 +38,106 @@ #include "../../Applications/Sdl/SdlOpenGLContext.h" #include "../Scene2D/OpenGLCompositor.h" +#include "../Scene2D/CairoCompositor.h" #include "ViewportBase.h" namespace OrthancStone { class SdlViewport : public ViewportBase { + public: + SdlViewport(const std::string& identifier) + : ViewportBase(identifier) + {} + + SdlViewport(const std::string& identifier, + boost::shared_ptr& scene) + : ViewportBase(identifier, scene) + { + + } + + virtual SdlWindow& GetWindow() = 0; + + virtual void UpdateSize(unsigned int width, + unsigned int height) = 0; + }; + + class SdlOpenGLViewport : public SdlViewport + { private: SdlOpenGLContext context_; OpenGLCompositor compositor_; public: - SdlViewport(const char* title, - unsigned int width, - unsigned int height, - bool allowDpiScaling = true); - - SdlViewport(const char* title, - unsigned int width, - unsigned int height, - boost::shared_ptr& scene, - bool allowDpiScaling = true); + SdlOpenGLViewport(const char* title, + unsigned int width, + unsigned int height, + bool allowDpiScaling = true); - virtual void Refresh() - { - compositor_.Refresh(); - } + SdlOpenGLViewport(const char* title, + unsigned int width, + unsigned int height, + boost::shared_ptr& scene, + bool allowDpiScaling = true); - virtual unsigned int GetCanvasWidth() const - { - return compositor_.GetCanvasWidth(); - } - virtual unsigned int GetCanvasHeight() const - { - return compositor_.GetCanvasHeight(); - } - - OpenGLCompositor& GetCompositor() + virtual ICompositor& GetCompositor() { return compositor_; } - SdlOpenGLContext& GetContext() + virtual SdlWindow& GetWindow() { - return context_; + return context_.GetWindow(); + } + + virtual void UpdateSize(unsigned int width, + unsigned int height) + { + // nothing to do in OpenGL, the OpenGLCompositor::UpdateSize will be called automatically } }; + + + class SdlCairoViewport : public SdlViewport + { + private: + SdlWindow window_; + CairoCompositor compositor_; + SDL_Surface* sdlSurface_; + + public: + SdlCairoViewport(const char* title, + unsigned int width, + unsigned int height, + bool allowDpiScaling = true); + + SdlCairoViewport(const char* title, + unsigned int width, + unsigned int height, + boost::shared_ptr& scene, + bool allowDpiScaling = true); + + ~SdlCairoViewport(); + + virtual ICompositor& GetCompositor() + { + return compositor_; + } + + virtual SdlWindow& GetWindow() + { + return window_; + } + + virtual void Refresh(); + + virtual void UpdateSize(unsigned int width, + unsigned int height); + + private: + void UpdateSdlSurfaceSize(unsigned int width, + unsigned int height); + }; } diff -r ef6e425dc79f -r 64e5f3ff6360 Framework/Viewport/ViewportBase.h --- a/Framework/Viewport/ViewportBase.h Wed Jul 17 15:33:07 2019 +0200 +++ b/Framework/Viewport/ViewportBase.h Thu Jul 18 10:50:59 2019 +0200 @@ -49,5 +49,21 @@ } virtual ScenePoint2D GetPixelCenterCoordinates(int x, int y) const; + + virtual void Refresh() + { + GetCompositor().Refresh(); + } + + virtual unsigned int GetCanvasWidth() const + { + return GetCompositor().GetCanvasWidth(); + } + + virtual unsigned int GetCanvasHeight() const + { + return GetCompositor().GetCanvasHeight(); + } + }; } diff -r ef6e425dc79f -r 64e5f3ff6360 Framework/Viewport/WebAssemblyViewport.cpp --- a/Framework/Viewport/WebAssemblyViewport.cpp Wed Jul 17 15:33:07 2019 +0200 +++ b/Framework/Viewport/WebAssemblyViewport.cpp Thu Jul 18 10:50:59 2019 +0200 @@ -20,29 +20,84 @@ #include "WebAssemblyViewport.h" +#include namespace OrthancStone { - WebAssemblyViewport::WebAssemblyViewport(const std::string& canvas) : - ViewportBase(canvas), + WebAssemblyOpenGLViewport::WebAssemblyOpenGLViewport(const std::string& canvas) : + WebAssemblyViewport(canvas), context_(canvas), compositor_(context_, GetScene()) { } - WebAssemblyViewport::WebAssemblyViewport(const std::string& canvas, - boost::shared_ptr& scene) : - ViewportBase(canvas, scene), + WebAssemblyOpenGLViewport::WebAssemblyOpenGLViewport(const std::string& canvas, + boost::shared_ptr& scene) : + WebAssemblyViewport(canvas, scene), context_(canvas), compositor_(context_, GetScene()) { } - void WebAssemblyViewport::UpdateSize() + void WebAssemblyOpenGLViewport::UpdateSize() { context_.UpdateSize(); // First read the size of the canvas compositor_.Refresh(); // Then refresh the content of the canvas } + + + WebAssemblyCairoViewport::WebAssemblyCairoViewport(const std::string& canvas) : + WebAssemblyViewport(canvas), + canvas_(canvas), + compositor_(GetScene(), 1024, 768) + { + } + + + WebAssemblyCairoViewport::WebAssemblyCairoViewport(const std::string& canvas, + boost::shared_ptr& scene) : + WebAssemblyViewport(canvas, scene), + canvas_(canvas), + compositor_(GetScene(), 1024, 768) + { + } + + + void WebAssemblyCairoViewport::UpdateSize() + { + LOG(INFO) << "updating cairo viewport size"; + double w, h; + emscripten_get_element_css_size(canvas_.c_str(), &w, &h); + + /** + * Emscripten has the function emscripten_get_element_css_size() + * to query the width and height of a named HTML element. I'm + * calling this first to get the initial size of the canvas DOM + * element, and then call emscripten_set_canvas_size() to + * initialize the framebuffer size of the canvas to the same + * size as its DOM element. + * https://floooh.github.io/2017/02/22/emsc-html.html + **/ + unsigned int canvasWidth = 0; + unsigned int canvasHeight = 0; + + if (w > 0 || + h > 0) + { + canvasWidth = static_cast(boost::math::iround(w)); + canvasHeight = static_cast(boost::math::iround(h)); + } + + emscripten_set_canvas_element_size(canvas_.c_str(), canvasWidth, canvasHeight); + compositor_.UpdateSize(canvasWidth, canvasHeight); + } + + void WebAssemblyCairoViewport::Refresh() + { + LOG(INFO) << "refreshing cairo viewport, TODO: blit to the canvans.getContext('2d')"; + GetCompositor().Refresh(); + } + } diff -r ef6e425dc79f -r 64e5f3ff6360 Framework/Viewport/WebAssemblyViewport.h --- a/Framework/Viewport/WebAssemblyViewport.h Wed Jul 17 15:33:07 2019 +0200 +++ b/Framework/Viewport/WebAssemblyViewport.h Thu Jul 18 10:50:59 2019 +0200 @@ -23,43 +23,67 @@ #include "../OpenGL/WebAssemblyOpenGLContext.h" #include "../Scene2D/OpenGLCompositor.h" +#include "../Scene2D/CairoCompositor.h" #include "ViewportBase.h" namespace OrthancStone { class WebAssemblyViewport : public ViewportBase { + public: + WebAssemblyViewport(const std::string& identifier) + : ViewportBase(identifier) + { + } + + WebAssemblyViewport(const std::string& identifier, + boost::shared_ptr& scene) + : ViewportBase(identifier, scene) + { + } + }; + + class WebAssemblyOpenGLViewport : public WebAssemblyViewport + { private: OpenGL::WebAssemblyOpenGLContext context_; OpenGLCompositor compositor_; public: - WebAssemblyViewport(const std::string& canvas); - - WebAssemblyViewport(const std::string& canvas, - boost::shared_ptr& scene); + WebAssemblyOpenGLViewport(const std::string& canvas); - virtual void Refresh() - { - compositor_.Refresh(); - } - - virtual unsigned int GetCanvasWidth() const - { - return context_.GetCanvasWidth(); - } - - virtual unsigned int GetCanvasHeight() const - { - return context_.GetCanvasHeight(); - } - + WebAssemblyOpenGLViewport(const std::string& canvas, + boost::shared_ptr& scene); + // This function must be called each time the browser window is resized void UpdateSize(); - OpenGLCompositor& GetCompositor() + virtual ICompositor& GetCompositor() { return compositor_; } }; + + class WebAssemblyCairoViewport : public WebAssemblyViewport + { + private: + CairoCompositor compositor_; + std::string canvas_; + + public: + WebAssemblyCairoViewport(const std::string& canvas); + + WebAssemblyCairoViewport(const std::string& canvas, + boost::shared_ptr& scene); + + void UpdateSize(); + + virtual void Refresh(); + + virtual ICompositor& GetCompositor() + { + return compositor_; + } + }; + } diff -r ef6e425dc79f -r 64e5f3ff6360 Resources/CMake/OrthancStoneConfiguration.cmake --- a/Resources/CMake/OrthancStoneConfiguration.cmake Wed Jul 17 15:33:07 2019 +0200 +++ b/Resources/CMake/OrthancStoneConfiguration.cmake Thu Jul 18 10:50:59 2019 +0200 @@ -444,6 +444,7 @@ ${ORTHANC_STONE_ROOT}/Framework/Scene2D/ColorTextureSceneLayer.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/FloatTextureSceneLayer.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/GrayscaleStyleConfigurator.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2D/ICompositor.h ${ORTHANC_STONE_ROOT}/Framework/Scene2D/InfoPanelSceneLayer.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/Internals/CairoColorTextureRenderer.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/Internals/CairoFloatTextureRenderer.cpp diff -r ef6e425dc79f -r 64e5f3ff6360 Samples/Sdl/BasicScene.cpp --- a/Samples/Sdl/BasicScene.cpp Wed Jul 17 15:33:07 2019 +0200 +++ b/Samples/Sdl/BasicScene.cpp Thu Jul 18 10:50:59 2019 +0200 @@ -48,6 +48,7 @@ static const unsigned int FONT_SIZE = 32; static const int LAYER_POSITION = 150; +#define OPENGL_ENABLED 0 void PrepareScene(OrthancStone::Scene2D& scene) { @@ -259,7 +260,7 @@ } } - +#if OPENGL_ENABLED==1 static void GLAPIENTRY OpenGLMessageCallback(GLenum source, GLenum type, @@ -276,7 +277,7 @@ type, severity, message ); } } - +#endif void Run(OrthancStone::MessageBroker& broker, OrthancStone::SdlViewport& viewport) @@ -286,8 +287,10 @@ boost::shared_ptr controller( new ViewportController(boost::make_shared(), broker, viewport)); +#if OPENGL_ENABLED==1 glEnable(GL_DEBUG_OUTPUT); glDebugMessageCallback(OpenGLMessageCallback, 0); +#endif boost::shared_ptr tracker; @@ -334,6 +337,7 @@ { case SDL_WINDOWEVENT_SIZE_CHANGED: tracker.reset(); + viewport.UpdateSize(event.window.data1, event.window.data2); break; case SDL_WINDOWEVENT_SHOWN: @@ -356,7 +360,7 @@ switch (event.key.keysym.sym) { case SDLK_f: - viewport.GetContext().GetWindow().ToggleMaximize(); + viewport.GetWindow().ToggleMaximize(); break; case SDLK_q: @@ -390,7 +394,11 @@ try { - OrthancStone::SdlViewport viewport("Hello", 1024, 768); +#if OPENGL_ENABLED==1 + OrthancStone::SdlOpenGLViewport viewport("Hello", 1024, 768); +#else + OrthancStone::SdlCairoViewport viewport("Hello", 1024, 768); +#endif PrepareScene(viewport.GetScene()); viewport.GetCompositor().SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, diff -r ef6e425dc79f -r 64e5f3ff6360 Samples/WebAssembly/NOTES.txt --- a/Samples/WebAssembly/NOTES.txt Wed Jul 17 15:33:07 2019 +0200 +++ b/Samples/WebAssembly/NOTES.txt Thu Jul 18 10:50:59 2019 +0200 @@ -74,4 +74,3 @@ cd build_stone_newsamples_wasm_wsl cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=${EMSDK}/fastcomp/emscripten/cmake/Modules/Platform/Emscripten.cmake -DORTHANC_FRAMEWORK_SOURCE=path -DORTHANC_FRAMEWORK_ROOT=/mnt/c/o/orthanc/ -DCMAKE_BUILD_TYPE=Release -DALLOW_DOWNLOADS=ON /mnt/c/o/orthanc-stone/Samples/WebAssembly -DCMAKE_INSTALL_PREFIX=/mnt/c/o/build_install_stone_newsamples_wasm_wsl ninja -