# HG changeset patch # User Alain Mazy # Date 1563273449 -7200 # Node ID 9c2f6d6b9f4a23989a27ec2887f72bed7792ce76 # Parent 875bd6aca5e613b1b3d7b6d3dc4bb6e88ca12450# Parent 50cd372e24608316a94d18b1b0ada71aa8e58f29 Merge diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Applications/Sdl/SdlOpenGLContext.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Sdl/SdlOpenGLContext.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -0,0 +1,122 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * 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 . + **/ + + +#include "SdlOpenGLContext.h" + +#if ORTHANC_ENABLE_SDL == 1 + +#if !defined(ORTHANC_ENABLE_GLEW) +# error Macro ORTHANC_ENABLE_GLEW must be defined +#endif + +#if ORTHANC_ENABLE_GLEW == 1 +# include +#endif + +#include + +namespace OrthancStone +{ + SdlOpenGLContext::SdlOpenGLContext(const char* title, + unsigned int width, + unsigned int height, + bool allowDpiScaling) : + window_(title, width, height, true /* enable OpenGL */, allowDpiScaling) + { + context_ = SDL_GL_CreateContext(window_.GetObject()); + + if (context_ == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, + "Cannot initialize OpenGL"); + } + +#if ORTHANC_ENABLE_GLEW == 1 + // The initialization function of glew (i.e. "glewInit()") can + // only be called once an OpenGL is setup. + // https://stackoverflow.com/a/45033669/881731 + { + static boost::mutex mutex_; + static bool isGlewInitialized_ = false; + + boost::mutex::scoped_lock lock(mutex_); + + if (!isGlewInitialized_) + { + LOG(INFO) << "Initializing glew"; + + GLenum err = glewInit(); + if (GLEW_OK != err) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, + "Cannot initialize glew"); + } + + isGlewInitialized_ = true; + } + } +#endif + } + + + SdlOpenGLContext::~SdlOpenGLContext() + { + SDL_GL_DeleteContext(context_); + } + + + void SdlOpenGLContext::MakeCurrent() + { + if (SDL_GL_MakeCurrent(window_.GetObject(), context_) != 0) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, + "Cannot set current OpenGL context"); + } + + // This makes our buffer swap syncronized with the monitor's vertical refresh + SDL_GL_SetSwapInterval(1); + } + + + void SdlOpenGLContext::SwapBuffer() + { + // Swap our buffer to display the current contents of buffer on screen + SDL_GL_SwapWindow(window_.GetObject()); + } + + + unsigned int SdlOpenGLContext::GetCanvasWidth() const + { + int w = 0; + SDL_GL_GetDrawableSize(window_.GetObject(), &w, NULL); + return static_cast(w); + } + + + unsigned int SdlOpenGLContext::GetCanvasHeight() const + { + int h = 0; + SDL_GL_GetDrawableSize(window_.GetObject(), NULL, &h); + return static_cast(h); + } +} + +#endif diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Applications/Sdl/SdlOpenGLContext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Sdl/SdlOpenGLContext.h Tue Jul 16 12:37:29 2019 +0200 @@ -0,0 +1,60 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * 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 . + **/ + + +#pragma once + +#if ORTHANC_ENABLE_SDL == 1 + +#include "../../Framework/OpenGL/IOpenGLContext.h" +#include "SdlWindow.h" + +namespace OrthancStone +{ + class SdlOpenGLContext : public OpenGL::IOpenGLContext + { + private: + SdlWindow window_; + SDL_GLContext context_; + + public: + SdlOpenGLContext(const char* title, + unsigned int width, + unsigned int height, + bool allowDpiScaling = true); + + ~SdlOpenGLContext(); + + SdlWindow& GetWindow() + { + return window_; + } + + virtual void MakeCurrent(); + + virtual void SwapBuffer(); + + virtual unsigned int GetCanvasWidth() const; + + virtual unsigned int GetCanvasHeight() const; + }; +} + +#endif diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Applications/Sdl/SdlOpenGLWindow.cpp --- a/Applications/Sdl/SdlOpenGLWindow.cpp Fri Jul 12 14:57:48 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,122 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2019 Osimis S.A., Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License - * as published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * 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 . - **/ - - -#include "SdlOpenGLWindow.h" - -#if ORTHANC_ENABLE_SDL == 1 - -#if !defined(ORTHANC_ENABLE_GLEW) -# error Macro ORTHANC_ENABLE_GLEW must be defined -#endif - -#if ORTHANC_ENABLE_GLEW == 1 -# include -#endif - -#include - -namespace OrthancStone -{ - SdlOpenGLWindow::SdlOpenGLWindow(const char* title, - unsigned int width, - unsigned int height, - bool allowDpiScaling) : - window_(title, width, height, true /* enable OpenGL */, allowDpiScaling) - { - context_ = SDL_GL_CreateContext(window_.GetObject()); - - if (context_ == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, - "Cannot initialize OpenGL"); - } - -#if ORTHANC_ENABLE_GLEW == 1 - // The initialization function of glew (i.e. "glewInit()") can - // only be called once an OpenGL is setup. - // https://stackoverflow.com/a/45033669/881731 - { - static boost::mutex mutex_; - static bool isGlewInitialized_ = false; - - boost::mutex::scoped_lock lock(mutex_); - - if (!isGlewInitialized_) - { - LOG(INFO) << "Initializing glew"; - - GLenum err = glewInit(); - if (GLEW_OK != err) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, - "Cannot initialize glew"); - } - - isGlewInitialized_ = true; - } - } -#endif - } - - - SdlOpenGLWindow::~SdlOpenGLWindow() - { - SDL_GL_DeleteContext(context_); - } - - - void SdlOpenGLWindow::MakeCurrent() - { - if (SDL_GL_MakeCurrent(window_.GetObject(), context_) != 0) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, - "Cannot set current OpenGL context"); - } - - // This makes our buffer swap syncronized with the monitor's vertical refresh - SDL_GL_SetSwapInterval(1); - } - - - void SdlOpenGLWindow::SwapBuffer() - { - // Swap our buffer to display the current contents of buffer on screen - SDL_GL_SwapWindow(window_.GetObject()); - } - - - unsigned int SdlOpenGLWindow::GetCanvasWidth() const - { - int w = 0; - SDL_GL_GetDrawableSize(window_.GetObject(), &w, NULL); - return static_cast(w); - } - - - unsigned int SdlOpenGLWindow::GetCanvasHeight() const - { - int h = 0; - SDL_GL_GetDrawableSize(window_.GetObject(), NULL, &h); - return static_cast(h); - } -} - -#endif diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Applications/Sdl/SdlOpenGLWindow.h --- a/Applications/Sdl/SdlOpenGLWindow.h Fri Jul 12 14:57:48 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2019 Osimis S.A., Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License - * as published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * 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 . - **/ - - -#pragma once - -#if ORTHANC_ENABLE_SDL == 1 - -#include "../../Framework/OpenGL/IOpenGLContext.h" -#include "SdlWindow.h" - -namespace OrthancStone -{ - class SdlOpenGLWindow : public OpenGL::IOpenGLContext - { - private: - SdlWindow window_; - SDL_GLContext context_; - - public: - SdlOpenGLWindow(const char* title, - unsigned int width, - unsigned int height, - bool allowDpiScaling = true); - - ~SdlOpenGLWindow(); - - SdlWindow& GetWindow() - { - return window_; - } - - virtual void MakeCurrent(); - - virtual void SwapBuffer(); - - virtual unsigned int GetCanvasWidth() const; - - virtual unsigned int GetCanvasHeight() const; - }; -} - -#endif diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/OpenGL/WebAssemblyOpenGLContext.cpp --- a/Framework/OpenGL/WebAssemblyOpenGLContext.cpp Fri Jul 12 14:57:48 2019 +0200 +++ b/Framework/OpenGL/WebAssemblyOpenGLContext.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -21,8 +21,6 @@ #include "WebAssemblyOpenGLContext.h" -#if ORTHANC_ENABLE_WASM == 1 - #include #include @@ -175,5 +173,3 @@ } } } - -#endif diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/OpenGL/WebAssemblyOpenGLContext.h --- a/Framework/OpenGL/WebAssemblyOpenGLContext.h Fri Jul 12 14:57:48 2019 +0200 +++ b/Framework/OpenGL/WebAssemblyOpenGLContext.h Tue Jul 16 12:37:29 2019 +0200 @@ -25,7 +25,17 @@ # error Macro ORTHANC_ENABLE_WASM must be defined #endif -#if ORTHANC_ENABLE_WASM == 1 +#if ORTHANC_ENABLE_WASM != 1 +# error This file can only be used if targeting WebAssembly +#endif + +#if !defined(ORTHANC_ENABLE_OPENGL) +# error The macro ORTHANC_ENABLE_OPENGL must be defined +#endif + +#if ORTHANC_ENABLE_OPENGL != 1 +# error Support for OpenGL is disabled +#endif #include "IOpenGLContext.h" @@ -58,5 +68,3 @@ }; } } - -#endif diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Scene2D/OpenGLCompositor.cpp --- a/Framework/Scene2D/OpenGLCompositor.cpp Fri Jul 12 14:57:48 2019 +0200 +++ b/Framework/Scene2D/OpenGLCompositor.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -134,7 +134,6 @@ canvasWidth_(0), canvasHeight_(0) { - UpdateSize(); } @@ -148,20 +147,14 @@ } - void OpenGLCompositor::UpdateSize() - { - canvasWidth_ = context_.GetCanvasWidth(); - canvasHeight_ = context_.GetCanvasHeight(); - - context_.MakeCurrent(); - glViewport(0, 0, canvasWidth_, canvasHeight_); - } - - void OpenGLCompositor::Refresh() { context_.MakeCurrent(); + canvasWidth_ = context_.GetCanvasWidth(); + canvasHeight_ = context_.GetCanvasHeight(); + + glViewport(0, 0, canvasWidth_, canvasHeight_); glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); @@ -174,6 +167,8 @@ void OpenGLCompositor::SetFont(size_t index, const GlyphBitmapAlphabet& dict) { + context_.MakeCurrent(); + std::auto_ptr font(new Font(dict)); Fonts::iterator found = fonts_.find(index); diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Scene2D/OpenGLCompositor.h --- a/Framework/Scene2D/OpenGLCompositor.h Fri Jul 12 14:57:48 2019 +0200 +++ b/Framework/Scene2D/OpenGLCompositor.h Tue Jul 16 12:37:29 2019 +0200 @@ -29,9 +29,7 @@ namespace OrthancStone { - class OpenGLCompositor : - public ICompositor, - private Internals::CompositorHelper::IRendererFactory + class OpenGLCompositor : private Internals::CompositorHelper::IRendererFactory { private: class Font; @@ -58,9 +56,7 @@ ~OpenGLCompositor(); - void UpdateSize(); - - virtual void Refresh(); + void Refresh(); void SetFont(size_t index, const GlyphBitmapAlphabet& dict); @@ -72,12 +68,12 @@ Orthanc::Encoding codepage); #endif - virtual unsigned int GetCanvasWidth() const + unsigned int GetCanvasWidth() const { return canvasWidth_; } - virtual unsigned int GetCanvasHeight() const + unsigned int GetCanvasHeight() const { return canvasHeight_; } diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Scene2DViewport/AngleMeasureTool.cpp --- a/Framework/Scene2DViewport/AngleMeasureTool.cpp Fri Jul 12 14:57:48 2019 +0200 +++ b/Framework/Scene2DViewport/AngleMeasureTool.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -120,7 +120,7 @@ AngleMeasureTool::AngleHighlightArea AngleMeasureTool::AngleHitTest(ScenePoint2D p) const { const double pixelToScene = - GetScene()->GetCanvasToSceneTransform().ComputeZoom(); + GetController()->GetScene().GetCanvasToSceneTransform().ComputeZoom(); const double SQUARED_HIT_TEST_MAX_DISTANCE_SCENE_COORD = pixelToScene * HIT_TEST_MAX_DISTANCE_CANVAS_COORD * pixelToScene * HIT_TEST_MAX_DISTANCE_CANVAS_COORD; { @@ -165,7 +165,7 @@ boost::shared_ptr AngleMeasureTool::CreateEditionTracker(const PointerEvent& e) { ScenePoint2D scenePos = e.GetMainPosition().Apply( - GetScene()->GetCanvasToSceneTransform()); + GetController()->GetScene().GetCanvasToSceneTransform()); if (!HitTest(scenePos)) return boost::shared_ptr(); @@ -233,7 +233,7 @@ { PolylineSceneLayer::Chain chain; //TODO: take DPI into account - AddSquare(chain, GetScene(), side1End_, + AddSquare(chain, GetController()->GetScene(), side1End_, GetController()->GetHandleSideLengthS()); if (angleHighlightArea_ == AngleHighlightArea_Side1End) @@ -245,7 +245,7 @@ { PolylineSceneLayer::Chain chain; //TODO: take DPI into account - AddSquare(chain, GetScene(), side2End_, + AddSquare(chain, GetController()->GetScene(), side2End_, GetController()->GetHandleSideLengthS()); if (angleHighlightArea_ == AngleHighlightArea_Side2End) @@ -294,7 +294,7 @@ sprintf(buf, "%0.02f\xc2\xb0", angleDeg); SetTextLayerOutlineProperties( - GetScene(), layerHolder_, buf, ScenePoint2D(pointX, pointY)); + GetController()->GetScene(), layerHolder_, buf, ScenePoint2D(pointX, pointY)); #if 0 // TODO:make it togglable diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Scene2DViewport/CreateAngleMeasureTracker.cpp --- a/Framework/Scene2DViewport/CreateAngleMeasureTracker.cpp Fri Jul 12 14:57:48 2019 +0200 +++ b/Framework/Scene2DViewport/CreateAngleMeasureTracker.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -34,7 +34,7 @@ new CreateAngleMeasureCommand( broker, controllerW, - e.GetMainPosition().Apply(GetScene()->GetCanvasToSceneTransform()))); + e.GetMainPosition().Apply(GetScene().GetCanvasToSceneTransform()))); } CreateAngleMeasureTracker::~CreateAngleMeasureTracker() @@ -43,8 +43,6 @@ void CreateAngleMeasureTracker::PointerMove(const PointerEvent& event) { - assert(GetScene()); - if (!alive_) { throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, @@ -53,7 +51,7 @@ } ScenePoint2D scenePos = event.GetMainPosition().Apply( - GetScene()->GetCanvasToSceneTransform()); + GetScene().GetCanvasToSceneTransform()); switch (state_) { diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Scene2DViewport/CreateLineMeasureTracker.cpp --- a/Framework/Scene2DViewport/CreateLineMeasureTracker.cpp Fri Jul 12 14:57:48 2019 +0200 +++ b/Framework/Scene2DViewport/CreateLineMeasureTracker.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -33,7 +33,7 @@ new CreateLineMeasureCommand( broker, controllerW, - e.GetMainPosition().Apply(GetScene()->GetCanvasToSceneTransform()))); + e.GetMainPosition().Apply(GetScene().GetCanvasToSceneTransform()))); } CreateLineMeasureTracker::~CreateLineMeasureTracker() @@ -43,8 +43,6 @@ void CreateLineMeasureTracker::PointerMove(const PointerEvent& event) { - assert(GetScene()); - if (!alive_) { throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, @@ -53,7 +51,7 @@ } ScenePoint2D scenePos = event.GetMainPosition().Apply( - GetScene()->GetCanvasToSceneTransform()); + GetScene().GetCanvasToSceneTransform()); //LOG(TRACE) << "scenePos.GetX() = " << scenePos.GetX() << " " << // "scenePos.GetY() = " << scenePos.GetY(); diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Scene2DViewport/EditAngleMeasureTracker.cpp --- a/Framework/Scene2DViewport/EditAngleMeasureTracker.cpp Fri Jul 12 14:57:48 2019 +0200 +++ b/Framework/Scene2DViewport/EditAngleMeasureTracker.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -30,7 +30,7 @@ : EditMeasureTracker(controllerW, e) { ScenePoint2D scenePos = e.GetMainPosition().Apply( - GetScene()->GetCanvasToSceneTransform()); + GetScene().GetCanvasToSceneTransform()); modifiedZone_ = measureTool->AngleHitTest(scenePos); @@ -45,7 +45,7 @@ void EditAngleMeasureTracker::PointerMove(const PointerEvent& e) { ScenePoint2D scenePos = e.GetMainPosition().Apply( - GetScene()->GetCanvasToSceneTransform()); + GetScene().GetCanvasToSceneTransform()); ScenePoint2D delta = scenePos - GetOriginalClickPosition(); diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Scene2DViewport/EditLineMeasureTracker.cpp --- a/Framework/Scene2DViewport/EditLineMeasureTracker.cpp Fri Jul 12 14:57:48 2019 +0200 +++ b/Framework/Scene2DViewport/EditLineMeasureTracker.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -21,16 +21,16 @@ #include "EditLineMeasureTracker.h" namespace OrthancStone -{ +{ EditLineMeasureTracker::EditLineMeasureTracker( boost::shared_ptr measureTool, MessageBroker& broker, boost::weak_ptr controllerW, - const PointerEvent& e) + const PointerEvent& e) : EditMeasureTracker(controllerW, e) - { + { ScenePoint2D scenePos = e.GetMainPosition().Apply( - GetScene()->GetCanvasToSceneTransform()); + GetScene().GetCanvasToSceneTransform()); modifiedZone_ = measureTool->LineHitTest(scenePos); @@ -39,7 +39,7 @@ measureTool, broker, controllerW)); - } + } EditLineMeasureTracker::~EditLineMeasureTracker() { @@ -49,7 +49,7 @@ void EditLineMeasureTracker::PointerMove(const PointerEvent& e) { ScenePoint2D scenePos = e.GetMainPosition().Apply( - GetScene()->GetCanvasToSceneTransform()); + GetScene().GetCanvasToSceneTransform()); ScenePoint2D delta = scenePos - GetOriginalClickPosition(); @@ -104,4 +104,4 @@ return ret; } -} \ No newline at end of file +} diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Scene2DViewport/LayerHolder.cpp --- a/Framework/Scene2DViewport/LayerHolder.cpp Fri Jul 12 14:57:48 2019 +0200 +++ b/Framework/Scene2DViewport/LayerHolder.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -43,18 +43,18 @@ { assert(baseLayerIndex_ == -1); - baseLayerIndex_ = GetScene()->GetMaxDepth() + 100; + baseLayerIndex_ = GetScene().GetMaxDepth() + 100; for (int i = 0; i < polylineLayerCount_; ++i) { std::auto_ptr layer(new PolylineSceneLayer()); - GetScene()->SetLayer(baseLayerIndex_ + i, layer.release()); + GetScene().SetLayer(baseLayerIndex_ + i, layer.release()); } for (int i = 0; i < textLayerCount_; ++i) { std::auto_ptr layer(new TextSceneLayer()); - GetScene()->SetLayer( + GetScene().SetLayer( baseLayerIndex_ + polylineLayerCount_ + i, layer.release()); } @@ -72,7 +72,7 @@ return (baseLayerIndex_ != -1); } - boost::shared_ptr LayerHolder::GetScene() + Scene2D& LayerHolder::GetScene() { boost::shared_ptr controller = controllerW_.lock(); ORTHANC_ASSERT(controller.get() != 0, "Zombie attack!"); @@ -83,8 +83,8 @@ { for (int i = 0; i < textLayerCount_ + polylineLayerCount_; ++i) { - ORTHANC_ASSERT(GetScene()->HasLayer(baseLayerIndex_ + i), "No layer"); - GetScene()->DeleteLayer(baseLayerIndex_ + i); + ORTHANC_ASSERT(GetScene().HasLayer(baseLayerIndex_ + i), "No layer"); + GetScene().DeleteLayer(baseLayerIndex_ + i); } baseLayerIndex_ = -1; } @@ -93,9 +93,9 @@ { using namespace Orthanc; ORTHANC_ASSERT(baseLayerIndex_ != -1); - ORTHANC_ASSERT(GetScene()->HasLayer(GetPolylineLayerIndex(index))); + ORTHANC_ASSERT(GetScene().HasLayer(GetPolylineLayerIndex(index))); ISceneLayer* layer = - &(GetScene()->GetLayer(GetPolylineLayerIndex(index))); + &(GetScene().GetLayer(GetPolylineLayerIndex(index))); PolylineSceneLayer* concreteLayer = dynamic_cast(layer); @@ -108,9 +108,9 @@ { using namespace Orthanc; ORTHANC_ASSERT(baseLayerIndex_ != -1); - ORTHANC_ASSERT(GetScene()->HasLayer(GetTextLayerIndex(index))); + ORTHANC_ASSERT(GetScene().HasLayer(GetTextLayerIndex(index))); ISceneLayer* layer = - &(GetScene()->GetLayer(GetTextLayerIndex(index))); + &(GetScene().GetLayer(GetTextLayerIndex(index))); TextSceneLayer* concreteLayer = dynamic_cast(layer); diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Scene2DViewport/LayerHolder.h --- a/Framework/Scene2DViewport/LayerHolder.h Fri Jul 12 14:57:48 2019 +0200 +++ b/Framework/Scene2DViewport/LayerHolder.h Tue Jul 16 12:37:29 2019 +0200 @@ -89,7 +89,7 @@ private: int GetPolylineLayerIndex(int index = 0); int GetTextLayerIndex(int index = 0); - boost::shared_ptr GetScene(); + Scene2D& GetScene(); int textLayerCount_; int polylineLayerCount_; diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Scene2DViewport/LineMeasureTool.cpp --- a/Framework/Scene2DViewport/LineMeasureTool.cpp Fri Jul 12 14:57:48 2019 +0200 +++ b/Framework/Scene2DViewport/LineMeasureTool.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -97,7 +97,7 @@ LineMeasureTool::LineHighlightArea LineMeasureTool::LineHitTest(ScenePoint2D p) const { const double pixelToScene = - GetScene()->GetCanvasToSceneTransform().ComputeZoom(); + GetController()->GetScene().GetCanvasToSceneTransform().ComputeZoom(); const double SQUARED_HIT_TEST_MAX_DISTANCE_SCENE_COORD = pixelToScene * HIT_TEST_MAX_DISTANCE_CANVAS_COORD * pixelToScene * HIT_TEST_MAX_DISTANCE_CANVAS_COORD; const double sqDistanceFromStart = ScenePoint2D::SquaredDistancePtPt(p, start_); @@ -123,7 +123,7 @@ boost::shared_ptr LineMeasureTool::CreateEditionTracker(const PointerEvent& e) { ScenePoint2D scenePos = e.GetMainPosition().Apply( - GetScene()->GetCanvasToSceneTransform()); + GetController()->GetScene().GetCanvasToSceneTransform()); if (!HitTest(scenePos)) return boost::shared_ptr(); @@ -196,7 +196,7 @@ PolylineSceneLayer::Chain chain; //TODO: take DPI into account - AddSquare(chain, GetScene(), start_, + AddSquare(chain, GetController()->GetScene(), start_, GetController()->GetHandleSideLengthS()); if (lineHighlightArea_ == LineHighlightArea_Start) @@ -209,7 +209,7 @@ PolylineSceneLayer::Chain chain; //TODO: take DPI into account - AddSquare(chain, GetScene(), end_, + AddSquare(chain, GetController()->GetScene(), end_, GetController()->GetHandleSideLengthS()); if (lineHighlightArea_ == LineHighlightArea_End) @@ -235,7 +235,7 @@ double midY = 0.5 * (end_.GetY() + start_.GetY()); SetTextLayerOutlineProperties( - GetScene(), layerHolder_, buf, ScenePoint2D(midX, midY)); + GetController()->GetScene(), layerHolder_, buf, ScenePoint2D(midX, midY)); } } else diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Scene2DViewport/MeasureTool.cpp --- a/Framework/Scene2DViewport/MeasureTool.cpp Fri Jul 12 14:57:48 2019 +0200 +++ b/Framework/Scene2DViewport/MeasureTool.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -76,16 +76,6 @@ #endif } - boost::shared_ptr MeasureTool::GetScene() - { - return GetController()->GetScene(); - } - - boost::shared_ptr MeasureTool::GetScene() const - { - return GetController()->GetScene(); - } - MeasureTool::MeasureTool(MessageBroker& broker, boost::weak_ptr controllerW) : IObserver(broker) diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Scene2DViewport/MeasureTool.h --- a/Framework/Scene2DViewport/MeasureTool.h Fri Jul 12 14:57:48 2019 +0200 +++ b/Framework/Scene2DViewport/MeasureTool.h Tue Jul 16 12:37:29 2019 +0200 @@ -125,9 +125,6 @@ boost::shared_ptr GetController() const; boost::shared_ptr GetController(); - boost::shared_ptr GetScene() const; - boost::shared_ptr GetScene(); - /** enabled_ is not accessible by subclasses because there is a state machine that we do not wanna mess with diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Scene2DViewport/MeasureToolsToolbox.h --- a/Framework/Scene2DViewport/MeasureToolsToolbox.h Fri Jul 12 14:57:48 2019 +0200 +++ b/Framework/Scene2DViewport/MeasureToolsToolbox.h Tue Jul 16 12:37:29 2019 +0200 @@ -31,9 +31,9 @@ square sides are parallel to the canvas boundaries. */ void AddSquare(PolylineSceneLayer::Chain& chain, - boost::shared_ptr scene, - const ScenePoint2D& centerS, - const double& sideLengthS); + const Scene2D& scene, + const ScenePoint2D& centerS, + const double& sideLengthS); /** Creates an arc centered on c that goes @@ -180,10 +180,11 @@ from layerIndex, up to (and not including) layerIndex+5. */ void SetTextLayerOutlineProperties( - boost::shared_ptr scene, boost::shared_ptr layerHolder, - const char* text, ScenePoint2D p); + Scene2D& scene, + boost::shared_ptr layerHolder, + const char* text, + ScenePoint2D p); - - std::ostream& operator<<(std::ostream& os, const ScenePoint2D& p); + std::ostream& operator<<(std::ostream& os, const ScenePoint2D& p); } diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Scene2DViewport/MeasureTrackers.cpp --- a/Framework/Scene2DViewport/MeasureTrackers.cpp Fri Jul 12 14:57:48 2019 +0200 +++ b/Framework/Scene2DViewport/MeasureTrackers.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -53,7 +53,7 @@ command_->Undo(); } - boost::shared_ptr CreateMeasureTracker::GetScene() + Scene2D& CreateMeasureTracker::GetScene() { return controllerW_.lock()->GetScene(); } @@ -64,10 +64,10 @@ , commitResult_(true) { boost::shared_ptr controller = controllerW.lock(); - originalClickPosition_ = e.GetMainPosition().Apply(controller->GetScene()->GetCanvasToSceneTransform()); + originalClickPosition_ = e.GetMainPosition().Apply(controller->GetScene().GetCanvasToSceneTransform()); } - boost::shared_ptr EditMeasureTracker::GetScene() + Scene2D& EditMeasureTracker::GetScene() { return controllerW_.lock()->GetScene(); } diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Scene2DViewport/MeasureTrackers.h --- a/Framework/Scene2DViewport/MeasureTrackers.h Fri Jul 12 14:57:48 2019 +0200 +++ b/Framework/Scene2DViewport/MeasureTrackers.h Tue Jul 16 12:37:29 2019 +0200 @@ -45,7 +45,7 @@ boost::shared_ptr command_; boost::weak_ptr controllerW_; bool alive_; - boost::shared_ptr GetScene(); + Scene2D& GetScene(); private: bool commitResult_; @@ -65,8 +65,8 @@ boost::shared_ptr command_; boost::weak_ptr controllerW_; bool alive_; - boost::shared_ptr GetScene(); - + Scene2D& GetScene(); + ScenePoint2D GetOriginalClickPosition() const { return originalClickPosition_; diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Scene2DViewport/ViewportController.cpp --- a/Framework/Scene2DViewport/ViewportController.cpp Fri Jul 12 14:57:48 2019 +0200 +++ b/Framework/Scene2DViewport/ViewportController.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -29,12 +29,15 @@ namespace OrthancStone { - ViewportController::ViewportController(boost::weak_ptr undoStackW, MessageBroker& broker) + ViewportController::ViewportController(boost::weak_ptr undoStackW, + MessageBroker& broker, + IViewport& viewport) : IObservable(broker) , undoStackW_(undoStackW) , canvasToSceneFactor_(0.0) + , viewport_(viewport) + , scene_(viewport.GetScene()) { - scene_ = boost::make_shared(); } boost::shared_ptr ViewportController::GetUndoStack() @@ -72,16 +75,6 @@ return GetUndoStack()->CanRedo(); } - boost::shared_ptr ViewportController::GetScene() const - { - return scene_; - } - - boost::shared_ptr ViewportController::GetScene() - { - return scene_; - } - bool ViewportController::HandlePointerEvent(PointerEvent e) { throw StoneException(ErrorCode_NotImplemented); @@ -111,18 +104,18 @@ const OrthancStone::AffineTransform2D& ViewportController::GetCanvasToSceneTransform() const { - return scene_->GetCanvasToSceneTransform(); + return GetScene().GetCanvasToSceneTransform(); } const OrthancStone::AffineTransform2D& ViewportController::GetSceneToCanvasTransform() const { - return scene_->GetSceneToCanvasTransform(); + return GetScene().GetSceneToCanvasTransform(); } void ViewportController::SetSceneToCanvasTransform( const AffineTransform2D& transform) { - scene_->SetSceneToCanvasTransform(transform); + viewport_.GetScene().SetSceneToCanvasTransform(transform); BroadcastMessage(SceneTransformChanged(*this)); // update the canvas to scene factor @@ -133,7 +126,7 @@ void ViewportController::FitContent( unsigned int canvasWidth, unsigned int canvasHeight) { - scene_->FitContent(canvasWidth, canvasHeight); + viewport_.GetScene().FitContent(canvasWidth, canvasHeight); BroadcastMessage(SceneTransformChanged(*this)); } @@ -159,7 +152,7 @@ if (canvasToSceneFactor_ == 0) { canvasToSceneFactor_ = - GetScene()->GetCanvasToSceneTransform().ComputeZoom(); + GetScene().GetCanvasToSceneTransform().ComputeZoom(); } return canvasToSceneFactor_; } diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Scene2DViewport/ViewportController.h --- a/Framework/Scene2DViewport/ViewportController.h Fri Jul 12 14:57:48 2019 +0200 +++ b/Framework/Scene2DViewport/ViewportController.h Tue Jul 16 12:37:29 2019 +0200 @@ -22,7 +22,7 @@ #include "PredeclaredTypes.h" -#include "../Scene2D/Scene2D.h" +#include "../Viewport/IViewport.h" #include "../Scene2D/PointerEvent.h" #include "../Scene2DViewport/IFlexiblePointerTracker.h" @@ -80,10 +80,9 @@ ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, \ SceneTransformChanged, ViewportController); - ViewportController(boost::weak_ptr undoStackW, MessageBroker& broker); - - boost::shared_ptr GetScene() const; - boost::shared_ptr GetScene(); + ViewportController(boost::weak_ptr undoStackW, + MessageBroker& broker, + IViewport& viewport); /** This method is called by the GUI system and should update/delete the @@ -170,6 +169,20 @@ /** forwarded to the UndoStack */ bool CanRedo() const; + IViewport& GetViewport() + { + return viewport_; + } + + Scene2D& GetScene() + { + return viewport_.GetScene(); + } + + const Scene2D& GetScene() const + { + return scene_; + } private: double GetCanvasToSceneFactor() const; @@ -180,10 +193,14 @@ boost::shared_ptr GetUndoStack() const; std::vector > measureTools_; - boost::shared_ptr scene_; boost::shared_ptr tracker_; // this is cached mutable double canvasToSceneFactor_; + + + // Refactoring on 2019-07-10: Removing shared_ptr from scene + IViewport& viewport_; + const Scene2D& scene_; // As long as the viewport exists, its associated scene too }; } diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Viewport/IViewport.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Viewport/IViewport.h Tue Jul 16 12:37:29 2019 +0200 @@ -0,0 +1,52 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * 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 . + **/ + +#pragma once + +#include "../Scene2D/Scene2D.h" +#include "../Scene2D/ScenePoint2D.h" + +namespace OrthancStone +{ + /** + * Class that combines a Scene2D with a canvas where to draw the + * scene. A call to "Refresh()" will update the content of the + * canvas. + **/ + class IViewport : public boost::noncopyable + { + public: + virtual ~IViewport() + { + } + + virtual Scene2D& GetScene() = 0; + + virtual void Refresh() = 0; + + virtual unsigned int GetCanvasWidth() const = 0; + + virtual unsigned int GetCanvasHeight() const = 0; + + virtual const std::string& GetCanvasIdentifier() const = 0; + + virtual ScenePoint2D GetPixelCenterCoordinates(int x, int y) const = 0; + }; +} diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Viewport/SdlViewport.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Viewport/SdlViewport.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -0,0 +1,47 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * 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 . + **/ + +#include "SdlViewport.h" + +#include + +#include + +namespace OrthancStone +{ + SdlViewport::SdlViewport(const char* title, + unsigned int width, + unsigned int height) : + ViewportBase(title), + context_(title, width, height), + compositor_(context_, GetScene()) + { + } + + SdlViewport::SdlViewport(const char* title, + unsigned int width, + unsigned int height, + boost::shared_ptr& scene) : + ViewportBase(title, scene), + context_(title, width, height), + compositor_(context_, GetScene()) + { + } +} diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Viewport/SdlViewport.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Viewport/SdlViewport.h Tue Jul 16 12:37:29 2019 +0200 @@ -0,0 +1,86 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * 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 . + **/ + +#pragma once + +#if !defined(ORTHANC_ENABLE_SDL) +# error Macro ORTHANC_ENABLE_SDL must be defined +#endif + +#if ORTHANC_ENABLE_SDL != 1 +# error SDL must be enabled to use this file +#endif + +#if !defined(ORTHANC_ENABLE_OPENGL) +# error The macro ORTHANC_ENABLE_OPENGL must be defined +#endif + +#if ORTHANC_ENABLE_OPENGL != 1 +# error Support for OpenGL is disabled +#endif + +#include "../../Applications/Sdl/SdlOpenGLContext.h" +#include "../Scene2D/OpenGLCompositor.h" +#include "ViewportBase.h" + +namespace OrthancStone +{ + class SdlViewport : public ViewportBase + { + private: + SdlOpenGLContext context_; + OpenGLCompositor compositor_; + + public: + SdlViewport(const char* title, + unsigned int width, + unsigned int height); + + SdlViewport(const char* title, + unsigned int width, + unsigned int height, + boost::shared_ptr& scene); + + virtual void Refresh() + { + compositor_.Refresh(); + } + + virtual unsigned int GetCanvasWidth() const + { + return compositor_.GetCanvasWidth(); + } + + virtual unsigned int GetCanvasHeight() const + { + return compositor_.GetCanvasHeight(); + } + + OpenGLCompositor& GetCompositor() + { + return compositor_; + } + + SdlOpenGLContext& GetContext() + { + return context_; + } + }; +} diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Viewport/ViewportBase.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Viewport/ViewportBase.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -0,0 +1,54 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * 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 . + **/ + +#include "ViewportBase.h" + +#include + +#include + +namespace OrthancStone +{ + ViewportBase::ViewportBase(const std::string& identifier) : + identifier_(identifier), + scene_(boost::make_shared()) + { + } + + + ViewportBase::ViewportBase(const std::string& identifier, + boost::shared_ptr& scene) : + identifier_(identifier), + scene_(scene) + { + if (scene.get() == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); + } + } + + + ScenePoint2D ViewportBase::GetPixelCenterCoordinates(int x, int y) const + { + return ScenePoint2D( + static_cast(x) + 0.5 - static_cast(GetCanvasWidth()) / 2.0, + static_cast(y) + 0.5 - static_cast(GetCanvasHeight()) / 2.0); + } +} diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Viewport/ViewportBase.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Viewport/ViewportBase.h Tue Jul 16 12:37:29 2019 +0200 @@ -0,0 +1,53 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * 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 . + **/ + +#pragma once + +#include "IViewport.h" + +#include + +namespace OrthancStone +{ + class ViewportBase : public IViewport + { + private: + std::string identifier_; + boost::shared_ptr scene_; + + public: + ViewportBase(const std::string& identifier); + + ViewportBase(const std::string& identifier, + boost::shared_ptr& scene); + + virtual Scene2D& GetScene() + { + return *scene_; + } + + virtual const std::string& GetCanvasIdentifier() const + { + return identifier_; + } + + virtual ScenePoint2D GetPixelCenterCoordinates(int x, int y) const; + }; +} diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Viewport/WebAssemblyViewport.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Viewport/WebAssemblyViewport.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -0,0 +1,48 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * 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 . + **/ + + +#include "WebAssemblyViewport.h" + +namespace OrthancStone +{ + WebAssemblyViewport::WebAssemblyViewport(const std::string& canvas) : + ViewportBase(canvas), + context_(canvas), + compositor_(context_, GetScene()) + { + } + + + WebAssemblyViewport::WebAssemblyViewport(const std::string& canvas, + boost::shared_ptr& scene) : + ViewportBase(canvas, scene), + context_(canvas), + compositor_(context_, GetScene()) + { + } + + + void WebAssemblyViewport::UpdateSize() + { + context_.UpdateSize(); // First read the size of the canvas + compositor_.Refresh(); // Then refresh the content of the canvas + } +} diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Framework/Viewport/WebAssemblyViewport.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Viewport/WebAssemblyViewport.h Tue Jul 16 12:37:29 2019 +0200 @@ -0,0 +1,65 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * 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 . + **/ + + +#pragma once + +#include "../OpenGL/WebAssemblyOpenGLContext.h" +#include "../Scene2D/OpenGLCompositor.h" +#include "ViewportBase.h" + +namespace OrthancStone +{ + class WebAssemblyViewport : public ViewportBase + { + private: + OpenGL::WebAssemblyOpenGLContext context_; + OpenGLCompositor compositor_; + + public: + WebAssemblyViewport(const std::string& canvas); + + WebAssemblyViewport(const std::string& canvas, + boost::shared_ptr& scene); + + virtual void Refresh() + { + compositor_.Refresh(); + } + + virtual unsigned int GetCanvasWidth() const + { + return context_.GetCanvasWidth(); + } + + virtual unsigned int GetCanvasHeight() const + { + return context_.GetCanvasHeight(); + } + + // This function must be called each time the browser window is resized + void UpdateSize(); + + OpenGLCompositor& GetCompositor() + { + return compositor_; + } + }; +} diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Resources/CMake/OrthancStoneConfiguration.cmake --- a/Resources/CMake/OrthancStoneConfiguration.cmake Fri Jul 12 14:57:48 2019 +0200 +++ b/Resources/CMake/OrthancStoneConfiguration.cmake Tue Jul 16 12:37:29 2019 +0200 @@ -276,11 +276,17 @@ list(APPEND APPLICATIONS_SOURCES ${ORTHANC_STONE_ROOT}/Applications/Sdl/SdlCairoSurface.cpp ${ORTHANC_STONE_ROOT}/Applications/Sdl/SdlEngine.cpp - ${ORTHANC_STONE_ROOT}/Applications/Sdl/SdlOpenGLWindow.cpp ${ORTHANC_STONE_ROOT}/Applications/Sdl/SdlOrthancSurface.cpp ${ORTHANC_STONE_ROOT}/Applications/Sdl/SdlStoneApplicationRunner.cpp ${ORTHANC_STONE_ROOT}/Applications/Sdl/SdlWindow.cpp ) + + if (ENABLE_OPENGL) + list(APPEND APPLICATIONS_SOURCES + ${ORTHANC_STONE_ROOT}/Applications/Sdl/SdlOpenGLContext.cpp + ${ORTHANC_STONE_ROOT}/Framework/Viewport/SdlViewport.cpp + ) + endif() endif() endif() elseif (ENABLE_WASM) @@ -518,6 +524,7 @@ ${ORTHANC_STONE_ROOT}/Framework/Toolbox/ShearWarpProjectiveTransform.cpp ${ORTHANC_STONE_ROOT}/Framework/Toolbox/SlicesSorter.cpp ${ORTHANC_STONE_ROOT}/Framework/Toolbox/UndoRedoStack.cpp + ${ORTHANC_STONE_ROOT}/Framework/Viewport/ViewportBase.cpp ${ORTHANC_STONE_ROOT}/Framework/Volumes/DicomVolumeImage.cpp ${ORTHANC_STONE_ROOT}/Framework/Volumes/DicomVolumeImageMPRSlicer.cpp ${ORTHANC_STONE_ROOT}/Framework/Volumes/DicomVolumeImageReslicer.cpp @@ -590,6 +597,7 @@ if (ENABLE_WASM) list(APPEND ORTHANC_STONE_SOURCES ${ORTHANC_STONE_ROOT}/Framework/OpenGL/WebAssemblyOpenGLContext.cpp + ${ORTHANC_STONE_ROOT}/Framework/Viewport/WebAssemblyViewport.cpp ) endif() endif() diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Samples/Qt/BasicScene.cpp --- a/Samples/Qt/BasicScene.cpp Fri Jul 12 14:57:48 2019 +0200 +++ b/Samples/Qt/BasicScene.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -21,7 +21,7 @@ #define GLEW_STATIC 1 // From Stone #include "../../Framework/OpenGL/OpenGLIncludes.h" -#include "../../Applications/Sdl/SdlOpenGLWindow.h" +#include "../../Applications/Sdl/SdlWindow.h" #include "../../Framework/Scene2D/CairoCompositor.h" #include "../../Framework/Scene2D/ColorTextureSceneLayer.h" #include "../../Framework/Scene2D/OpenGLCompositor.h" @@ -94,7 +94,7 @@ boost::shared_ptr undoStack(new UndoStack); boost::shared_ptr controller = boost::make_shared( undoStack, boost::ref(broker)); - PrepareScene(*(controller->GetScene())); + PrepareScene(controller->GetScene()); boost::shared_ptr interactor(new BasicScene2DInteractor(controller)); window.GetOpenGlWidget().SetInteractor(interactor); diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Samples/Qt/QStoneOpenGlWidget.cpp --- a/Samples/Qt/QStoneOpenGlWidget.cpp Fri Jul 12 14:57:48 2019 +0200 +++ b/Samples/Qt/QStoneOpenGlWidget.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -33,11 +33,11 @@ OrthancStone::GuiAdapterMouseEvent& guiEvent, PointerEvent& pointerEvent, const QMouseEvent& qtEvent, - const OrthancStone::OpenGLCompositor& compositor) + const IViewport& viewport) { guiEvent.targetX = qtEvent.x(); guiEvent.targetY = qtEvent.y(); - pointerEvent.AddPosition(compositor.GetPixelCenterCoordinates(guiEvent.targetX, guiEvent.targetY)); + pointerEvent.AddPosition(viewport.GetPixelCenterCoordinates(guiEvent.targetX, guiEvent.targetY)); switch (qtEvent.button()) { @@ -66,7 +66,7 @@ { OrthancStone::GuiAdapterMouseEvent guiEvent; PointerEvent pointerEvent; - ConvertFromPlatform(guiEvent, pointerEvent, *qtEvent, *compositor_); + ConvertFromPlatform(guiEvent, pointerEvent, *qtEvent, *viewport_); guiEvent.type = guiEventType; if (sceneInteractor_.get() != NULL && compositor_.get() != NULL) diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Samples/Qt/QStoneOpenGlWidget.h --- a/Samples/Qt/QStoneOpenGlWidget.h Fri Jul 12 14:57:48 2019 +0200 +++ b/Samples/Qt/QStoneOpenGlWidget.h Tue Jul 16 12:37:29 2019 +0200 @@ -6,12 +6,14 @@ #include #include "../../Framework/OpenGL/IOpenGLContext.h" #include "../../Framework/Scene2D/OpenGLCompositor.h" +#include "../../Framework/Viewport/IViewport.h" #include "../../Applications/Generic/Scene2DInteractor.h" namespace OrthancStone { class QStoneOpenGlWidget : public QOpenGLWidget, public OrthancStone::OpenGL::IOpenGLContext { + boost::shared_ptr viewport_; boost::shared_ptr compositor_; boost::shared_ptr sceneInteractor_; diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Samples/Sdl/BasicScene.cpp --- a/Samples/Sdl/BasicScene.cpp Fri Jul 12 14:57:48 2019 +0200 +++ b/Samples/Sdl/BasicScene.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -20,71 +20,243 @@ // From Stone -#include "../../Applications/Sdl/SdlOpenGLWindow.h" +#include "../../Framework/Viewport/SdlViewport.h" +#include "../../Framework/Scene2D/CairoCompositor.h" +#include "../../Framework/Scene2D/ColorTextureSceneLayer.h" #include "../../Framework/Scene2D/OpenGLCompositor.h" +#include "../../Framework/Scene2D/PanSceneTracker.h" +#include "../../Framework/Scene2D/RotateSceneTracker.h" +#include "../../Framework/Scene2D/ZoomSceneTracker.h" +#include "../../Framework/Scene2DViewport/ViewportController.h" #include "../../Framework/Scene2DViewport/UndoStack.h" + #include "../../Framework/StoneInitialization.h" #include "../../Framework/Messages/MessageBroker.h" // From Orthanc framework #include #include +#include +#include +#include #include -#include #include #include - -#include "../Shared/SharedBasicScene.h" - -using namespace OrthancStone; +static const unsigned int FONT_SIZE = 32; +static const int LAYER_POSITION = 150; -boost::shared_ptr interactor; -void HandleApplicationEvent(boost::shared_ptr controller, - const OrthancStone::OpenGLCompositor& compositor, - const SDL_Event& event) +void PrepareScene(OrthancStone::Scene2D& scene) { using namespace OrthancStone; - Scene2D& scene(*controller->GetScene()); - if (event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP || event.type == SDL_MOUSEMOTION) + + // Texture of 2x2 size + { + Orthanc::Image i(Orthanc::PixelFormat_RGB24, 2, 2, false); + + uint8_t *p = reinterpret_cast(i.GetRow(0)); + p[0] = 255; + p[1] = 0; + p[2] = 0; + + p[3] = 0; + p[4] = 255; + p[5] = 0; + + p = reinterpret_cast(i.GetRow(1)); + p[0] = 0; + p[1] = 0; + p[2] = 255; + + p[3] = 255; + p[4] = 0; + p[5] = 0; + + scene.SetLayer(12, new ColorTextureSceneLayer(i)); + + std::auto_ptr l(new ColorTextureSceneLayer(i)); + l->SetOrigin(-3, 2); + l->SetPixelSpacing(1.5, 1); + l->SetAngle(20.0 / 180.0 * M_PI); + scene.SetLayer(14, l.release()); + } + + // Texture of 1x1 size + { + Orthanc::Image i(Orthanc::PixelFormat_RGB24, 1, 1, false); + + uint8_t *p = reinterpret_cast(i.GetRow(0)); + p[0] = 255; + p[1] = 0; + p[2] = 0; + + std::auto_ptr l(new ColorTextureSceneLayer(i)); + l->SetOrigin(-2, 1); + l->SetAngle(20.0 / 180.0 * M_PI); + scene.SetLayer(13, l.release()); + } + + // Some lines { - // TODO: this code is copy/pasted from GuiAdapter::Run() -> find the right place + std::auto_ptr layer(new PolylineSceneLayer); + + layer->SetThickness(10); + + PolylineSceneLayer::Chain chain; + chain.push_back(ScenePoint2D(0 - 0.5, 0 - 0.5)); + chain.push_back(ScenePoint2D(0 - 0.5, 2 - 0.5)); + chain.push_back(ScenePoint2D(2 - 0.5, 2 - 0.5)); + chain.push_back(ScenePoint2D(2 - 0.5, 0 - 0.5)); + layer->AddChain(chain, true, 255, 0, 0); + + chain.clear(); + chain.push_back(ScenePoint2D(-5, -5)); + chain.push_back(ScenePoint2D(5, -5)); + chain.push_back(ScenePoint2D(5, 5)); + chain.push_back(ScenePoint2D(-5, 5)); + layer->AddChain(chain, true, 0, 255, 0); + + double dy = 1.01; + chain.clear(); + chain.push_back(ScenePoint2D(-4, -4)); + chain.push_back(ScenePoint2D(4, -4 + dy)); + chain.push_back(ScenePoint2D(-4, -4 + 2.0 * dy)); + chain.push_back(ScenePoint2D(4, 2)); + layer->AddChain(chain, false, 0, 0, 255); + + scene.SetLayer(50, layer.release()); + } + + // Some text + { + std::auto_ptr layer(new TextSceneLayer); + layer->SetText("Hello"); + scene.SetLayer(100, layer.release()); + } +} + + +void TakeScreenshot(const std::string& target, + const OrthancStone::Scene2D& scene, + unsigned int canvasWidth, + unsigned int canvasHeight) +{ + using namespace OrthancStone; + // Take a screenshot, then save it as PNG file + CairoCompositor compositor(scene, canvasWidth, canvasHeight); + compositor.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, FONT_SIZE, Orthanc::Encoding_Latin1); + compositor.Refresh(); + + Orthanc::ImageAccessor canvas; + compositor.GetCanvas().GetReadOnlyAccessor(canvas); + + Orthanc::Image png(Orthanc::PixelFormat_RGB24, canvas.GetWidth(), canvas.GetHeight(), false); + Orthanc::ImageProcessing::Convert(png, canvas); + + Orthanc::PngWriter writer; + writer.WriteToFile(target, png); +} + + +void HandleApplicationEvent(const SDL_Event& event, + boost::shared_ptr& controller, + boost::shared_ptr& activeTracker) +{ + using namespace OrthancStone; + + Scene2D& scene = controller->GetScene(); + IViewport& viewport = controller->GetViewport(); + + if (event.type == SDL_MOUSEMOTION) + { int scancodeCount = 0; const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount); - bool ctrlPressed(false); - bool shiftPressed(false); - bool altPressed(false); + + if (activeTracker.get() == NULL && + SDL_SCANCODE_LCTRL < scancodeCount && + keyboardState[SDL_SCANCODE_LCTRL]) + { + // The "left-ctrl" key is down, while no tracker is present - if (SDL_SCANCODE_LCTRL < scancodeCount && keyboardState[SDL_SCANCODE_LCTRL]) - ctrlPressed = true; - if (SDL_SCANCODE_RCTRL < scancodeCount && keyboardState[SDL_SCANCODE_RCTRL]) - ctrlPressed = true; - if (SDL_SCANCODE_LSHIFT < scancodeCount && keyboardState[SDL_SCANCODE_LSHIFT]) - shiftPressed = true; - if (SDL_SCANCODE_RSHIFT < scancodeCount && keyboardState[SDL_SCANCODE_RSHIFT]) - shiftPressed = true; - if (SDL_SCANCODE_LALT < scancodeCount && keyboardState[SDL_SCANCODE_LALT]) - altPressed = true; + PointerEvent e; + e.AddPosition(viewport.GetPixelCenterCoordinates(event.button.x, event.button.y)); + + ScenePoint2D p = e.GetMainPosition().Apply(scene.GetCanvasToSceneTransform()); + + char buf[64]; + sprintf(buf, "(%0.02f,%0.02f)", p.GetX(), p.GetY()); - GuiAdapterMouseEvent guiEvent; - ConvertFromPlatform(guiEvent, ctrlPressed, shiftPressed, altPressed, event); - PointerEvent pointerEvent; - pointerEvent.AddPosition(compositor.GetPixelCenterCoordinates(event.button.x, event.button.y)); - - interactor->OnMouseEvent(guiEvent, pointerEvent); - return; + if (scene.HasLayer(LAYER_POSITION)) + { + TextSceneLayer& layer = + dynamic_cast(scene.GetLayer(LAYER_POSITION)); + layer.SetText(buf); + layer.SetPosition(p.GetX(), p.GetY()); + } + else + { + std::auto_ptr + layer(new TextSceneLayer); + layer->SetColor(0, 255, 0); + layer->SetText(buf); + layer->SetBorder(20); + layer->SetAnchor(BitmapAnchor_BottomCenter); + layer->SetPosition(p.GetX(), p.GetY()); + scene.SetLayer(LAYER_POSITION, layer.release()); + } + } + else + { + scene.DeleteLayer(LAYER_POSITION); + } } - else if ((event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) && event.key.repeat == 0 /* Ignore key bounce */) + else if (event.type == SDL_MOUSEBUTTONDOWN) { - GuiAdapterKeyboardEvent guiEvent; - ConvertFromPlatform(guiEvent, event); + PointerEvent e; + e.AddPosition(viewport.GetPixelCenterCoordinates(event.button.x, event.button.y)); + + switch (event.button.button) + { + case SDL_BUTTON_MIDDLE: + activeTracker = boost::make_shared(controller, e); + break; + + case SDL_BUTTON_RIGHT: + activeTracker = boost::make_shared + (controller, e, viewport.GetCanvasHeight()); + break; + + case SDL_BUTTON_LEFT: + activeTracker = boost::make_shared(controller, e); + break; - interactor->OnKeyboardEvent(guiEvent); + default: + break; + } } - + else if (event.type == SDL_KEYDOWN && + event.key.repeat == 0 /* Ignore key bounce */) + { + switch (event.key.keysym.sym) + { + case SDLK_s: + controller->FitContent(viewport.GetCanvasWidth(), + viewport.GetCanvasHeight()); + break; + + case SDLK_c: + TakeScreenshot("screenshot.png", scene, + viewport.GetCanvasWidth(), + viewport.GetCanvasHeight()); + break; + + default: + break; + } + } } @@ -106,24 +278,24 @@ } -void Run(boost::shared_ptr controller) +void Run(OrthancStone::MessageBroker& broker, + OrthancStone::SdlViewport& viewport) { - SdlOpenGLWindow window("Hello", 1024, 768); - - controller->FitContent(window.GetCanvasWidth(), window.GetCanvasHeight()); + using namespace OrthancStone; + + boost::shared_ptr controller( + new ViewportController(boost::make_shared(), broker, viewport)); glEnable(GL_DEBUG_OUTPUT); glDebugMessageCallback(OpenGLMessageCallback, 0); - boost::shared_ptr compositor(new OpenGLCompositor(window, *controller->GetScene())); - compositor->SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, - BASIC_SCENE_FONT_SIZE, Orthanc::Encoding_Latin1); - interactor->SetCompositor(compositor); + boost::shared_ptr tracker; + bool firstShown = true; bool stop = false; while (!stop) { - compositor->Refresh(); + viewport.Refresh(); SDL_Event event; while (!stop && @@ -134,10 +306,49 @@ stop = true; break; } - else if (event.type == SDL_WINDOWEVENT && - event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) + else if (event.type == SDL_MOUSEMOTION) + { + if (tracker) + { + PointerEvent e; + e.AddPosition(viewport.GetPixelCenterCoordinates( + event.button.x, event.button.y)); + tracker->PointerMove(e); + } + } + else if (event.type == SDL_MOUSEBUTTONUP) { - compositor->UpdateSize(); + if (tracker) + { + PointerEvent e; + e.AddPosition(viewport.GetPixelCenterCoordinates( + event.button.x, event.button.y)); + tracker->PointerUp(e); + if(!tracker->IsAlive()) + tracker.reset(); + } + } + else if (event.type == SDL_WINDOWEVENT) + { + switch (event.window.event) + { + case SDL_WINDOWEVENT_SIZE_CHANGED: + tracker.reset(); + break; + + case SDL_WINDOWEVENT_SHOWN: + if (firstShown) + { + // Once the window is first shown, fit the content to its size + controller->FitContent(viewport.GetCanvasWidth(), viewport.GetCanvasHeight()); + firstShown = false; + } + + break; + + default: + break; + } } else if (event.type == SDL_KEYDOWN && event.key.repeat == 0 /* Ignore key bounce */) @@ -145,7 +356,7 @@ switch (event.key.keysym.sym) { case SDLK_f: - window.GetWindow().ToggleMaximize(); + viewport.GetContext().GetWindow().ToggleMaximize(); break; case SDLK_q: @@ -157,12 +368,11 @@ } } - HandleApplicationEvent(controller, *compositor, event); + HandleApplicationEvent(event, controller, tracker); } SDL_Delay(1); } - interactor.reset(); } @@ -175,26 +385,26 @@ **/ int main(int argc, char* argv[]) { - using namespace OrthancStone; - StoneInitialize(); + OrthancStone::StoneInitialize(); Orthanc::Logging::EnableInfoLevel(true); try { - MessageBroker broker; - boost::shared_ptr undoStack(new UndoStack); - boost::shared_ptr controller = boost::make_shared( - undoStack, boost::ref(broker)); - interactor.reset(new BasicScene2DInteractor(controller)); - PrepareScene(controller); - Run(controller); + OrthancStone::SdlViewport viewport("Hello", 1024, 768); + PrepareScene(viewport.GetScene()); + + viewport.GetCompositor().SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, + FONT_SIZE, Orthanc::Encoding_Latin1); + + OrthancStone::MessageBroker broker; + Run(broker, viewport); } catch (Orthanc::OrthancException& e) { LOG(ERROR) << "EXCEPTION: " << e.What(); } - StoneFinalize(); + OrthancStone::StoneFinalize(); return 0; } diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Samples/Sdl/CMakeLists.txt --- a/Samples/Sdl/CMakeLists.txt Fri Jul 12 14:57:48 2019 +0200 +++ b/Samples/Sdl/CMakeLists.txt Tue Jul 16 12:37:29 2019 +0200 @@ -66,8 +66,6 @@ add_executable(BasicScene BasicScene.cpp - ${CMAKE_CURRENT_LIST_DIR}/../Shared/SharedBasicScene.h - ${CMAKE_CURRENT_LIST_DIR}/../Shared/SharedBasicScene.cpp ) target_link_libraries(BasicScene OrthancStone) diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Samples/Sdl/FusionMprSdl.cpp --- a/Samples/Sdl/FusionMprSdl.cpp Fri Jul 12 14:57:48 2019 +0200 +++ b/Samples/Sdl/FusionMprSdl.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -20,7 +20,7 @@ #include "FusionMprSdl.h" -#include "../../Applications/Sdl/SdlOpenGLWindow.h" +#include "../../Applications/Sdl/SdlOpenGLContext.h" #include "../../Framework/StoneInitialization.h" @@ -587,7 +587,7 @@ { // False means we do NOT let Windows treat this as a legacy application // that needs to be scaled - SdlOpenGLWindow window("Hello", 1024, 1024, false); + SdlOpenGLContext window("Hello", 1024, 1024, false); controller_->FitContent(window.GetCanvasWidth(), window.GetCanvasHeight()); @@ -706,7 +706,6 @@ event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { DisableTracker(); // was: tracker.reset(NULL); - compositor_->UpdateSize(); } else if (event.type == SDL_KEYDOWN && event.key.repeat == 0 /* Ignore key bounce */) diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Samples/Sdl/TrackerSample.cpp --- a/Samples/Sdl/TrackerSample.cpp Fri Jul 12 14:57:48 2019 +0200 +++ b/Samples/Sdl/TrackerSample.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -21,7 +21,7 @@ #include "TrackerSampleApp.h" // From Stone -#include "../../Applications/Sdl/SdlOpenGLWindow.h" +#include "../../Applications/Sdl/SdlOpenGLContext.h" #include "../../Framework/Scene2D/CairoCompositor.h" #include "../../Framework/Scene2D/ColorTextureSceneLayer.h" #include "../../Framework/Scene2D/OpenGLCompositor.h" diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Samples/Sdl/TrackerSampleApp.cpp --- a/Samples/Sdl/TrackerSampleApp.cpp Fri Jul 12 14:57:48 2019 +0200 +++ b/Samples/Sdl/TrackerSampleApp.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -20,7 +20,7 @@ #include "TrackerSampleApp.h" -#include "../../Applications/Sdl/SdlOpenGLWindow.h" +#include "../../Applications/Sdl/SdlOpenGLContext.h" #include "../../Framework/Scene2D/CairoCompositor.h" #include "../../Framework/Scene2D/ColorTextureSceneLayer.h" @@ -68,16 +68,6 @@ return descs[i]; } - boost::shared_ptr TrackerSampleApp::GetScene() - { - return controller_->GetScene(); - } - - boost::shared_ptr TrackerSampleApp::GetScene() const - { - return controller_->GetScene(); - } - void TrackerSampleApp::SelectNextTool() { currentTool_ = static_cast(currentTool_ + 1); @@ -102,10 +92,10 @@ std::string msgS = msg.str(); TextSceneLayer* layerP = NULL; - if (GetScene()->HasLayer(FIXED_INFOTEXT_LAYER_ZINDEX)) + if (controller_->GetScene().HasLayer(FIXED_INFOTEXT_LAYER_ZINDEX)) { TextSceneLayer& layer = dynamic_cast( - GetScene()->GetLayer(FIXED_INFOTEXT_LAYER_ZINDEX)); + controller_->GetScene().GetLayer(FIXED_INFOTEXT_LAYER_ZINDEX)); layerP = &layer; } else @@ -117,29 +107,29 @@ layer->SetBorder(20); layer->SetAnchor(BitmapAnchor_TopLeft); //layer->SetPosition(0,0); - GetScene()->SetLayer(FIXED_INFOTEXT_LAYER_ZINDEX, layer.release()); + controller_->GetScene().SetLayer(FIXED_INFOTEXT_LAYER_ZINDEX, layer.release()); } // position the fixed info text in the upper right corner layerP->SetText(msgS.c_str()); double cX = compositor_->GetCanvasWidth() * (-0.5); double cY = compositor_->GetCanvasHeight() * (-0.5); - GetScene()->GetCanvasToSceneTransform().Apply(cX,cY); + controller_->GetScene().GetCanvasToSceneTransform().Apply(cX,cY); layerP->SetPosition(cX, cY); } void TrackerSampleApp::DisplayFloatingCtrlInfoText(const PointerEvent& e) { - ScenePoint2D p = e.GetMainPosition().Apply(GetScene()->GetCanvasToSceneTransform()); + ScenePoint2D p = e.GetMainPosition().Apply(controller_->GetScene().GetCanvasToSceneTransform()); char buf[128]; sprintf(buf, "S:(%0.02f,%0.02f) C:(%0.02f,%0.02f)", p.GetX(), p.GetY(), e.GetMainPosition().GetX(), e.GetMainPosition().GetY()); - if (GetScene()->HasLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)) + if (controller_->GetScene().HasLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)) { TextSceneLayer& layer = - dynamic_cast(GetScene()->GetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)); + dynamic_cast(controller_->GetScene().GetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)); layer.SetText(buf); layer.SetPosition(p.GetX(), p.GetY()); } @@ -151,13 +141,13 @@ layer->SetBorder(20); layer->SetAnchor(BitmapAnchor_BottomCenter); layer->SetPosition(p.GetX(), p.GetY()); - GetScene()->SetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX, layer.release()); + controller_->GetScene().SetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX, layer.release()); } } void TrackerSampleApp::HideInfoText() { - GetScene()->DeleteLayer(FLOATING_INFOTEXT_LAYER_ZINDEX); + controller_->GetScene().DeleteLayer(FLOATING_INFOTEXT_LAYER_ZINDEX); } ScenePoint2D TrackerSampleApp::GetRandomPointInScene() const @@ -179,7 +169,7 @@ ScenePoint2D p = compositor_->GetPixelCenterCoordinates(x, y); LOG(TRACE) << "--> p.GetX() = " << p.GetX() << " p.GetY() = " << p.GetY(); - ScenePoint2D r = p.Apply(GetScene()->GetCanvasToSceneTransform()); + ScenePoint2D r = p.Apply(controller_->GetScene().GetCanvasToSceneTransform()); LOG(TRACE) << "--> r.GetX() = " << r.GetX() << " r.GetY() = " << r.GetY(); return r; } @@ -276,7 +266,7 @@ e.AddPosition(compositor_->GetPixelCenterCoordinates(event.button.x, event.button.y)); ScenePoint2D scenePos = e.GetMainPosition().Apply( - controller_->GetScene()->GetCanvasToSceneTransform()); + controller_->GetScene().GetCanvasToSceneTransform()); //auto measureTools = GetController()->HitTestMeasureTools(scenePos); //LOG(TRACE) << "# of hit tests: " << measureTools.size(); @@ -527,13 +517,13 @@ p[4] = 0; p[5] = 0; - GetScene()->SetLayer(TEXTURE_2x2_1_ZINDEX, new ColorTextureSceneLayer(i)); + controller_->GetScene().SetLayer(TEXTURE_2x2_1_ZINDEX, new ColorTextureSceneLayer(i)); std::auto_ptr l(new ColorTextureSceneLayer(i)); l->SetOrigin(-3, 2); l->SetPixelSpacing(1.5, 1); l->SetAngle(20.0 / 180.0 * M_PI); - GetScene()->SetLayer(TEXTURE_2x2_2_ZINDEX, l.release()); + controller_->GetScene().SetLayer(TEXTURE_2x2_2_ZINDEX, l.release()); } // Texture of 1x1 size @@ -548,7 +538,7 @@ std::auto_ptr l(new ColorTextureSceneLayer(i)); l->SetOrigin(-2, 1); l->SetAngle(20.0 / 180.0 * M_PI); - GetScene()->SetLayer(TEXTURE_1x1_ZINDEX, l.release()); + controller_->GetScene().SetLayer(TEXTURE_1x1_ZINDEX, l.release()); } // Some lines @@ -579,14 +569,14 @@ chain.push_back(ScenePoint2D(4, 2)); layer->AddChain(chain, false, 0, 0, 255); - GetScene()->SetLayer(LINESET_1_ZINDEX, layer.release()); + controller_->GetScene().SetLayer(LINESET_1_ZINDEX, layer.release()); } // Some text { std::auto_ptr layer(new TextSceneLayer); layer->SetText("Hello"); - GetScene()->SetLayer(LINESET_2_ZINDEX, layer.release()); + controller_->GetScene().SetLayer(LINESET_2_ZINDEX, layer.release()); } } @@ -623,7 +613,7 @@ { // std::vector> measureTools_; ScenePoint2D scenePos = e.GetMainPosition().Apply( - controller_->GetScene()->GetCanvasToSceneTransform()); + controller_->GetScene().GetCanvasToSceneTransform()); std::vector > measureTools = controller_->HitTestMeasureTools(scenePos); @@ -657,7 +647,7 @@ { // False means we do NOT let Windows treat this as a legacy application // that needs to be scaled - SdlOpenGLWindow window("Hello", 1024, 1024, false); + SdlOpenGLContext window("Hello", 1024, 1024, false); controller_->FitContent(window.GetCanvasWidth(), window.GetCanvasHeight()); @@ -687,7 +677,6 @@ event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { DisableTracker(); // was: tracker.reset(NULL); - compositor_->UpdateSize(); } else if (event.type == SDL_KEYDOWN && event.key.repeat == 0 /* Ignore key bounce */) diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Samples/Sdl/TrackerSampleApp.h --- a/Samples/Sdl/TrackerSampleApp.h Fri Jul 12 14:57:48 2019 +0200 +++ b/Samples/Sdl/TrackerSampleApp.h Tue Jul 16 12:37:29 2019 +0200 @@ -65,9 +65,6 @@ void SetInfoDisplayMessage(std::string key, std::string value); void DisableTracker(); - boost::shared_ptr GetScene(); - boost::shared_ptr GetScene() const; - void HandleApplicationEvent(const SDL_Event& event); /** diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Samples/Shared/SharedBasicScene.cpp --- a/Samples/Shared/SharedBasicScene.cpp Fri Jul 12 14:57:48 2019 +0200 +++ b/Samples/Shared/SharedBasicScene.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -225,7 +225,7 @@ { if (showCursorInfo_) { - Scene2D& scene(*(viewportController_->GetScene())); + Scene2D& scene(viewportController_->GetScene()); ShowCursorInfo(scene, pointerEvent); } return true; @@ -247,7 +247,7 @@ #if ORTHANC_SANDBOXED == 0 case 'c': { - Scene2D& scene(*(viewportController_->GetScene())); + Scene2D& scene(viewportController_->GetScene()); TakeScreenshot("screenshot.png", scene, compositor_->GetCanvasWidth(), compositor_->GetCanvasHeight()); return true; } @@ -257,7 +257,7 @@ showCursorInfo_ = !showCursorInfo_; if (!showCursorInfo_) { - Scene2D& scene(*(viewportController_->GetScene())); + Scene2D& scene(viewportController_->GetScene()); scene.DeleteLayer(BASIC_SCENE_LAYER_POSITION); } diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Samples/WebAssembly/BasicScene.cpp --- a/Samples/WebAssembly/BasicScene.cpp Fri Jul 12 14:57:48 2019 +0200 +++ b/Samples/WebAssembly/BasicScene.cpp Tue Jul 16 12:37:29 2019 +0200 @@ -33,12 +33,108 @@ #include #include -#include "../Shared/SharedBasicScene.h" +void PrepareScene(OrthancStone::Scene2D& scene) +{ + using namespace OrthancStone; + + // Texture of 2x2 size + if (1) + { + Orthanc::Image i(Orthanc::PixelFormat_RGB24, 2, 2, false); + + uint8_t *p = reinterpret_cast(i.GetRow(0)); + p[0] = 255; + p[1] = 0; + p[2] = 0; + + p[3] = 0; + p[4] = 255; + p[5] = 0; + + p = reinterpret_cast(i.GetRow(1)); + p[0] = 0; + p[1] = 0; + p[2] = 255; + + p[3] = 255; + p[4] = 0; + p[5] = 0; + + scene.SetLayer(12, new ColorTextureSceneLayer(i)); + + std::auto_ptr l(new ColorTextureSceneLayer(i)); + l->SetOrigin(-3, 2); + l->SetPixelSpacing(1.5, 1); + l->SetAngle(20.0 / 180.0 * M_PI); + scene.SetLayer(14, l.release()); + } + + // Texture of 1x1 size + if (1) + { + Orthanc::Image i(Orthanc::PixelFormat_RGB24, 1, 1, false); + + uint8_t *p = reinterpret_cast(i.GetRow(0)); + p[0] = 255; + p[1] = 0; + p[2] = 0; + + std::auto_ptr l(new ColorTextureSceneLayer(i)); + l->SetOrigin(-2, 1); + l->SetAngle(20.0 / 180.0 * M_PI); + scene.SetLayer(13, l.release()); + } + + // Some lines + if (1) + { + std::auto_ptr layer(new PolylineSceneLayer); + + layer->SetThickness(1); + + PolylineSceneLayer::Chain chain; + chain.push_back(ScenePoint2D(0 - 0.5, 0 - 0.5)); + chain.push_back(ScenePoint2D(0 - 0.5, 2 - 0.5)); + chain.push_back(ScenePoint2D(2 - 0.5, 2 - 0.5)); + chain.push_back(ScenePoint2D(2 - 0.5, 0 - 0.5)); + layer->AddChain(chain, true, 255, 0, 0); + + chain.clear(); + chain.push_back(ScenePoint2D(-5, -5)); + chain.push_back(ScenePoint2D(5, -5)); + chain.push_back(ScenePoint2D(5, 5)); + chain.push_back(ScenePoint2D(-5, 5)); + layer->AddChain(chain, true, 0, 255, 0); + + double dy = 1.01; + chain.clear(); + chain.push_back(ScenePoint2D(-4, -4)); + chain.push_back(ScenePoint2D(4, -4 + dy)); + chain.push_back(ScenePoint2D(-4, -4 + 2.0 * dy)); + chain.push_back(ScenePoint2D(4, 2)); + layer->AddChain(chain, false, 0, 0, 255); + + scene.SetLayer(50, layer.release()); + } + + // Some text + if (1) + { + std::auto_ptr layer(new TextSceneLayer); + layer->SetText("Hello"); + scene.SetLayer(100, layer.release()); + } +} + std::auto_ptr viewport1_; std::auto_ptr viewport2_; std::auto_ptr viewport3_; -OrthancStone::MessageBroker broker_; +boost::shared_ptr controller1_; +boost::shared_ptr controller2_; +boost::shared_ptr controller3_; +OrthancStone::MessageBroker broker_; + EM_BOOL OnWindowResize( int eventType, const EmscriptenUiEvent *uiEvent, void *userData) @@ -74,21 +170,41 @@ EMSCRIPTEN_KEEPALIVE void Initialize() { - viewport1_.reset( - new OrthancStone::WebAssemblyViewport(broker_, "mycanvas1")); + viewport1_.reset(new OrthancStone::WebAssemblyViewport("mycanvas1")); PrepareScene(viewport1_->GetScene()); viewport1_->UpdateSize(); - viewport2_.reset( - new OrthancStone::WebAssemblyViewport(broker_, "mycanvas2")); + viewport2_.reset(new OrthancStone::WebAssemblyViewport("mycanvas2")); PrepareScene(viewport2_->GetScene()); viewport2_->UpdateSize(); - viewport3_.reset( - new OrthancStone::WebAssemblyViewport(broker_, "mycanvas3")); + viewport3_.reset(new OrthancStone::WebAssemblyViewport("mycanvas3")); PrepareScene(viewport3_->GetScene()); viewport3_->UpdateSize(); + viewport1_->GetCompositor().SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, + FONT_SIZE, Orthanc::Encoding_Latin1); + viewport2_->GetCompositor().SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, + FONT_SIZE, Orthanc::Encoding_Latin1); + viewport3_->GetCompositor().SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, + FONT_SIZE, Orthanc::Encoding_Latin1); + + controller1_.reset(new OrthancStone::ViewportController(boost::make_shared(), broker_, *viewport1_)); + controller2_.reset(new OrthancStone::ViewportController(boost::make_shared(), broker_, *viewport2_)); + controller3_.reset(new OrthancStone::ViewportController(boost::make_shared(), broker_, *viewport3_)); + + controller1_->FitContent(viewport1_->GetCanvasWidth(), viewport1_->GetCanvasHeight()); + controller2_->FitContent(viewport2_->GetCanvasWidth(), viewport2_->GetCanvasHeight()); + controller3_->FitContent(viewport3_->GetCanvasWidth(), viewport3_->GetCanvasHeight()); + + viewport1_->Refresh(); + viewport2_->Refresh(); + viewport3_->Refresh(); + + SetupEvents("mycanvas1", controller1_); + SetupEvents("mycanvas2", controller2_); + SetupEvents("mycanvas3", controller3_); + emscripten_set_resize_callback("#window", NULL, false, OnWindowResize); } } diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Samples/WebAssembly/CMakeLists.txt --- a/Samples/WebAssembly/CMakeLists.txt Fri Jul 12 14:57:48 2019 +0200 +++ b/Samples/WebAssembly/CMakeLists.txt Tue Jul 16 12:37:29 2019 +0200 @@ -15,6 +15,8 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s ASSERTIONS=1 -s DISABLE_EXCEPTION_CATCHING=0") #set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s EXIT_RUNTIME=1") +#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=1") + ##################################################################### ## Configuration of the Orthanc framework diff -r 875bd6aca5e6 -r 9c2f6d6b9f4a Samples/WebAssembly/dev.h --- a/Samples/WebAssembly/dev.h Fri Jul 12 14:57:48 2019 +0200 +++ b/Samples/WebAssembly/dev.h Tue Jul 16 12:37:29 2019 +0200 @@ -21,95 +21,23 @@ #pragma once -#include "../../Framework/OpenGL/WebAssemblyOpenGLContext.h" +#include "../../Framework/Viewport/WebAssemblyViewport.h" #include "../../Framework/Scene2D/OpenGLCompositor.h" #include "../../Framework/Scene2D/PanSceneTracker.h" #include "../../Framework/Scene2D/RotateSceneTracker.h" #include "../../Framework/Scene2D/ZoomSceneTracker.h" +#include "../../Framework/Scene2DViewport/UndoStack.h" #include "../../Framework/Scene2DViewport/ViewportController.h" -#include "../../Framework/Scene2DViewport/UndoStack.h" #include -#include #include +#include static const unsigned int FONT_SIZE = 32; namespace OrthancStone { - class WebAssemblyViewport : public boost::noncopyable - { - private: - // the construction order is important because compositor_ - // will hold a reference to the scene that belong to the - // controller_ object - OpenGL::WebAssemblyOpenGLContext context_; - boost::shared_ptr controller_; - OpenGLCompositor compositor_; - - void SetupEvents(const std::string& canvas); - - public: - WebAssemblyViewport(MessageBroker& broker, - const std::string& canvas) : - context_(canvas), - controller_(new ViewportController(boost::make_shared(), broker)), - compositor_(context_, *controller_->GetScene()) - { - compositor_.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, - FONT_SIZE, Orthanc::Encoding_Latin1); - SetupEvents(canvas); - } - - Scene2D& GetScene() - { - return *controller_->GetScene(); - } - - const boost::shared_ptr& GetController() - { - return controller_; - } - - void UpdateSize() - { - context_.UpdateSize(); - compositor_.UpdateSize(); - Refresh(); - } - - void Refresh() - { - compositor_.Refresh(); - } - - void FitContent() - { - GetScene().FitContent(context_.GetCanvasWidth(), context_.GetCanvasHeight()); - } - - const std::string& GetCanvasIdentifier() const - { - return context_.GetCanvasIdentifier(); - } - - ScenePoint2D GetPixelCenterCoordinates(int x, int y) const - { - return compositor_.GetPixelCenterCoordinates(x, y); - } - - unsigned int GetCanvasWidth() const - { - return context_.GetCanvasWidth(); - } - - unsigned int GetCanvasHeight() const - { - return context_.GetCanvasHeight(); - } - }; - class ActiveTracker : public boost::noncopyable { private: @@ -119,9 +47,9 @@ public: ActiveTracker(const boost::shared_ptr& tracker, - const std::string& canvasIdentifier) : + const std::string& canvasId) : tracker_(tracker), - canvasIdentifier_(canvasIdentifier), + canvasIdentifier_(canvasId), insideCanvas_(true) { if (tracker_.get() == NULL) @@ -149,13 +77,13 @@ static OrthancStone::PointerEvent* ConvertMouseEvent( const EmscriptenMouseEvent& source, - OrthancStone::WebAssemblyViewport& viewport) + OrthancStone::IViewport& viewport) { std::auto_ptr target( new OrthancStone::PointerEvent); target->AddPosition(viewport.GetPixelCenterCoordinates( - source.targetX, source.targetY)); + source.targetX, source.targetY)); target->SetAltModifier(source.altKey); target->SetControlModifier(source.ctrlKey); target->SetShiftModifier(source.shiftKey); @@ -172,8 +100,8 @@ if (mouseEvent != NULL && userData != NULL) { - OrthancStone::WebAssemblyViewport& viewport = - *reinterpret_cast(userData); + boost::shared_ptr& controller = + *reinterpret_cast*>(userData); switch (eventType) { @@ -185,8 +113,8 @@ std::auto_ptr layer(new OrthancStone::TextSceneLayer); layer->SetText(buf); - viewport.GetScene().SetLayer(100, layer.release()); - viewport.Refresh(); + controller->GetViewport().GetScene().SetLayer(100, layer.release()); + controller->GetViewport().Refresh(); break; } @@ -196,27 +124,27 @@ { std::auto_ptr event( - ConvertMouseEvent(*mouseEvent, viewport)); + ConvertMouseEvent(*mouseEvent, controller->GetViewport())); switch (mouseEvent->button) { case 0: // Left button emscripten_console_log("Creating RotateSceneTracker"); t.reset(new OrthancStone::RotateSceneTracker( - viewport.GetController(), *event)); + controller, *event)); break; case 1: // Middle button emscripten_console_log("Creating PanSceneTracker"); LOG(INFO) << "Creating PanSceneTracker" ; t.reset(new OrthancStone::PanSceneTracker( - viewport.GetController(), *event)); + controller, *event)); break; case 2: // Right button emscripten_console_log("Creating ZoomSceneTracker"); t.reset(new OrthancStone::ZoomSceneTracker( - viewport.GetController(), *event, viewport.GetCanvasWidth())); + controller, *event, controller->GetViewport().GetCanvasWidth())); break; default: @@ -227,8 +155,8 @@ if (t.get() != NULL) { tracker_.reset( - new OrthancStone::ActiveTracker(t, viewport.GetCanvasIdentifier())); - viewport.Refresh(); + new OrthancStone::ActiveTracker(t, controller->GetViewport().GetCanvasIdentifier())); + controller->GetViewport().Refresh(); } break; @@ -238,9 +166,9 @@ if (tracker_.get() != NULL) { std::auto_ptr event( - ConvertMouseEvent(*mouseEvent, viewport)); + ConvertMouseEvent(*mouseEvent, controller->GetViewport())); tracker_->PointerMove(*event); - viewport.Refresh(); + controller->GetViewport().Refresh(); } break; @@ -248,9 +176,9 @@ if (tracker_.get() != NULL) { std::auto_ptr event( - ConvertMouseEvent(*mouseEvent, viewport)); + ConvertMouseEvent(*mouseEvent, controller->GetViewport())); tracker_->PointerUp(*event); - viewport.Refresh(); + controller->GetViewport().Refresh(); if (!tracker_->IsAlive()) tracker_.reset(); } @@ -265,9 +193,10 @@ } -void OrthancStone::WebAssemblyViewport::SetupEvents(const std::string& canvas) +void SetupEvents(const std::string& canvas, + boost::shared_ptr& controller) { - emscripten_set_mousedown_callback(canvas.c_str(), this, false, OnMouseEvent); - emscripten_set_mousemove_callback(canvas.c_str(), this, false, OnMouseEvent); - emscripten_set_mouseup_callback(canvas.c_str(), this, false, OnMouseEvent); + emscripten_set_mousedown_callback(canvas.c_str(), &controller, false, OnMouseEvent); + emscripten_set_mousemove_callback(canvas.c_str(), &controller, false, OnMouseEvent); + emscripten_set_mouseup_callback(canvas.c_str(), &controller, false, OnMouseEvent); }