Mercurial > hg > orthanc-stone
changeset 1569:546ec0531099
removing deprecated files, backup is available in tag legacy-with-deprecated
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 21 Sep 2020 14:50:07 +0200 |
parents | 37d90bd69f31 |
children | 9a04f42098a3 |
files | OrthancStone/Resources/CMake/OrthancStoneConfiguration.cmake OrthancStone/Resources/CMake/OrthancStoneParameters.cmake OrthancStone/Resources/Graveyard/Deprecated/Applications/Commands/BaseCommands.yml OrthancStone/Resources/Graveyard/Deprecated/Applications/Generic/NativeStoneApplicationContext.cpp OrthancStone/Resources/Graveyard/Deprecated/Applications/Generic/NativeStoneApplicationContext.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Generic/NativeStoneApplicationRunner.cpp OrthancStone/Resources/Graveyard/Deprecated/Applications/Generic/NativeStoneApplicationRunner.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Generic/Scene2DInteractor.h OrthancStone/Resources/Graveyard/Deprecated/Applications/IStoneApplication.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Qt/QCairoWidget.cpp OrthancStone/Resources/Graveyard/Deprecated/Applications/Qt/QCairoWidget.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Qt/QStoneMainWindow.cpp OrthancStone/Resources/Graveyard/Deprecated/Applications/Qt/QStoneMainWindow.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Qt/QtStoneApplicationRunner.cpp OrthancStone/Resources/Graveyard/Deprecated/Applications/Qt/QtStoneApplicationRunner.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/BasicPetCtFusionApplication.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/CMakeLists.txt OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/CMakeLists.txt.old OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/EmptyApplication.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/LayoutPetCtFusionApplication.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Qt/SampleMainWindow.cpp OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Qt/SampleMainWindow.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Qt/SampleMainWindow.ui OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Qt/SampleMainWindowWithButtons.cpp OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Qt/SampleMainWindowWithButtons.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Qt/SampleMainWindowWithButtons.ui OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Qt/SampleQtApplicationRunner.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SampleApplicationBase.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SampleInteractor.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SampleList.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SampleMainNative.cpp OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SampleMainWasm.cpp OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Samples-status.md OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/AppStatus.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/MainWidgetInteractor.cpp OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/MainWidgetInteractor.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/Qt/SimpleViewerMainWindow.cpp OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/Qt/SimpleViewerMainWindow.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/Qt/SimpleViewerMainWindow.ui OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/Qt/mainQt.cpp OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/SimpleViewerApplication.cpp OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/SimpleViewerApplication.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/ThumbnailInteractor.cpp OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/ThumbnailInteractor.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/Wasm/SimpleViewerWasmApplicationAdapter.cpp OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/Wasm/SimpleViewerWasmApplicationAdapter.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/Wasm/mainWasm.cpp OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/Wasm/simple-viewer.html OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/Wasm/simple-viewer.ts OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/Wasm/styles.css OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/Wasm/tsconfig-simple-viewer.json OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewerApplicationSingleFile.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SingleFrameApplication.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SingleFrameEditorApplication.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SingleVolumeApplication.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/StoneSampleCommands.yml OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/StoneSampleCommands_generate.py OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/StoneSampleCommands_generated.hpp OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/StoneSampleCommands_generated.ts OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SynchronizedSeriesApplication.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/TestPatternApplication.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/index.html OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/samples-styles.css OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/simple-viewer-single-file.html OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/simple-viewer-single-file.ts OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/simple-viewer-single-file.tsconfig.json OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/single-frame-editor.html OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/single-frame-editor.ts OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/single-frame-editor.tsconfig.json OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/single-frame.html OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/single-frame.ts OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/single-frame.tsconfig.json OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/tsconfig-samples.json OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/build-wasm.sh OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/build-wasm.sh.old OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/build-web-ext.sh OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/build-web.sh OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/get-requirements-windows.ps1 OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/nginx.local.conf OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/package-lock.json OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/CMakeLists.txt OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/build-sdl-msvc15.ps1 OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/build-wasm.sh OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/build-web.sh OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/index.html OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/main.cpp OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/nginx.local.conf OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/rt-viewer-demo.html OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/rt-viewer-demo.ts OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/rt-viewer-demo.tsconfig.json OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/samples-styles.css OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/start-serving-files.sh OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/stop-serving-files.sh OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/tsconfig-samples.json OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/tsconfig-stone.json OrthancStone/Resources/Graveyard/Deprecated/Applications/Sdl/SdlCairoSurface.cpp OrthancStone/Resources/Graveyard/Deprecated/Applications/Sdl/SdlCairoSurface.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Sdl/SdlEngine.cpp OrthancStone/Resources/Graveyard/Deprecated/Applications/Sdl/SdlEngine.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Sdl/SdlOrthancSurface.cpp OrthancStone/Resources/Graveyard/Deprecated/Applications/Sdl/SdlOrthancSurface.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Sdl/SdlStoneApplicationRunner.cpp OrthancStone/Resources/Graveyard/Deprecated/Applications/Sdl/SdlStoneApplicationRunner.h OrthancStone/Resources/Graveyard/Deprecated/Applications/StoneApplicationContext.cpp OrthancStone/Resources/Graveyard/Deprecated/Applications/StoneApplicationContext.h OrthancStone/Resources/Graveyard/Deprecated/Applications/Wasm/StartupParametersBuilder.cpp OrthancStone/Resources/Graveyard/Deprecated/Applications/Wasm/StartupParametersBuilder.h OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/DelayedCallCommand.cpp OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/DelayedCallCommand.h OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/IOracleCommand.h OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/Oracle.cpp OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/Oracle.h OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/OracleDelayedCallExecutor.h OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/OracleWebService.cpp OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/OracleWebService.h OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/WebServiceCommandBase.cpp OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/WebServiceCommandBase.h OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/WebServiceDeleteCommand.cpp OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/WebServiceDeleteCommand.h OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/WebServiceGetCommand.cpp OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/WebServiceGetCommand.h OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/WebServicePostCommand.cpp OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/WebServicePostCommand.h OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/Defaults.cpp OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/Defaults.h OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/WasmDelayedCallExecutor.cpp OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/WasmDelayedCallExecutor.h OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/WasmDelayedCallExecutor.js OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/WasmPlatformApplicationAdapter.cpp OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/WasmPlatformApplicationAdapter.h OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/WasmViewport.cpp OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/WasmViewport.h OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/WasmWebService.cpp OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/WasmWebService.h OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/WasmWebService.js OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/default-library.js OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/logger.ts OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/stone-framework-loader.ts OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/tsconfig-stone.json OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/wasm-application-runner.ts OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/wasm-viewport.ts OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/Graveyard/playground.ts OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/Graveyard/playground2.ts OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/Graveyard/playground3.ts OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/Graveyard/playground4.py OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/Graveyard/runts.ps1 OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/Graveyard/test_stonegen.html OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/Graveyard/test_stonegen.ts OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/Graveyard/tsconfig.json OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/README.md OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/stonegentool.py OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/stonegentool_test.py OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/template.in.h.j2 OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/template.in.ts.j2 OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testCppHandler/CMakeLists.txt OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testCppHandler/README.md OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testCppHandler/conanfile.txt OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testCppHandler/main.cpp OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testCppHandler/test_data/test_Message2.json OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/CMakeLists.txt OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/DefaultLibrary.js OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/build-web.sh OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/build.sh OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/jsoncpp-1.8.4/json/json-forwards.h OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/jsoncpp-1.8.4/json/json.h OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/jsoncpp-1.8.4/jsoncpp.cpp OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/main.cpp OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/serve.py OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/styles.css OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/testWasmIntegrated.html OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/testWasmIntegrated.ts OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/test_data/test2.yaml OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/test_data/testTestStoneCodeGen.yaml OrthancStone/Resources/Graveyard/Deprecated/Samples/MultiPlatform/BasicScene/BasicScene.cpp OrthancStone/Resources/Graveyard/Deprecated/Samples/MultiPlatform/BasicScene/BasicScene.h OrthancStone/Resources/Graveyard/Deprecated/Samples/MultiPlatform/BasicScene/mainQt.cpp OrthancStone/Resources/Graveyard/Deprecated/Samples/MultiPlatform/BasicScene/mainSdl.cpp OrthancStone/Resources/Graveyard/Deprecated/Samples/Qt/BasicSceneWindow.cpp OrthancStone/Resources/Graveyard/Deprecated/Samples/Qt/BasicSceneWindow.h OrthancStone/Resources/Graveyard/Deprecated/Samples/Qt/BasicSceneWindow.ui OrthancStone/Resources/Graveyard/Deprecated/Samples/Qt/CMakeLists.txt OrthancStone/Resources/Graveyard/Deprecated/Samples/Qt/QStoneOpenGlWidget.cpp OrthancStone/Resources/Graveyard/Deprecated/Samples/Qt/QStoneOpenGlWidget.h OrthancStone/Resources/Graveyard/Deprecated/Samples/Qt/Scene2DInteractor.cpp OrthancStone/Resources/Graveyard/Deprecated/Samples/Qt/Scene2DInteractor.h OrthancStone/Resources/Graveyard/Deprecated/Samples/README.md OrthancStone/Resources/Graveyard/Deprecated/Samples/Sdl/BasicScene.cpp OrthancStone/Resources/Graveyard/Deprecated/Samples/Sdl/CMakeLists.txt OrthancStone/Resources/Graveyard/Deprecated/Samples/Sdl/FusionMprSdl.cpp OrthancStone/Resources/Graveyard/Deprecated/Samples/Sdl/FusionMprSdl.h OrthancStone/Resources/Graveyard/Deprecated/Samples/Sdl/Loader.cpp OrthancStone/Resources/Graveyard/Deprecated/Samples/Sdl/RadiographyEditor.cpp OrthancStone/Resources/Graveyard/Deprecated/Samples/Sdl/TrackerSample.cpp OrthancStone/Resources/Graveyard/Deprecated/Samples/Sdl/TrackerSampleApp.cpp OrthancStone/Resources/Graveyard/Deprecated/Samples/Sdl/TrackerSampleApp.h OrthancStone/Resources/Graveyard/Deprecated/Samples/Sdl/cpp.hint OrthancStone/Resources/Graveyard/Deprecated/Samples/WebAssembly/BasicMPR.cpp OrthancStone/Resources/Graveyard/Deprecated/Samples/WebAssembly/BasicMPR.html OrthancStone/Resources/Graveyard/Deprecated/Samples/WebAssembly/BasicScene.cpp OrthancStone/Resources/Graveyard/Deprecated/Samples/WebAssembly/BasicScene.html OrthancStone/Resources/Graveyard/Deprecated/Samples/WebAssembly/CMakeLists.txt OrthancStone/Resources/Graveyard/Deprecated/Samples/WebAssembly/Configuration.json OrthancStone/Resources/Graveyard/Deprecated/Samples/WebAssembly/ConfigurationLocalSJO.json OrthancStone/Resources/Graveyard/Deprecated/Samples/WebAssembly/NOTES.txt OrthancStone/Resources/Graveyard/Deprecated/Samples/WebAssembly/app.js OrthancStone/Resources/Graveyard/Deprecated/Samples/WebAssembly/dev.h OrthancStone/Resources/Graveyard/Deprecated/Samples/WebAssembly/index.html OrthancStone/Sources/Deprecated/GuiAdapter.cpp OrthancStone/Sources/Deprecated/GuiAdapter.h OrthancStone/Sources/Deprecated/Layers/CircleMeasureTracker.cpp OrthancStone/Sources/Deprecated/Layers/CircleMeasureTracker.h OrthancStone/Sources/Deprecated/Layers/ColorFrameRenderer.cpp OrthancStone/Sources/Deprecated/Layers/ColorFrameRenderer.h OrthancStone/Sources/Deprecated/Layers/DicomSeriesVolumeSlicer.cpp OrthancStone/Sources/Deprecated/Layers/DicomSeriesVolumeSlicer.h OrthancStone/Sources/Deprecated/Layers/DicomStructureSetSlicer.cpp OrthancStone/Sources/Deprecated/Layers/DicomStructureSetSlicer.h OrthancStone/Sources/Deprecated/Layers/FrameRenderer.cpp OrthancStone/Sources/Deprecated/Layers/FrameRenderer.h OrthancStone/Sources/Deprecated/Layers/GrayscaleFrameRenderer.cpp OrthancStone/Sources/Deprecated/Layers/GrayscaleFrameRenderer.h OrthancStone/Sources/Deprecated/Layers/ILayerRenderer.h OrthancStone/Sources/Deprecated/Layers/IVolumeSlicer.h OrthancStone/Sources/Deprecated/Layers/LineLayerRenderer.cpp OrthancStone/Sources/Deprecated/Layers/LineLayerRenderer.h OrthancStone/Sources/Deprecated/Layers/LineMeasureTracker.cpp OrthancStone/Sources/Deprecated/Layers/LineMeasureTracker.h OrthancStone/Sources/Deprecated/Layers/RenderStyle.cpp OrthancStone/Sources/Deprecated/Layers/RenderStyle.h OrthancStone/Sources/Deprecated/Layers/SeriesFrameRendererFactory.cpp OrthancStone/Sources/Deprecated/Layers/SeriesFrameRendererFactory.h OrthancStone/Sources/Deprecated/Layers/SingleFrameRendererFactory.cpp OrthancStone/Sources/Deprecated/Layers/SingleFrameRendererFactory.h OrthancStone/Sources/Deprecated/Layers/SliceOutlineRenderer.cpp OrthancStone/Sources/Deprecated/Layers/SliceOutlineRenderer.h OrthancStone/Sources/Deprecated/Loaders/DicomStructureSetLoader2.cpp OrthancStone/Sources/Deprecated/Loaders/DicomStructureSetLoader2.h OrthancStone/Sources/Deprecated/Messages/LockingEmitter.cpp OrthancStone/Sources/Deprecated/Messages/LockingEmitter.h OrthancStone/Sources/Deprecated/Radiography/RadiographyAlphaLayer.cpp OrthancStone/Sources/Deprecated/Radiography/RadiographyAlphaLayer.h OrthancStone/Sources/Deprecated/Radiography/RadiographyDicomLayer.cpp OrthancStone/Sources/Deprecated/Radiography/RadiographyDicomLayer.h OrthancStone/Sources/Deprecated/Radiography/RadiographyLayer.cpp OrthancStone/Sources/Deprecated/Radiography/RadiographyLayer.h OrthancStone/Sources/Deprecated/Radiography/RadiographyLayerCropTracker.cpp OrthancStone/Sources/Deprecated/Radiography/RadiographyLayerCropTracker.h OrthancStone/Sources/Deprecated/Radiography/RadiographyLayerMaskTracker.cpp OrthancStone/Sources/Deprecated/Radiography/RadiographyLayerMaskTracker.h OrthancStone/Sources/Deprecated/Radiography/RadiographyLayerMoveTracker.cpp OrthancStone/Sources/Deprecated/Radiography/RadiographyLayerMoveTracker.h OrthancStone/Sources/Deprecated/Radiography/RadiographyLayerResizeTracker.cpp OrthancStone/Sources/Deprecated/Radiography/RadiographyLayerResizeTracker.h OrthancStone/Sources/Deprecated/Radiography/RadiographyLayerRotateTracker.cpp OrthancStone/Sources/Deprecated/Radiography/RadiographyLayerRotateTracker.h OrthancStone/Sources/Deprecated/Radiography/RadiographyMaskLayer.cpp OrthancStone/Sources/Deprecated/Radiography/RadiographyMaskLayer.h OrthancStone/Sources/Deprecated/Radiography/RadiographyScene.cpp OrthancStone/Sources/Deprecated/Radiography/RadiographyScene.h OrthancStone/Sources/Deprecated/Radiography/RadiographySceneCommand.cpp OrthancStone/Sources/Deprecated/Radiography/RadiographySceneCommand.h OrthancStone/Sources/Deprecated/Radiography/RadiographySceneReader.cpp OrthancStone/Sources/Deprecated/Radiography/RadiographySceneReader.h OrthancStone/Sources/Deprecated/Radiography/RadiographySceneWriter.cpp OrthancStone/Sources/Deprecated/Radiography/RadiographySceneWriter.h OrthancStone/Sources/Deprecated/Radiography/RadiographyTextLayer.cpp OrthancStone/Sources/Deprecated/Radiography/RadiographyTextLayer.h OrthancStone/Sources/Deprecated/Radiography/RadiographyWidget.cpp OrthancStone/Sources/Deprecated/Radiography/RadiographyWidget.h OrthancStone/Sources/Deprecated/Radiography/RadiographyWindowingTracker.cpp OrthancStone/Sources/Deprecated/Radiography/RadiographyWindowingTracker.h OrthancStone/Sources/Deprecated/SmartLoader.cpp OrthancStone/Sources/Deprecated/SmartLoader.h OrthancStone/Sources/Deprecated/Toolbox/BaseWebService.cpp OrthancStone/Sources/Deprecated/Toolbox/BaseWebService.h OrthancStone/Sources/Deprecated/Toolbox/DicomFrameConverter.cpp OrthancStone/Sources/Deprecated/Toolbox/DicomFrameConverter.h OrthancStone/Sources/Deprecated/Toolbox/DownloadStack.cpp OrthancStone/Sources/Deprecated/Toolbox/DownloadStack.h OrthancStone/Sources/Deprecated/Toolbox/IDelayedCallExecutor.h OrthancStone/Sources/Deprecated/Toolbox/ISeriesLoader.h OrthancStone/Sources/Deprecated/Toolbox/IWebService.cpp OrthancStone/Sources/Deprecated/Toolbox/IWebService.h OrthancStone/Sources/Deprecated/Toolbox/MessagingToolbox.cpp OrthancStone/Sources/Deprecated/Toolbox/MessagingToolbox.h OrthancStone/Sources/Deprecated/Toolbox/OrthancApiClient.cpp OrthancStone/Sources/Deprecated/Toolbox/OrthancApiClient.h OrthancStone/Sources/Deprecated/Toolbox/OrthancSlicesLoader.cpp OrthancStone/Sources/Deprecated/Toolbox/OrthancSlicesLoader.h OrthancStone/Sources/Deprecated/Toolbox/ParallelSlices.cpp OrthancStone/Sources/Deprecated/Toolbox/ParallelSlices.h OrthancStone/Sources/Deprecated/Toolbox/ParallelSlicesCursor.cpp OrthancStone/Sources/Deprecated/Toolbox/ParallelSlicesCursor.h OrthancStone/Sources/Deprecated/Toolbox/Slice.cpp OrthancStone/Sources/Deprecated/Toolbox/Slice.h OrthancStone/Sources/Deprecated/Toolbox/ViewportGeometry.cpp OrthancStone/Sources/Deprecated/Toolbox/ViewportGeometry.h OrthancStone/Sources/Deprecated/Viewport/CairoFont.cpp OrthancStone/Sources/Deprecated/Viewport/CairoFont.h OrthancStone/Sources/Deprecated/Viewport/IMouseTracker.h OrthancStone/Sources/Deprecated/Viewport/IStatusBar.h OrthancStone/Sources/Deprecated/Viewport/IViewport.h OrthancStone/Sources/Deprecated/Viewport/WidgetViewport.cpp OrthancStone/Sources/Deprecated/Viewport/WidgetViewport.h OrthancStone/Sources/Deprecated/Volumes/ISlicedVolume.h OrthancStone/Sources/Deprecated/Volumes/IVolumeLoader.h OrthancStone/Sources/Deprecated/Volumes/StructureSetLoader.cpp OrthancStone/Sources/Deprecated/Volumes/StructureSetLoader.h OrthancStone/Sources/Deprecated/Widgets/CairoWidget.cpp OrthancStone/Sources/Deprecated/Widgets/CairoWidget.h OrthancStone/Sources/Deprecated/Widgets/EmptyWidget.cpp OrthancStone/Sources/Deprecated/Widgets/EmptyWidget.h OrthancStone/Sources/Deprecated/Widgets/IWidget.h OrthancStone/Sources/Deprecated/Widgets/IWorldSceneInteractor.h OrthancStone/Sources/Deprecated/Widgets/IWorldSceneMouseTracker.h OrthancStone/Sources/Deprecated/Widgets/LayoutWidget.cpp OrthancStone/Sources/Deprecated/Widgets/LayoutWidget.h OrthancStone/Sources/Deprecated/Widgets/PanMouseTracker.cpp OrthancStone/Sources/Deprecated/Widgets/PanMouseTracker.h OrthancStone/Sources/Deprecated/Widgets/PanZoomMouseTracker.cpp OrthancStone/Sources/Deprecated/Widgets/PanZoomMouseTracker.h OrthancStone/Sources/Deprecated/Widgets/SliceViewerWidget.cpp OrthancStone/Sources/Deprecated/Widgets/SliceViewerWidget.h OrthancStone/Sources/Deprecated/Widgets/TestCairoWidget.cpp OrthancStone/Sources/Deprecated/Widgets/TestCairoWidget.h OrthancStone/Sources/Deprecated/Widgets/TestWorldSceneWidget.cpp OrthancStone/Sources/Deprecated/Widgets/TestWorldSceneWidget.h OrthancStone/Sources/Deprecated/Widgets/WidgetBase.cpp OrthancStone/Sources/Deprecated/Widgets/WidgetBase.h OrthancStone/Sources/Deprecated/Widgets/WorldSceneWidget.cpp OrthancStone/Sources/Deprecated/Widgets/WorldSceneWidget.h OrthancStone/Sources/Deprecated/Widgets/ZoomMouseTracker.cpp OrthancStone/Sources/Deprecated/Widgets/ZoomMouseTracker.h OrthancStone/Sources/Deprecated/dev.h |
diffstat | 334 files changed, 0 insertions(+), 52491 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancStone/Resources/CMake/OrthancStoneConfiguration.cmake Thu Sep 17 15:39:33 2020 +0200 +++ b/OrthancStone/Resources/CMake/OrthancStoneConfiguration.cmake Mon Sep 21 14:50:07 2020 +0200 @@ -268,13 +268,6 @@ ) endif() -if ((ENABLE_SDL OR ENABLE_WASM) AND ENABLE_GUIADAPTER) - list(APPEND APPLICATIONS_SOURCES - ${ORTHANC_STONE_ROOT}/Sources/Deprecated/GuiAdapter.cpp - ${ORTHANC_STONE_ROOT}/Sources/Deprecated/GuiAdapter.h - ) -endif() - list(APPEND ORTHANC_STONE_SOURCES ${ORTHANC_STONE_ROOT}/Sources/Toolbox/OrthancDatasets/DicomDatasetReader.cpp
--- a/OrthancStone/Resources/CMake/OrthancStoneParameters.cmake Thu Sep 17 15:39:33 2020 +0200 +++ b/OrthancStone/Resources/CMake/OrthancStoneParameters.cmake Mon Sep 21 14:50:07 2020 +0200 @@ -90,4 +90,3 @@ set(ENABLE_OPENGL ON CACHE BOOL "Enable support of OpenGL") set(ENABLE_WASM OFF CACHE INTERNAL "Enable support of WebAssembly") -set(ENABLE_GUIADAPTER OFF CACHE INTERNAL "Enable backward compatibility with the Stone GuiAdapter class")
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Commands/BaseCommands.yml Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -SelectTool: - target: Application - toolName: string - comment: Selects the current application tool -DownloadDicom: - target: SliceViewerWidget - comment: Downloads the slice currently displayed in the SliceViewerWidget -Export: - target: IWidget - comment: Export the content of the widget \ No newline at end of file
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Generic/NativeStoneApplicationContext.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "NativeStoneApplicationContext.h" -#include "../../Platforms/Generic/OracleWebService.h" - -namespace OrthancStone -{ - void NativeStoneApplicationContext::GlobalMutexLocker::SetCentralWidget( - boost::shared_ptr<Deprecated::IWidget> widget) - { - that_.centralViewport_.SetCentralWidget(widget); - } - - - void NativeStoneApplicationContext::UpdateThread(NativeStoneApplicationContext* that) - { - while (!that->stopped_) - { - { - GlobalMutexLocker locker(*that); - locker.GetCentralViewport().DoAnimation(); - } - - boost::this_thread::sleep(boost::posix_time::milliseconds(that->updateDelayInMs_)); - } - } - - - NativeStoneApplicationContext::NativeStoneApplicationContext() : - stopped_(true), - updateDelayInMs_(100) // By default, 100ms between each refresh of the content - { - srand(static_cast<unsigned int>(time(NULL))); - } - - - void NativeStoneApplicationContext::Start() - { - boost::recursive_mutex::scoped_lock lock(globalMutex_); - - if (stopped_ && - centralViewport_.HasAnimation()) - { - stopped_ = false; - updateThread_ = boost::thread(UpdateThread, this); - } - } - - - void NativeStoneApplicationContext::Stop() - { - stopped_ = true; - - if (updateThread_.joinable()) - { - updateThread_.join(); - } - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Generic/NativeStoneApplicationContext.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../Framework/Deprecated/Viewport/WidgetViewport.h" -#include "../../Framework/Deprecated/Volumes/ISlicedVolume.h" -#include "../../Framework/Deprecated/Volumes/IVolumeLoader.h" - -#include <list> -#include <boost/thread.hpp> -#include "../StoneApplicationContext.h" - -namespace OrthancStone -{ - class NativeStoneApplicationContext : public StoneApplicationContext - { - private: - static void UpdateThread(NativeStoneApplicationContext* that); - - boost::recursive_mutex globalMutex_; - Deprecated::WidgetViewport centralViewport_; - boost::thread updateThread_; - bool stopped_; - unsigned int updateDelayInMs_; - - public: - class GlobalMutexLocker: public boost::noncopyable - { - private: - NativeStoneApplicationContext& that_; - boost::recursive_mutex::scoped_lock lock_; - - public: - GlobalMutexLocker(NativeStoneApplicationContext& that) : - that_(that), - lock_(that.globalMutex_) - { - } - - void SetCentralWidget(boost::shared_ptr<Deprecated::IWidget> widget); - - Deprecated::IViewport& GetCentralViewport() - { - return that_.centralViewport_; - } - - void SetUpdateDelay(unsigned int delayInMs) - { - that_.updateDelayInMs_ = delayInMs; - } - }; - - NativeStoneApplicationContext(); - - void Start(); - - void Stop(); - }; -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Generic/NativeStoneApplicationRunner.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,265 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#if ORTHANC_ENABLE_THREADS != 1 -#error this file shall be included only with the ORTHANC_ENABLE_THREADS set to 1 -#endif - -#include "NativeStoneApplicationRunner.h" - -#include "../../Framework/Deprecated/Toolbox/MessagingToolbox.h" -#include "../../Platforms/Generic/OracleWebService.h" -#include "../../Platforms/Generic/OracleDelayedCallExecutor.h" -#include "NativeStoneApplicationContext.h" - -#include <Core/Logging.h> -#include <Core/HttpClient.h> -#include <Core/Toolbox.h> -#include <Core/OrthancException.h> -#include <Plugins/Samples/Common/OrthancHttpConnection.h> - -#include <boost/program_options.hpp> - -namespace OrthancStone -{ - // Anonymous namespace to avoid clashes against other compilation modules - namespace - { - class LogStatusBar : public Deprecated::IStatusBar - { - public: - virtual void ClearMessage() - { - } - - virtual void SetMessage(const std::string& message) - { - LOG(WARNING) << message; - } - }; - } - - int NativeStoneApplicationRunner::Execute(int argc, - char* argv[]) - { - /****************************************************************** - * Initialize all the subcomponents of Orthanc Stone - ******************************************************************/ - - Orthanc::Logging::Initialize(); - Orthanc::Toolbox::InitializeOpenSsl(); - Orthanc::HttpClient::GlobalInitialize(); - - Initialize(); - - /****************************************************************** - * Declare and parse the command-line options of the application - ******************************************************************/ - - boost::program_options::options_description options; - - { // generic options - boost::program_options::options_description generic("Generic options"); - generic.add_options() - ("help", "Display this help and exit") - ("verbose", "Be verbose in logs") - ("orthanc", boost::program_options::value<std::string>()-> - default_value("http://localhost:8042/"), - "URL to the Orthanc server") - ("username", "Username for the Orthanc server") - ("password", "Password for the Orthanc server") - ("https-verify", boost::program_options::value<bool>()-> - default_value(true), "Check HTTPS certificates") - ; - - options.add(generic); - } - - // platform specific options - DeclareCommandLineOptions(options); - - // application specific options - application_->DeclareStartupOptions(options); - - boost::program_options::variables_map parameters; - bool error = false; - - try - { - boost::program_options::store( - boost::program_options::command_line_parser(argc, argv). - options(options).allow_unregistered().run(), parameters); - boost::program_options::notify(parameters); - } - catch (boost::program_options::error& e) - { - LOG(ERROR) << - "Error while parsing the command-line arguments: " << e.what(); - error = true; - } - - - /****************************************************************** - * Configure the application with the command-line parameters - ******************************************************************/ - - if (error || parameters.count("help")) - { - std::cout << std::endl; - - std::cout << options << "\n"; - return error ? -1 : 0; - } - - if (parameters.count("https-verify") && - !parameters["https-verify"].as<bool>()) - { - LOG(WARNING) << "Turning off verification of HTTPS certificates (unsafe)"; - Orthanc::HttpClient::ConfigureSsl(false, ""); - } - - LOG(ERROR) << "???????? if (parameters.count(\"verbose\"))"; - if (parameters.count("verbose")) - { - LOG(ERROR) << "parameters.count(\"verbose\") != 0"; - Orthanc::Logging::EnableInfoLevel(true); - LOG(INFO) << "Verbose logs are enabled"; - } - - LOG(ERROR) << "???????? if (parameters.count(\"trace\"))"; - if (parameters.count("trace")) - { - LOG(ERROR) << "parameters.count(\"trace\") != 0"; - Orthanc::Logging::EnableTraceLevel(true); - VLOG(1) << "Trace logs are enabled"; - } - - ParseCommandLineOptions(parameters); - - bool success = true; - try - { - /**************************************************************** - * Initialize the connection to the Orthanc server - ****************************************************************/ - - Orthanc::WebServiceParameters webServiceParameters; - - if (parameters.count("orthanc")) - { - webServiceParameters.SetUrl(parameters["orthanc"].as<std::string>()); - } - - if (parameters.count("username") && parameters.count("password")) - { - webServiceParameters.SetCredentials(parameters["username"]. - as<std::string>(), - parameters["password"].as<std::string>()); - } - - LOG(WARNING) << "URL to the Orthanc REST API: " << - webServiceParameters.GetUrl(); - - { - OrthancPlugins::OrthancHttpConnection orthanc(webServiceParameters); - if (!Deprecated::MessagingToolbox::CheckOrthancVersion(orthanc)) - { - LOG(ERROR) << "Your version of Orthanc is incompatible with Stone of " - << "Orthanc, please upgrade"; - throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol); - } - } - - - /**************************************************************** - * Initialize the application - ****************************************************************/ - - LOG(WARNING) << "Creating the widgets of the application"; - - LogStatusBar statusBar; - - NativeStoneApplicationContext context; - - { - // use multiple threads to execute asynchronous tasks like - // download content - Deprecated::Oracle oracle(6); - oracle.Start(); - - { - boost::shared_ptr<Deprecated::OracleWebService> webService - (new Deprecated::OracleWebService(oracle, webServiceParameters, context)); - context.SetWebService(webService); - context.SetOrthancBaseUrl(webServiceParameters.GetUrl()); - - Deprecated::OracleDelayedCallExecutor delayedExecutor(oracle, context); - context.SetDelayedCallExecutor(delayedExecutor); - - application_->Initialize(&context, statusBar, parameters); - - { - NativeStoneApplicationContext::GlobalMutexLocker locker(context); - locker.SetCentralWidget(application_->GetCentralWidget()); - locker.GetCentralViewport().SetStatusBar(statusBar); - } - - std::string title = application_->GetTitle(); - if (title.empty()) - { - title = "Stone of Orthanc"; - } - - /**************************************************************** - * Run the application - ****************************************************************/ - - Run(context, title, argc, argv); - - /**************************************************************** - * Finalize the application - ****************************************************************/ - - oracle.Stop(); - } - } - - LOG(WARNING) << "The application is stopping"; - application_->Finalize(); - } - catch (Orthanc::OrthancException& e) - { - LOG(ERROR) << "EXCEPTION: " << e.What(); - success = false; - } - - - /****************************************************************** - * Finalize all the subcomponents of Orthanc Stone - ******************************************************************/ - - Finalize(); - Orthanc::HttpClient::GlobalFinalize(); - Orthanc::Toolbox::FinalizeOpenSsl(); - - return (success ? 0 : -1); - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Generic/NativeStoneApplicationRunner.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../IStoneApplication.h" - -#if ORTHANC_ENABLE_THREADS != 1 -#error this file shall be included only with the ORTHANC_ENABLE_THREADS set to 1 -#endif - -namespace OrthancStone -{ - class NativeStoneApplicationContext; - - class NativeStoneApplicationRunner - { - protected: - boost::shared_ptr<IStoneApplication> application_; - - public: - NativeStoneApplicationRunner(boost::shared_ptr<IStoneApplication> application) - : application_(application) - { - } - int Execute(int argc, - char* argv[]); - - virtual void Initialize() = 0; - virtual void DeclareCommandLineOptions(boost::program_options::options_description& options) = 0; - virtual void ParseCommandLineOptions(const boost::program_options::variables_map& parameters) = 0; - - virtual void Run(NativeStoneApplicationContext& context, const std::string& title, int argc, char* argv[]) = 0; - virtual void Finalize() = 0; - }; - -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Generic/Scene2DInteractor.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ -#pragma once - -#include "../../Framework/Scene2D/PointerEvent.h" -#include "../../Framework/Scene2DViewport/ViewportController.h" -//#include "../../Framework/Scene2D/Internals/CompositorHelper.h" -#include "GuiAdapter.h" - - -namespace OrthancStone -{ - - class Scene2DInteractor - { - protected: - boost::shared_ptr<ViewportController> viewportController_; -// boost::shared_ptr<ICompositor> compositor_; - - public: - Scene2DInteractor(boost::shared_ptr<ViewportController> viewportController) : - viewportController_(viewportController) - {} - -// void SetCompositor(boost::shared_ptr<ICompositor> compositor) -// { -// compositor_ = compositor; -// } - - virtual bool OnMouseEvent(const GuiAdapterMouseEvent& guiEvent, const PointerEvent& pointerEvent) = 0; // returns true if it has handled the event - virtual bool OnKeyboardEvent(const GuiAdapterKeyboardEvent& guiEvent) = 0; // returns true if it has handled the event - virtual bool OnWheelEvent(const GuiAdapterWheelEvent& guiEvent) = 0; // returns true if it has handled the event - - }; -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/IStoneApplication.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "StoneApplicationContext.h" -#include "../Framework/Deprecated/Viewport/WidgetViewport.h" - -#include <boost/program_options.hpp> -#include <json/json.h> - -namespace OrthancStone -{ -#if ORTHANC_ENABLE_QT==1 - class QStoneMainWindow; -#endif - - // a StoneApplication is an application that can actually be executed - // in multiple environments. i.e: it can run natively integrated in a QtApplication - // or it can be executed as part of a WebPage when compiled into WebAssembly. - class IStoneApplication : public boost::noncopyable - { - protected: - StoneApplicationContext* context_; - - public: - virtual ~IStoneApplication() - { - } - - virtual void DeclareStartupOptions(boost::program_options::options_description& options) = 0; - virtual void Initialize(StoneApplicationContext* context, - Deprecated::IStatusBar& statusBar, - const boost::program_options::variables_map& parameters) = 0; - - /** - This method is meant to process messages received from the outside world (i.e. GUI) - */ - virtual void HandleSerializedMessage(const char* data) = 0; - -#if ORTHANC_ENABLE_WASM==1 - virtual void InitializeWasm() {} // specific initialization when the app is running in WebAssembly. This is called after the other Initialize() -#endif -#if ORTHANC_ENABLE_QT==1 - virtual QStoneMainWindow* CreateQtMainWindow() = 0; -#endif - - virtual std::string GetTitle() const = 0; - - virtual void SetCentralWidget(boost::shared_ptr<Deprecated::IWidget> widget) = 0; - - virtual boost::shared_ptr<Deprecated::IWidget> GetCentralWidget() = 0; - - virtual void Finalize() = 0; - }; -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Qt/QCairoWidget.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,238 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#include "QCairoWidget.h" - -#include <QPainter> -#include <QPaintEvent> - -#include <stdexcept> - - -QCairoWidget::StoneObserver::StoneObserver(QCairoWidget& that, - Deprecated::IViewport& viewport, - OrthancStone::MessageBroker& broker) : - OrthancStone::IObserver(broker), - that_(that) -{ - // get notified each time the content of the central viewport changes - viewport.RegisterObserverCallback( - new OrthancStone::Callable<StoneObserver, Deprecated::IViewport::ViewportChangedMessage> - (*this, &StoneObserver::OnViewportChanged)); -} - - -QCairoWidget::QCairoWidget(QWidget *parent) : - QWidget(parent), - context_(NULL) -{ - setFocusPolicy(Qt::StrongFocus); // catch keyPressEvents -} - - -void QCairoWidget::SetContext(OrthancStone::NativeStoneApplicationContext& context) -{ - context_ = &context; - - { - OrthancStone::NativeStoneApplicationContext::GlobalMutexLocker locker(*context_); - observer_.reset(new StoneObserver(*this, - locker.GetCentralViewport(), - locker.GetMessageBroker())); - } -} - - -void QCairoWidget::paintEvent(QPaintEvent* /*event*/) -{ - QPainter painter(this); - - if (image_.get() != NULL && - context_ != NULL) - { - OrthancStone::NativeStoneApplicationContext::GlobalMutexLocker locker(*context_); - Deprecated::IViewport& viewport = locker.GetCentralViewport(); - Orthanc::ImageAccessor a; - surface_.GetWriteableAccessor(a); - viewport.Render(a); - painter.drawImage(0, 0, *image_); - } - else - { - painter.fillRect(rect(), Qt::red); - } -} - -OrthancStone::KeyboardModifiers GetKeyboardModifiers(QInputEvent* event) -{ - Qt::KeyboardModifiers qtModifiers = event->modifiers(); - int stoneModifiers = static_cast<int>(OrthancStone::KeyboardModifiers_None); - if ((qtModifiers & Qt::AltModifier) != 0) - { - stoneModifiers |= static_cast<int>(OrthancStone::KeyboardModifiers_Alt); - } - if ((qtModifiers & Qt::ControlModifier) != 0) - { - stoneModifiers |= static_cast<int>(OrthancStone::KeyboardModifiers_Control); - } - if ((qtModifiers & Qt::ShiftModifier) != 0) - { - stoneModifiers |= static_cast<int>(OrthancStone::KeyboardModifiers_Shift); - } - return static_cast<OrthancStone::KeyboardModifiers>(stoneModifiers); -} - -void QCairoWidget::mousePressEvent(QMouseEvent* event) -{ - OrthancStone::KeyboardModifiers stoneModifiers = GetKeyboardModifiers(event); - - OrthancStone::MouseButton button; - - switch (event->button()) - { - case Qt::LeftButton: - button = OrthancStone::MouseButton_Left; - break; - - case Qt::RightButton: - button = OrthancStone::MouseButton_Right; - break; - - case Qt::MiddleButton: - button = OrthancStone::MouseButton_Middle; - break; - - default: - return; // Unsupported button - } - - { - OrthancStone::NativeStoneApplicationContext::GlobalMutexLocker locker(*context_); - locker.GetCentralViewport().MouseDown(button, event->pos().x(), event->pos().y(), stoneModifiers, std::vector<Deprecated::Touch>()); - } -} - - -void QCairoWidget::mouseReleaseEvent(QMouseEvent* /*eventNotUsed*/) -{ - OrthancStone::NativeStoneApplicationContext::GlobalMutexLocker locker(*context_); - locker.GetCentralViewport().MouseLeave(); -} - - -void QCairoWidget::mouseMoveEvent(QMouseEvent* event) -{ - OrthancStone::NativeStoneApplicationContext::GlobalMutexLocker locker(*context_); - locker.GetCentralViewport().MouseMove(event->pos().x(), event->pos().y(), std::vector<Deprecated::Touch>()); -} - - -void QCairoWidget::wheelEvent(QWheelEvent * event) -{ - OrthancStone::NativeStoneApplicationContext::GlobalMutexLocker locker(*context_); - - OrthancStone::KeyboardModifiers stoneModifiers = GetKeyboardModifiers(event); - - if (event->orientation() == Qt::Vertical) - { - if (event->delta() < 0) // TODO: compare direction with SDL and make sure we send the same directions - { - locker.GetCentralViewport().MouseWheel(OrthancStone::MouseWheelDirection_Up, event->pos().x(), event->pos().y(), stoneModifiers); - } - else - { - locker.GetCentralViewport().MouseWheel(OrthancStone::MouseWheelDirection_Down, event->pos().x(), event->pos().y(), stoneModifiers); - } - } -} - -void QCairoWidget::keyPressEvent(QKeyEvent *event) -{ - using namespace OrthancStone; - - OrthancStone::KeyboardModifiers stoneModifiers = GetKeyboardModifiers(event); - - OrthancStone::KeyboardKeys keyType = OrthancStone::KeyboardKeys_Generic; - char keyChar = event->text()[0].toLatin1(); - -#define CASE_QT_KEY_TO_ORTHANC(qt, o) case qt: keyType = o; break; - if (keyChar == 0) - { - switch (event->key()) - { - CASE_QT_KEY_TO_ORTHANC(Qt::Key_Up, KeyboardKeys_Up); - CASE_QT_KEY_TO_ORTHANC(Qt::Key_Down, KeyboardKeys_Down); - CASE_QT_KEY_TO_ORTHANC(Qt::Key_Left, KeyboardKeys_Left); - CASE_QT_KEY_TO_ORTHANC(Qt::Key_Right, KeyboardKeys_Right); - CASE_QT_KEY_TO_ORTHANC(Qt::Key_F1, KeyboardKeys_F1); - CASE_QT_KEY_TO_ORTHANC(Qt::Key_F2, KeyboardKeys_F2); - CASE_QT_KEY_TO_ORTHANC(Qt::Key_F3, KeyboardKeys_F3); - CASE_QT_KEY_TO_ORTHANC(Qt::Key_F4, KeyboardKeys_F4); - CASE_QT_KEY_TO_ORTHANC(Qt::Key_F5, KeyboardKeys_F5); - CASE_QT_KEY_TO_ORTHANC(Qt::Key_F6, KeyboardKeys_F6); - CASE_QT_KEY_TO_ORTHANC(Qt::Key_F7, KeyboardKeys_F7); - CASE_QT_KEY_TO_ORTHANC(Qt::Key_F8, KeyboardKeys_F8); - CASE_QT_KEY_TO_ORTHANC(Qt::Key_F9, KeyboardKeys_F9); - CASE_QT_KEY_TO_ORTHANC(Qt::Key_F10, KeyboardKeys_F10); - CASE_QT_KEY_TO_ORTHANC(Qt::Key_F11, KeyboardKeys_F11); - CASE_QT_KEY_TO_ORTHANC(Qt::Key_F12, KeyboardKeys_F12); - default: - break; - } - } - else if (keyChar == 127) - { - switch (event->key()) - { - CASE_QT_KEY_TO_ORTHANC(Qt::Key_Delete, KeyboardKeys_Delete); - CASE_QT_KEY_TO_ORTHANC(Qt::Key_Backspace, KeyboardKeys_Backspace); - default: - break; - } - } - - { - OrthancStone::NativeStoneApplicationContext::GlobalMutexLocker locker(*context_); - locker.GetCentralViewport().KeyPressed(keyType, keyChar, stoneModifiers); - } -} - - -void QCairoWidget::resizeEvent(QResizeEvent* event) -{ - grabGesture(Qt::PanGesture); - QWidget::resizeEvent(event); - - if (event) - { - surface_.SetSize(event->size().width(), event->size().height(), true); - - image_.reset(new QImage(reinterpret_cast<uchar*>(surface_.GetBuffer()), - event->size().width(), - event->size().height(), - surface_.GetPitch(), - QImage::Format_RGB32)); - - { - OrthancStone::NativeStoneApplicationContext::GlobalMutexLocker locker(*context_); - locker.GetCentralViewport().SetSize(event->size().width(), event->size().height()); - } - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Qt/QCairoWidget.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#pragma once - -#include "../../Applications/Generic/NativeStoneApplicationContext.h" -#include "../../Framework/Wrappers/CairoSurface.h" -#include "../../Framework/Deprecated/Widgets/IWidget.h" - -#include <QWidget> -#include <memory> -#include <cassert> - -class QCairoWidget : public QWidget -{ - Q_OBJECT - -private: - class StoneObserver : public OrthancStone::IObserver - { - private: - QCairoWidget& that_; - - public: - StoneObserver(QCairoWidget& that, - Deprecated::IViewport& viewport, - OrthancStone::MessageBroker& broker); - - void OnViewportChanged(const Deprecated::IViewport::ViewportChangedMessage& message) - { - that_.OnViewportChanged(); - } - }; - - std::unique_ptr<QImage> image_; - OrthancStone::CairoSurface surface_; - OrthancStone::NativeStoneApplicationContext* context_; - std::unique_ptr<StoneObserver> observer_; - -protected: - virtual void paintEvent(QPaintEvent *event); - - virtual void resizeEvent(QResizeEvent *event); - - virtual void mouseMoveEvent(QMouseEvent *event); - - virtual void mousePressEvent(QMouseEvent *event); - - virtual void mouseReleaseEvent(QMouseEvent *event); - - virtual void wheelEvent(QWheelEvent *event); - - virtual void keyPressEvent(QKeyEvent *event); - -public: - explicit QCairoWidget(QWidget *parent); - - void SetContext(OrthancStone::NativeStoneApplicationContext& context); - - void OnViewportChanged() - { - update(); // schedule a repaint (handled by Qt) - emit ContentChanged(); - } - -signals: - void ContentChanged(); - -public slots: - -};
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Qt/QStoneMainWindow.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#include "QStoneMainWindow.h" - -namespace OrthancStone -{ - - QStoneMainWindow::QStoneMainWindow(NativeStoneApplicationContext& context, - QWidget *parent) : - QMainWindow(parent), - context_(context), - cairoCentralWidget_(NULL) - { - } - - void QStoneMainWindow::SetCentralStoneWidget(QCairoWidget& centralWidget) - { - cairoCentralWidget_ = ¢ralWidget; - cairoCentralWidget_->SetContext(context_); - } - - QStoneMainWindow::~QStoneMainWindow() - { - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Qt/QStoneMainWindow.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ -#pragma once - -#include <QMainWindow> - -#include "QCairoWidget.h" -#include "../Generic/NativeStoneApplicationContext.h" - -namespace OrthancStone -{ - class QStoneMainWindow : public QMainWindow - { - Q_OBJECT - - private: - OrthancStone::NativeStoneApplicationContext& context_; - QCairoWidget *cairoCentralWidget_; - - protected: // you must inherit this class - QStoneMainWindow(NativeStoneApplicationContext& context, QWidget *parent = 0); - void SetCentralStoneWidget(QCairoWidget& centralWidget); - - public: - virtual ~QStoneMainWindow(); - }; - -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Qt/QtStoneApplicationRunner.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#if ORTHANC_ENABLE_QT != 1 -#error this file shall be included only with the ORTHANC_ENABLE_QT set to 1 -#endif - -#include "QtStoneApplicationRunner.h" -#include <boost/program_options.hpp> -#include <QApplication> - -#include "../../Framework/Deprecated/Toolbox/MessagingToolbox.h" - -#include <Core/Logging.h> -#include <Core/HttpClient.h> -#include <Core/Toolbox.h> -#include <Plugins/Samples/Common/OrthancHttpConnection.h> -#include "../../Platforms/Generic/OracleWebService.h" - - -namespace OrthancStone -{ - void QtStoneApplicationRunner::Initialize() - { - } - - void QtStoneApplicationRunner::DeclareCommandLineOptions(boost::program_options::options_description& options) - { - } - - void QtStoneApplicationRunner::Run(NativeStoneApplicationContext& context, const std::string& title, int argc, char* argv[]) - { - context.Start(); - - QApplication qtApplication(argc, argv); - window_.reset(application_.CreateQtMainWindow()); - - window_->show(); - qtApplication.exec(); - - context.Stop(); - } - - void QtStoneApplicationRunner::Finalize() - { - } - - -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Qt/QtStoneApplicationRunner.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../Generic/NativeStoneApplicationRunner.h" -#include "QStoneMainWindow.h" - -#if ORTHANC_ENABLE_QT != 1 -#error this file shall be included only with the ORTHANC_ENABLE_QT set to 1 -#endif - -namespace OrthancStone -{ - class QtStoneApplicationRunner : public NativeStoneApplicationRunner - { - protected: - std::unique_ptr<QStoneMainWindow> window_; - - public: - QtStoneApplicationRunner(MessageBroker& broker, - IStoneApplication& application) - : NativeStoneApplicationRunner(broker, application) - { - } - - - virtual void Initialize(); - - virtual void DeclareCommandLineOptions(boost::program_options::options_description& options); - virtual void ParseCommandLineOptions(const boost::program_options::variables_map& parameters) {} - virtual void Run(NativeStoneApplicationContext& context, const std::string& title, int argc, char* argv[]); - virtual void Finalize(); - }; - -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/BasicPetCtFusionApplication.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,202 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "SampleInteractor.h" - -#include <Core/Logging.h> - -namespace OrthancStone -{ - namespace Samples - { - class BasicPetCtFusionApplication : public SampleApplicationBase - { - private: - class Interactor : public SampleInteractor - { - public: - static void SetStyle(LayeredSceneWidget& widget, - bool ct, - bool pet) - { - if (ct) - { - RenderStyle style; - style.windowing_ = ImageWindowing_Bone; - widget.SetLayerStyle(0, style); - } - else - { - RenderStyle style; - style.visible_ = false; - widget.SetLayerStyle(0, style); - } - - if (ct && pet) - { - RenderStyle style; - style.applyLut_ = true; - style.alpha_ = 0.5; - widget.SetLayerStyle(1, style); - } - else if (pet) - { - RenderStyle style; - style.applyLut_ = true; - widget.SetLayerStyle(1, style); - } - else - { - RenderStyle style; - style.visible_ = false; - widget.SetLayerStyle(1, style); - } - } - - - static bool IsVisible(LayeredSceneWidget& widget, - size_t layer) - { - RenderStyle style = widget.GetLayerStyle(layer); - return style.visible_; - } - - - static void ToggleInterpolation(LayeredSceneWidget& widget, - size_t layer) - { - RenderStyle style = widget.GetLayerStyle(layer); - - if (style.interpolation_ == ImageInterpolation_Bilinear) - { - style.interpolation_ = ImageInterpolation_Nearest; - } - else - { - style.interpolation_ = ImageInterpolation_Bilinear; - } - - widget.SetLayerStyle(layer, style); - } - - - Interactor(VolumeImage& volume, - VolumeProjection projection, - bool reverse) : - SampleInteractor(volume, projection, reverse) - { - } - - - virtual void KeyPressed(WorldSceneWidget& widget, - char key, - KeyboardModifiers modifiers, - IStatusBar* statusBar) - { - LayeredSceneWidget& layered = dynamic_cast<LayeredSceneWidget&>(widget); - - switch (key) - { - case 'c': - // Toggle the visibility of the CT layer - SetStyle(layered, !IsVisible(layered, 0), IsVisible(layered, 1)); - break; - - case 'p': - // Toggle the visibility of the PET layer - SetStyle(layered, IsVisible(layered, 0), !IsVisible(layered, 1)); - break; - - case 'i': - { - // Toggle on/off the interpolation - ToggleInterpolation(layered, 0); - ToggleInterpolation(layered, 1); - break; - } - - default: - break; - } - } - }; - - - public: - virtual void DeclareCommandLineOptions(boost::program_options::options_description& options) - { - boost::program_options::options_description generic("Sample options"); - generic.add_options() - ("ct", boost::program_options::value<std::string>(), - "Orthanc ID of the CT series") - ("pet", boost::program_options::value<std::string>(), - "Orthanc ID of the PET series") - ("threads", boost::program_options::value<unsigned int>()->default_value(3), - "Number of download threads for the CT series") - ; - - options.add(generic); - } - - virtual void Initialize(BasicApplicationContext& context, - IStatusBar& statusBar, - const boost::program_options::variables_map& parameters) - { - using namespace OrthancStone; - - if (parameters.count("ct") != 1 || - parameters.count("pet") != 1) - { - LOG(ERROR) << "The series ID is missing"; - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - std::string ct = parameters["ct"].as<std::string>(); - std::string pet = parameters["pet"].as<std::string>(); - unsigned int threads = parameters["threads"].as<unsigned int>(); - - VolumeImage& ctVolume = context.AddSeriesVolume(ct, true /* progressive download */, threads); - VolumeImage& petVolume = context.AddSeriesVolume(pet, true /* progressive download */, 1); - - // Take the PET volume as the reference for the slices - std::unique_ptr<Interactor> interactor(new Interactor(petVolume, VolumeProjection_Axial, false /* don't reverse normal */)); - - std::unique_ptr<LayeredSceneWidget> widget(new LayeredSceneWidget); - widget->AddLayer(new VolumeImage::LayerFactory(ctVolume)); - widget->AddLayer(new VolumeImage::LayerFactory(petVolume)); - widget->SetSlice(interactor->GetCursor().GetCurrentSlice()); - widget->SetInteractor(*interactor); - - Interactor::SetStyle(*widget, true, true); // Initially, show both CT and PET layers - - context.AddInteractor(interactor.release()); - context.SetCentralWidget(widget.release()); - - statusBar.SetMessage("Use the key \"t\" to toggle the fullscreen mode"); - statusBar.SetMessage("Use the key \"c\" to show/hide the CT layer"); - statusBar.SetMessage("Use the key \"p\" to show/hide the PET layer"); - statusBar.SetMessage("Use the key \"i\" to toggle the smoothing of the images"); - } - }; - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/CMakeLists.txt Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,292 +0,0 @@ -# Usage (Linux): -# to build the WASM samples -# source ~/Downloads/emsdk/emsdk_env.sh && cmake -DCMAKE_TOOLCHAIN_FILE=${EMSCRIPTEN}/cmake/Modules/Platform/Emscripten.cmake -DCMAKE_BUILD_TYPE=Release -DSTONE_SOURCES_DIR=$currentDir/../../../orthanc-stone -DORTHANC_FRAMEWORK_SOURCE=path -DORTHANC_FRAMEWORK_ROOT=$currentDir/../../../orthanc -DALLOW_DOWNLOADS=ON .. -DENABLE_WASM=ON -# to build the Qt samples - -cmake_minimum_required(VERSION 2.8.3) -project(OrthancStone) - -include(../../../Resources/CMake/OrthancStoneParameters.cmake) - -set(ENABLE_STONE_DEPRECATED ON) # Need deprecated classes for these samples -set(EMSCRIPTEN_SET_LLVM_WASM_BACKEND ON) - -include(${ORTHANC_ROOT}/Resources/CMake/DownloadPackage.cmake) -DownloadPackage( - "a24b8136b8f3bb93f166baf97d9328de" - "http://orthanc.osimis.io/ThirdPartyDownloads/ubuntu-font-family-0.83.zip" - "${CMAKE_BINARY_DIR}/ubuntu-font-family-0.83") - -set(ORTHANC_STONE_APPLICATION_RESOURCES - UBUNTU_FONT ${CMAKE_BINARY_DIR}/ubuntu-font-family-0.83/Ubuntu-R.ttf - ) - -if (OPENSSL_NO_CAPIENG) -add_definitions(-DOPENSSL_NO_CAPIENG=1) -endif() - - -# the following block has been borrowed from orthanc/**/Compiler.cmake -if (MSVC_MULTIPLE_PROCESSES) -# "If you omit the processMax argument in the /MP option, the -# compiler obtains the number of effective processors from the -# operating system, and then creates one process per effective -# processor" -# https://blog.kitware.com/cmake-building-with-all-your-cores/ -# https://docs.microsoft.com/en-us/cpp/build/reference/mp-build-with-multiple-processes -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") -endif() - -#set(ENABLE_DCMTK ON) - -set(ENABLE_SDL OFF CACHE BOOL "Target SDL Native application") -set(ENABLE_QT OFF CACHE BOOL "Target Qt Native application") -set(ENABLE_WASM OFF CACHE BOOL "Target WASM application") - -if (ENABLE_WASM) - ##################################################################### - ## Configuration of the Emscripten compiler for WebAssembly target - ##################################################################### - - set(WASM_FLAGS "-s WASM=1") - set(WASM_FLAGS "${WASM_FLAGS} -s STRICT=1") # drops support for all deprecated build options - set(WASM_FLAGS "${WASM_FLAGS} -s FILESYSTEM=1") # if we don't include it, gen_uuid.c fails to build because srand, getpid(), ... are not defined - set(WASM_FLAGS "${WASM_FLAGS} -s DISABLE_EXCEPTION_CATCHING=0") # actually enable exception catching - set(WASM_FLAGS "${WASM_FLAGS} -s ERROR_ON_MISSING_LIBRARIES=1") - - if (CMAKE_BUILD_TYPE MATCHES DEBUG) - set(WASM_FLAGS "${WASM_FLAGS} -g4") # generate debug information - set(WASM_FLAGS "${WASM_FLAGS} -s ASSERTIONS=2") # more runtime checks - else() - set(WASM_FLAGS "${WASM_FLAGS} -Os") # optimize for web (speed and size) - endif() - - set(WASM_MODULE_NAME "StoneFrameworkModule" CACHE STRING "Name of the WebAssembly module") - - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WASM_FLAGS}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WASM_FLAGS}") - - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${WASM_FLAGS}") # not always clear which flags are for the compiler and which one are for the linker -> pass them all to the linker too - # set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --js-library ${STONE_SOURCES_DIR}/Applications/Samples/samples-library.js") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --js-library ${STONE_SOURCES_DIR}/Platforms/Wasm/WasmWebService.js") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --js-library ${STONE_SOURCES_DIR}/Platforms/Wasm/WasmDelayedCallExecutor.js") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --js-library ${STONE_SOURCES_DIR}/Platforms/Wasm/default-library.js") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"ccall\", \"cwrap\"]'") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s EXPORT_NAME='\"${WASM_MODULE_NAME}\"'") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s ALLOW_MEMORY_GROWTH=1") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s TOTAL_MEMORY=536870912") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s TOTAL_STACK=128000000") - - add_definitions(-DORTHANC_ENABLE_WASM=1) - set(ORTHANC_SANDBOXED ON) - -elseif (ENABLE_QT OR ENABLE_SDL) - - set(ENABLE_NATIVE ON) - set(ORTHANC_SANDBOXED OFF) - set(ENABLE_CRYPTO_OPTIONS ON) - set(ENABLE_GOOGLE_TEST ON) - set(ENABLE_WEB_CLIENT ON) - -else() - set(ENABLE_NATIVE ON) - set(ENABLE_OPENGL OFF) - -endif() - - -##################################################################### -## Configuration for Orthanc -##################################################################### - -# include(../../Resources/CMake/Version.cmake) - -if (ORTHANC_STONE_VERSION STREQUAL "mainline") - set(ORTHANC_FRAMEWORK_VERSION "mainline") - set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "hg") -else() - set(ORTHANC_FRAMEWORK_VERSION "1.4.1") - set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "web") -endif() - -set(ORTHANC_FRAMEWORK_SOURCE "${ORTHANC_FRAMEWORK_DEFAULT_SOURCE}" CACHE STRING "Source of the Orthanc source code (can be \"hg\", \"archive\", \"web\" or \"path\")") -set(ORTHANC_FRAMEWORK_ARCHIVE "" CACHE STRING "Path to the Orthanc archive, if ORTHANC_FRAMEWORK_SOURCE is \"archive\"") -set(ORTHANC_FRAMEWORK_ROOT "" CACHE STRING "Path to the Orthanc source directory, if ORTHANC_FRAMEWORK_SOURCE is \"path\"") - -add_definitions( - -DORTHANC_ENABLE_LOGGING_PLUGIN=0 - ) - - -##################################################################### -## Build a static library containing the Orthanc Stone framework -##################################################################### - - -LIST(APPEND ORTHANC_BOOST_COMPONENTS program_options) - -include(../../../Resources/CMake/OrthancStoneConfiguration.cmake) - -add_library(OrthancStone STATIC - ${ORTHANC_STONE_SOURCES} - ) - -##################################################################### -## Build all the sample applications -##################################################################### - -include_directories(${ORTHANC_STONE_ROOT}) - -# files common to all samples -list(APPEND SAMPLE_APPLICATIONS_SOURCES - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/SampleInteractor.h - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/SampleApplicationBase.h - ) - -if (ENABLE_QT) - list(APPEND SAMPLE_APPLICATIONS_SOURCES - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/Qt/SampleQtApplicationRunner.h - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/Qt/SampleMainWindow.cpp - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/Qt/SampleMainWindowWithButtons.cpp - ) - - ORTHANC_QT_WRAP_UI(SAMPLE_APPLICATIONS_SOURCES - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/Qt/SampleMainWindow.ui - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/Qt/SampleMainWindowWithButtons.ui - ) - - ORTHANC_QT_WRAP_CPP(SAMPLE_APPLICATIONS_SOURCES - ${ORTHANC_STONE_ROOT}/Applications/Qt/QCairoWidget.h - ${ORTHANC_STONE_ROOT}/Applications/Qt/QStoneMainWindow.h - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/Qt/SampleMainWindow.h - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/Qt/SampleMainWindowWithButtons.h - ) -endif() - -if (ENABLE_NATIVE) - list(APPEND SAMPLE_APPLICATIONS_SOURCES - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/SampleMainNative.cpp - ) - -elseif (ENABLE_WASM) - - list(APPEND SAMPLE_APPLICATIONS_SOURCES - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/SampleMainWasm.cpp - ${STONE_WASM_SOURCES} - ) -endif() - - -macro(BuildSingleFileSample Target Header Sample) - add_executable(${Target} - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/${Header} - ${SAMPLE_APPLICATIONS_SOURCES} - ) - set_target_properties(${Target} PROPERTIES COMPILE_DEFINITIONS ORTHANC_STONE_SAMPLE=${Sample}) - target_link_libraries(${Target} OrthancStone) -endmacro() - - -if (ENABLE_SDL) - #BuildSingleFileSample(OrthancStoneEmpty EmptyApplication.h 1) - #BuildSingleFileSample(OrthancStoneTestPattern TestPatternApplication.h 2) - BuildSingleFileSample(OrthancStoneSingleFrame SingleFrameApplication.h 3) - #BuildSingleFileSample(OrthancStoneSingleVolume SingleVolumeApplication.h 4) - #BuildSingleFileSample(OrthancStoneBasicPetCtFusion 5) - #BuildSingleFileSample(OrthancStoneSynchronizedSeries 6) - #BuildSingleFileSample(OrthancStoneLayoutPetCtFusion 7) - BuildSingleFileSample(OrthancStoneSimpleViewerSingleFile SimpleViewerApplicationSingleFile.h 8) # we keep that one just as a sample before we convert another sample to this pattern - BuildSingleFileSample(OrthancStoneSingleFrameEditor SingleFrameEditorApplication.h 9) -endif() - -##### SimpleViewer sample (Qt and WASM only) ####### - -if (ENABLE_QT OR ENABLE_WASM) - - if (ENABLE_QT) - list(APPEND SIMPLE_VIEWER_APPLICATION_SOURCES - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/SimpleViewer/Qt/SimpleViewerMainWindow.cpp - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/SimpleViewer/Qt/SimpleViewerMainWindow.ui - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/SimpleViewer/Qt/mainQt.cpp - ) - - ORTHANC_QT_WRAP_UI(SIMPLE_VIEWER_APPLICATION_SOURCES - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/SimpleViewer/Qt/SimpleViewerMainWindow.ui - ) - - ORTHANC_QT_WRAP_CPP(SIMPLE_VIEWER_APPLICATION_SOURCES - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/SimpleViewer/Qt/SimpleViewerMainWindow.h - ) - -elseif (ENABLE_WASM) - list(APPEND SIMPLE_VIEWER_APPLICATION_SOURCES - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/SimpleViewer/Wasm/mainWasm.cpp - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/SimpleViewer/Wasm/SimpleViewerWasmApplicationAdapter.cpp - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/SimpleViewer/Wasm/SimpleViewerWasmApplicationAdapter.h - ${STONE_WASM_SOURCES} - ) - endif() - - add_executable(OrthancStoneSimpleViewer - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/SimpleViewer/AppStatus.h - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/SimpleViewer/MainWidgetInteractor.cpp - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/SimpleViewer/MainWidgetInteractor.h - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/SimpleViewer/SimpleViewerApplication.cpp - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/SimpleViewer/SimpleViewerApplication.h - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/SimpleViewer/ThumbnailInteractor.cpp - ${ORTHANC_STONE_ROOT}/Applications/Samples/Deprecated/SimpleViewer/ThumbnailInteractor.h - ${SIMPLE_VIEWER_APPLICATION_SOURCES} - ) - target_link_libraries(OrthancStoneSimpleViewer OrthancStone) - - BuildSingleFileSample(OrthancStoneSingleFrameEditor SingleFrameEditorApplication.h 9) -endif() - -##################################################################### -## Build the unit tests -##################################################################### - -if (ENABLE_NATIVE) - add_executable(UnitTests - ${GOOGLE_TEST_SOURCES} - ${ORTHANC_STONE_ROOT}/UnitTestsSources/GenericToolboxTests.cpp - ${ORTHANC_STONE_ROOT}/UnitTestsSources/ImageToolboxTests.cpp - ${ORTHANC_STONE_ROOT}/UnitTestsSources/PixelTestPatternsTests.cpp - ${ORTHANC_STONE_ROOT}/UnitTestsSources/TestCommands.cpp - ${ORTHANC_STONE_ROOT}/UnitTestsSources/TestMessageBroker.cpp - ${ORTHANC_STONE_ROOT}/UnitTestsSources/TestStrategy.cpp - ${ORTHANC_STONE_ROOT}/UnitTestsSources/TestStructureSet.cpp - ${ORTHANC_STONE_ROOT}/UnitTestsSources/UnitTestsMain.cpp - ) - - target_link_libraries(UnitTests OrthancStone) - - add_custom_command( - TARGET UnitTests - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy - "${ORTHANC_STONE_ROOT}/UnitTestsSources/72c773ac-5059f2c4-2e6a9120-4fd4bca1-45701661.json" - "$<TARGET_FILE_DIR:UnitTests>/72c773ac-5059f2c4-2e6a9120-4fd4bca1-45701661.json" - ) - -endif() - -##################################################################### -## Generate the documentation if Doxygen is present -##################################################################### - -find_package(Doxygen) -if (DOXYGEN_FOUND) - configure_file( - ${ORTHANC_STONE_ROOT}/Resources/OrthancStone.doxygen - ${CMAKE_CURRENT_BINARY_DIR}/OrthancStone.doxygen - @ONLY) - - add_custom_target(doc - ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/OrthancStone.doxygen - COMMENT "Generating documentation with Doxygen" VERBATIM - ) -else() - message("Doxygen not found. The documentation will not be built.") -endif()
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/CMakeLists.txt.old Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,248 +0,0 @@ -# Usage: see README file - -cmake_minimum_required(VERSION 2.8.3) - -# Automatically link Qt executables to qtmain target on Windows -# ("OLD" == do not link) -if(POLICY CMP0020) - cmake_policy(SET CMP0020 OLD) -endif() - -# Only interpret if() arguments as variables or keywords when unquoted. -# NEW = do NOT dereference *quoted* variables -if(POLICY CMP0054) - cmake_policy(SET CMP0054 NEW) -endif() - -project(OrthancStone) - -include(../../Resources/CMake/OrthancStoneParameters.cmake) - -#set(ENABLE_DCMTK ON) - -set(ENABLE_SDL OFF CACHE BOOL "Target SDL Native application") -set(ENABLE_QT OFF CACHE BOOL "Target Qt Native application") -set(ENABLE_WASM OFF CACHE BOOL "Target WASM application") - -# TODO: replace or compute STONE_SOURCES_DIR from CMAKE_CURRENT_LIST_FILE - -if (ENABLE_WASM) - ##################################################################### - ## Configuration of the Emscripten compiler for WebAssembly target - ##################################################################### - - set(WASM_FLAGS "-s WASM=1 -O0 -g0") - message("*****************************************************************************") - message("WARNING: optimizations are disabled in emcc!!! Enable them for production use") - message("*****************************************************************************") - set(WASM_MODULE_NAME "StoneFrameworkModule" CACHE STRING "Name of the WebAssembly module") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WASM_FLAGS}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WASM_FLAGS}") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --js-library ${STONE_SOURCES_DIR}/Platforms/Wasm/WasmWebService.js --js-library ${STONE_SOURCES_DIR}/Platforms/Wasm/WasmDelayedCallExecutor.js --js-library ${STONE_SOURCES_DIR}/Platforms/Wasm/default-library.js -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"ccall\", \"cwrap\"]'") - - # Handling of memory - #set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s ALLOW_MEMORY_GROWTH=1") # Resize - #set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s TOTAL_MEMORY=536870912") # 512MB - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s EXPORT_NAME='\"${WASM_MODULE_NAME}\"' -s ALLOW_MEMORY_GROWTH=1 -s TOTAL_MEMORY=536870912 -s TOTAL_STACK=128000000") # 512MB + resize - #set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -s TOTAL_MEMORY=1073741824") # 1GB + resize - - # To debug exceptions - #set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s DEMANGLE_SUPPORT=1 -s ASSERTIONS=2") - - add_definitions(-DORTHANC_ENABLE_WASM=1) - set(ORTHANC_SANDBOXED ON) - -elseif (ENABLE_QT OR ENABLE_SDL) - - set(ENABLE_NATIVE ON) - set(ORTHANC_SANDBOXED OFF) - set(ENABLE_CRYPTO_OPTIONS ON) - set(ENABLE_GOOGLE_TEST ON) - set(ENABLE_WEB_CLIENT ON) - -endif() - -##################################################################### -## Configuration for Orthanc -##################################################################### - -# include(../../Resources/CMake/Version.cmake) - -if (ORTHANC_STONE_VERSION STREQUAL "mainline") - set(ORTHANC_FRAMEWORK_VERSION "mainline") - set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "hg") -else() - set(ORTHANC_FRAMEWORK_VERSION "1.4.1") - set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "web") -endif() - -set(ORTHANC_FRAMEWORK_SOURCE "${ORTHANC_FRAMEWORK_DEFAULT_SOURCE}" CACHE STRING "Source of the Orthanc source code (can be \"hg\", \"archive\", \"web\" or \"path\")") -set(ORTHANC_FRAMEWORK_ARCHIVE "" CACHE STRING "Path to the Orthanc archive, if ORTHANC_FRAMEWORK_SOURCE is \"archive\"") -set(ORTHANC_FRAMEWORK_ROOT "" CACHE STRING "Path to the Orthanc source directory, if ORTHANC_FRAMEWORK_SOURCE is \"path\"") - -##################################################################### -## Build a static library containing the Orthanc Stone framework -##################################################################### - -LIST(APPEND ORTHANC_BOOST_COMPONENTS program_options) - -include(../../Resources/CMake/OrthancStoneConfiguration.cmake) - -add_library(OrthancStone STATIC - ${ORTHANC_STONE_SOURCES} - ) - -##################################################################### -## Build all the sample applications -##################################################################### - -include_directories(${ORTHANC_STONE_ROOT}) - -# files common to all samples -list(APPEND SAMPLE_APPLICATIONS_SOURCES - ${ORTHANC_STONE_ROOT}/Applications/Samples/SampleInteractor.h - ${ORTHANC_STONE_ROOT}/Applications/Samples/SampleApplicationBase.h - ) - -if (ENABLE_QT) - list(APPEND SAMPLE_APPLICATIONS_SOURCES - ${ORTHANC_STONE_ROOT}/Applications/Samples/Qt/SampleQtApplicationRunner.h - ${ORTHANC_STONE_ROOT}/Applications/Samples/Qt/SampleMainWindow.cpp - ${ORTHANC_STONE_ROOT}/Applications/Samples/Qt/SampleMainWindowWithButtons.cpp - ) - - ORTHANC_QT_WRAP_UI(SAMPLE_APPLICATIONS_SOURCES - ${ORTHANC_STONE_ROOT}/Applications/Samples/Qt/SampleMainWindow.ui - ${ORTHANC_STONE_ROOT}/Applications/Samples/Qt/SampleMainWindowWithButtons.ui - ) - - ORTHANC_QT_WRAP_CPP(SAMPLE_APPLICATIONS_SOURCES - ${ORTHANC_STONE_ROOT}/Applications/Qt/QCairoWidget.h - ${ORTHANC_STONE_ROOT}/Applications/Qt/QStoneMainWindow.h - ${ORTHANC_STONE_ROOT}/Applications/Samples/Qt/SampleMainWindow.h - ${ORTHANC_STONE_ROOT}/Applications/Samples/Qt/SampleMainWindowWithButtons.h - ) -endif() - -if (ENABLE_NATIVE) - list(APPEND SAMPLE_APPLICATIONS_SOURCES - ${ORTHANC_STONE_ROOT}/Applications/Samples/SampleMainNative.cpp - ) - -elseif (ENABLE_WASM) - - list(APPEND SAMPLE_APPLICATIONS_SOURCES - ${ORTHANC_STONE_ROOT}/Applications/Samples/SampleMainWasm.cpp - ${STONE_WASM_SOURCES} - ) -endif() - - -macro(BuildSingleFileSample Target Header Sample) - add_executable(${Target} - ${ORTHANC_STONE_ROOT}/Applications/Samples/${Header} - ${SAMPLE_APPLICATIONS_SOURCES} - ) - set_target_properties(${Target} PROPERTIES COMPILE_DEFINITIONS ORTHANC_STONE_SAMPLE=${Sample}) - target_link_libraries(${Target} OrthancStone) - - if (ENABLE_QT AND (CMAKE_SYSTEM_NAME STREQUAL "Windows")) - message("(ENABLE_QT and (CMAKE_SYSTEM_NAME matches \"Windows\")) is true") - add_custom_command( - TARGET ${Target} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:Qt5::Core> $<TARGET_FILE_DIR:${Target}> - COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:Qt5::Widgets> $<TARGET_FILE_DIR:${Target}> - COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:Qt5::Gui> $<TARGET_FILE_DIR:${Target}> - ) - endif() -endmacro() - -#BuildSingleFileSample(OrthancStoneEmpty EmptyApplication.h 1) -#BuildSingleFileSample(OrthancStoneTestPattern TestPatternApplication.h 2) -BuildSingleFileSample(OrthancStoneSingleFrame SingleFrameApplication.h 3) -#BuildSingleFileSample(OrthancStoneSingleVolume SingleVolumeApplication.h 4) -#BuildSingleFileSample(OrthancStoneBasicPetCtFusion 5) -#BuildSingleFileSample(OrthancStoneSynchronizedSeries 6) -#BuildSingleFileSample(OrthancStoneLayoutPetCtFusion 7) -BuildSingleFileSample(OrthancStoneSimpleViewerSingleFile SimpleViewerApplicationSingleFile.h 8) # we keep that one just as a sample before we convert another sample to this pattern -BuildSingleFileSample(OrthancStoneSingleFrameEditor SingleFrameEditorApplication.h 9) - -##### SimpleViewer sample (Qt and WASM only) ####### - -if (ENABLE_QT OR ENABLE_WASM) - - # GenerateCodeFromFlatBufferSchema("${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/ApplicationCommands.fbs") - - list(APPEND SIMPLE_VIEWER_APPLICATION_SOURCES ${FLATC_AUTOGENERATED_SOURCES}) - message(STATUS "SIMPLE_VIEWER_APPLICATION_SOURCES = ${SIMPLE_VIEWER_APPLICATION_SOURCES}") - message(STATUS "FLATC_AUTOGENERATED_SOURCES = ${FLATC_AUTOGENERATED_SOURCES}") - - if (ENABLE_QT) - list(APPEND SIMPLE_VIEWER_APPLICATION_SOURCES - ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/Qt/SimpleViewerMainWindow.cpp - ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/Qt/SimpleViewerMainWindow.ui - ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/Qt/mainQt.cpp - ) - - ORTHANC_QT_WRAP_UI(SIMPLE_VIEWER_APPLICATION_SOURCES - ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/Qt/SimpleViewerMainWindow.ui - ) - - ORTHANC_QT_WRAP_CPP(SIMPLE_VIEWER_APPLICATION_SOURCES - ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/Qt/SimpleViewerMainWindow.h - ) - -elseif (ENABLE_WASM) - list(APPEND SIMPLE_VIEWER_APPLICATION_SOURCES - ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/Wasm/mainWasm.cpp - ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/Wasm/SimpleViewerWasmApplicationAdapter.cpp - ${STONE_WASM_SOURCES} - ) - endif() - - add_executable(OrthancStoneSimpleViewer - ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/SimpleViewerApplication.cpp - ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/ThumbnailInteractor.cpp - ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/MainWidgetInteractor.cpp - ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/AppStatus.h - ${ORTHANC_STONE_ROOT}/Applications/Samples/SimpleViewer/Messages.h - ${SIMPLE_VIEWER_APPLICATION_SOURCES} - ) - target_link_libraries(OrthancStoneSimpleViewer OrthancStone) - -endif() - -##################################################################### -## Build the unit tests -##################################################################### - -if (ENABLE_NATIVE) - add_executable(UnitTests - ${GOOGLE_TEST_SOURCES} - ${ORTHANC_STONE_ROOT}/UnitTestsSources/TestCommands.cpp - ${ORTHANC_STONE_ROOT}/UnitTestsSources/TestExceptions.cpp - ${ORTHANC_STONE_ROOT}/UnitTestsSources/TestMessageBroker.cpp - ${ORTHANC_STONE_ROOT}/UnitTestsSources/UnitTestsMain.cpp - ) - - target_link_libraries(UnitTests OrthancStone) -endif() - -##################################################################### -## Generate the documentation if Doxygen is present -##################################################################### - -find_package(Doxygen) -if (DOXYGEN_FOUND) - configure_file( - ${ORTHANC_STONE_ROOT}/Resources/OrthancStone.doxygen - ${CMAKE_CURRENT_BINARY_DIR}/OrthancStone.doxygen - @ONLY) - - add_custom_target(doc - ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/OrthancStone.doxygen - COMMENT "Generating documentation with Doxygen" VERBATIM - ) -else() - message("Doxygen not found. The documentation will not be built.") -endif()
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/EmptyApplication.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "SampleApplicationBase.h" - -#include "../../../Framework/Widgets/EmptyWidget.h" - -namespace OrthancStone -{ - namespace Samples - { - class EmptyApplication : public SampleApplicationBase - { - public: - virtual void DeclareStartupOptions(boost::program_options::options_description& options) - { - boost::program_options::options_description generic("Sample options"); - generic.add_options() - ("red", boost::program_options::value<int>()->default_value(255), "Background color: red channel") - ("green", boost::program_options::value<int>()->default_value(0), "Background color: green channel") - ("blue", boost::program_options::value<int>()->default_value(0), "Background color: blue channel") - ; - - options.add(generic); - } - - virtual void Initialize(IStatusBar& statusBar, - const boost::program_options::variables_map& parameters) - { - int red = parameters["red"].as<int>(); - int green = parameters["green"].as<int>(); - int blue = parameters["blue"].as<int>(); - - context_->SetCentralWidget(new EmptyWidget(red, green, blue)); - } - }; - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/LayoutPetCtFusionApplication.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,398 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "SampleInteractor.h" - -#include "../../../Framework/Layers/ReferenceLineFactory.h" -#include "../../../Framework/Layers/DicomStructureSetSlicer.h" -#include "../../../Framework/Widgets/LayoutWidget.h" - -#include <Core/Logging.h> - -namespace OrthancStone -{ - namespace Samples - { - class LayoutPetCtFusionApplication : - public SampleApplicationBase, - public LayeredSceneWidget::ISliceObserver, - public WorldSceneWidget::IWorldObserver - { - private: - class Interactor : public SampleInteractor - { - private: - LayoutPetCtFusionApplication& that_; - - public: - Interactor(LayoutPetCtFusionApplication& that, - VolumeImage& volume, - VolumeProjection projection, - bool reverse) : - SampleInteractor(volume, projection, reverse), - that_(that) - { - } - - virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, - const SliceGeometry& slice, - const ViewportGeometry& view, - MouseButton button, - double x, - double y, - IStatusBar* statusBar) - { - if (button == MouseButton_Left) - { - // Center the sibling views over the clicked point - Vector p = slice.MapSliceToWorldCoordinates(x, y); - - if (statusBar != NULL) - { - char buf[64]; - sprintf(buf, "Click on coordinates (%.02f,%.02f,%.02f) in cm", p[0] / 10.0, p[1] / 10.0, p[2] / 10.0); - statusBar->SetMessage(buf); - } - - that_.interactorAxial_->LookupSliceContainingPoint(*that_.ctAxial_, p); - that_.interactorCoronal_->LookupSliceContainingPoint(*that_.ctCoronal_, p); - that_.interactorSagittal_->LookupSliceContainingPoint(*that_.ctSagittal_, p); - } - - return NULL; - } - - virtual void KeyPressed(WorldSceneWidget& widget, - char key, - KeyboardModifiers modifiers, - IStatusBar* statusBar) - { - if (key == 's') - { - that_.FitContent(); - } - } - }; - - bool processingEvent_; - Interactor* interactorAxial_; - Interactor* interactorCoronal_; - Interactor* interactorSagittal_; - LayeredSceneWidget* ctAxial_; - LayeredSceneWidget* ctCoronal_; - LayeredSceneWidget* ctSagittal_; - LayeredSceneWidget* petAxial_; - LayeredSceneWidget* petCoronal_; - LayeredSceneWidget* petSagittal_; - LayeredSceneWidget* fusionAxial_; - LayeredSceneWidget* fusionCoronal_; - LayeredSceneWidget* fusionSagittal_; - - - void FitContent() - { - petAxial_->FitContent(); - petCoronal_->FitContent(); - petSagittal_->FitContent(); - } - - - void AddLayer(LayeredSceneWidget& widget, - VolumeImage& volume, - bool isCt) - { - size_t layer; - widget.AddLayer(layer, new VolumeImage::LayerFactory(volume)); - - if (isCt) - { - RenderStyle style; - style.windowing_ = ImageWindowing_Bone; - widget.SetLayerStyle(layer, style); - } - else - { - RenderStyle style; - style.applyLut_ = true; - style.alpha_ = (layer == 0 ? 1.0f : 0.5f); - widget.SetLayerStyle(layer, style); - } - } - - - void ConnectSiblingLocations(LayeredSceneWidget& axial, - LayeredSceneWidget& coronal, - LayeredSceneWidget& sagittal) - { - ReferenceLineFactory::Configure(axial, coronal); - ReferenceLineFactory::Configure(axial, sagittal); - ReferenceLineFactory::Configure(coronal, sagittal); - } - - - void SynchronizeView(const WorldSceneWidget& source, - const ViewportGeometry& view, - LayeredSceneWidget& widget1, - LayeredSceneWidget& widget2, - LayeredSceneWidget& widget3) - { - if (&source == &widget1 || - &source == &widget2 || - &source == &widget3) - { - if (&source != &widget1) - { - widget1.SetView(view); - } - - if (&source != &widget2) - { - widget2.SetView(view); - } - - if (&source != &widget3) - { - widget3.SetView(view); - } - } - } - - - void SynchronizeSlice(const LayeredSceneWidget& source, - const SliceGeometry& slice, - LayeredSceneWidget& widget1, - LayeredSceneWidget& widget2, - LayeredSceneWidget& widget3) - { - if (&source == &widget1 || - &source == &widget2 || - &source == &widget3) - { - if (&source != &widget1) - { - widget1.SetSlice(slice); - } - - if (&source != &widget2) - { - widget2.SetSlice(slice); - } - - if (&source != &widget3) - { - widget3.SetSlice(slice); - } - } - } - - - LayeredSceneWidget* CreateWidget() - { - std::unique_ptr<LayeredSceneWidget> widget(new LayeredSceneWidget); - widget->Register(dynamic_cast<WorldSceneWidget::IWorldObserver&>(*this)); - widget->Register(dynamic_cast<LayeredSceneWidget::ISliceObserver&>(*this)); - return widget.release(); - } - - - void CreateLayout(BasicApplicationContext& context) - { - std::unique_ptr<OrthancStone::LayoutWidget> layout(new OrthancStone::LayoutWidget); - layout->SetBackgroundCleared(true); - //layout->SetBackgroundColor(255,0,0); - layout->SetPadding(5); - - OrthancStone::LayoutWidget& layoutA = dynamic_cast<OrthancStone::LayoutWidget&> - (layout->AddWidget(new OrthancStone::LayoutWidget)); - layoutA.SetPadding(0, 0, 0, 0, 5); - layoutA.SetVertical(); - petAxial_ = &dynamic_cast<LayeredSceneWidget&>(layoutA.AddWidget(CreateWidget())); - OrthancStone::LayoutWidget& layoutA2 = dynamic_cast<OrthancStone::LayoutWidget&> - (layoutA.AddWidget(new OrthancStone::LayoutWidget)); - layoutA2.SetPadding(0, 0, 0, 0, 5); - petSagittal_ = &dynamic_cast<LayeredSceneWidget&>(layoutA2.AddWidget(CreateWidget())); - petCoronal_ = &dynamic_cast<LayeredSceneWidget&>(layoutA2.AddWidget(CreateWidget())); - - OrthancStone::LayoutWidget& layoutB = dynamic_cast<OrthancStone::LayoutWidget&> - (layout->AddWidget(new OrthancStone::LayoutWidget)); - layoutB.SetPadding(0, 0, 0, 0, 5); - layoutB.SetVertical(); - ctAxial_ = &dynamic_cast<LayeredSceneWidget&>(layoutB.AddWidget(CreateWidget())); - OrthancStone::LayoutWidget& layoutB2 = dynamic_cast<OrthancStone::LayoutWidget&> - (layoutB.AddWidget(new OrthancStone::LayoutWidget)); - layoutB2.SetPadding(0, 0, 0, 0, 5); - ctSagittal_ = &dynamic_cast<LayeredSceneWidget&>(layoutB2.AddWidget(CreateWidget())); - ctCoronal_ = &dynamic_cast<LayeredSceneWidget&>(layoutB2.AddWidget(CreateWidget())); - - OrthancStone::LayoutWidget& layoutC = dynamic_cast<OrthancStone::LayoutWidget&> - (layout->AddWidget(new OrthancStone::LayoutWidget)); - layoutC.SetPadding(0, 0, 0, 0, 5); - layoutC.SetVertical(); - fusionAxial_ = &dynamic_cast<LayeredSceneWidget&>(layoutC.AddWidget(CreateWidget())); - OrthancStone::LayoutWidget& layoutC2 = dynamic_cast<OrthancStone::LayoutWidget&> - (layoutC.AddWidget(new OrthancStone::LayoutWidget)); - layoutC2.SetPadding(0, 0, 0, 0, 5); - fusionSagittal_ = &dynamic_cast<LayeredSceneWidget&>(layoutC2.AddWidget(CreateWidget())); - fusionCoronal_ = &dynamic_cast<LayeredSceneWidget&>(layoutC2.AddWidget(CreateWidget())); - - context.SetCentralWidget(layout.release()); - } - - - public: - virtual void DeclareCommandLineOptions(boost::program_options::options_description& options) - { - boost::program_options::options_description generic("Sample options"); - generic.add_options() - ("ct", boost::program_options::value<std::string>(), - "Orthanc ID of the CT series") - ("pet", boost::program_options::value<std::string>(), - "Orthanc ID of the PET series") - ("rt", boost::program_options::value<std::string>(), - "Orthanc ID of the DICOM RT-STRUCT series (optional)") - ("threads", boost::program_options::value<unsigned int>()->default_value(3), - "Number of download threads for the CT series") - ; - - options.add(generic); - } - - virtual void Initialize(BasicApplicationContext& context, - IStatusBar& statusBar, - const boost::program_options::variables_map& parameters) - { - using namespace OrthancStone; - - processingEvent_ = true; - - if (parameters.count("ct") != 1 || - parameters.count("pet") != 1) - { - LOG(ERROR) << "The series ID is missing"; - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - std::string ct = parameters["ct"].as<std::string>(); - std::string pet = parameters["pet"].as<std::string>(); - unsigned int threads = parameters["threads"].as<unsigned int>(); - - VolumeImage& ctVolume = context.AddSeriesVolume(ct, true /* progressive download */, threads); - VolumeImage& petVolume = context.AddSeriesVolume(pet, true /* progressive download */, 1); - - // Take the PET volume as the reference for the slices - interactorAxial_ = &dynamic_cast<Interactor&> - (context.AddInteractor(new Interactor(*this, petVolume, VolumeProjection_Axial, false))); - interactorCoronal_ = &dynamic_cast<Interactor&> - (context.AddInteractor(new Interactor(*this, petVolume, VolumeProjection_Coronal, false))); - interactorSagittal_ = &dynamic_cast<Interactor&> - (context.AddInteractor(new Interactor(*this, petVolume, VolumeProjection_Sagittal, true))); - - CreateLayout(context); - - AddLayer(*ctAxial_, ctVolume, true); - AddLayer(*ctCoronal_, ctVolume, true); - AddLayer(*ctSagittal_, ctVolume, true); - - AddLayer(*petAxial_, petVolume, false); - AddLayer(*petCoronal_, petVolume, false); - AddLayer(*petSagittal_, petVolume, false); - - AddLayer(*fusionAxial_, ctVolume, true); - AddLayer(*fusionAxial_, petVolume, false); - AddLayer(*fusionCoronal_, ctVolume, true); - AddLayer(*fusionCoronal_, petVolume, false); - AddLayer(*fusionSagittal_, ctVolume, true); - AddLayer(*fusionSagittal_, petVolume, false); - - if (parameters.count("rt") == 1) - { - DicomStructureSet& rtStruct = context.AddStructureSet(parameters["rt"].as<std::string>()); - - Vector p = rtStruct.GetStructureCenter(0); - interactorAxial_->GetCursor().LookupSliceContainingPoint(p); - - ctAxial_->AddLayer(new DicomStructureSetSlicer(rtStruct)); - petAxial_->AddLayer(new DicomStructureSetSlicer(rtStruct)); - fusionAxial_->AddLayer(new DicomStructureSetSlicer(rtStruct)); - } - - ConnectSiblingLocations(*ctAxial_, *ctCoronal_, *ctSagittal_); - ConnectSiblingLocations(*petAxial_, *petCoronal_, *petSagittal_); - ConnectSiblingLocations(*fusionAxial_, *fusionCoronal_, *fusionSagittal_); - - interactorAxial_->AddWidget(*ctAxial_); - interactorAxial_->AddWidget(*petAxial_); - interactorAxial_->AddWidget(*fusionAxial_); - - interactorCoronal_->AddWidget(*ctCoronal_); - interactorCoronal_->AddWidget(*petCoronal_); - interactorCoronal_->AddWidget(*fusionCoronal_); - - interactorSagittal_->AddWidget(*ctSagittal_); - interactorSagittal_->AddWidget(*petSagittal_); - interactorSagittal_->AddWidget(*fusionSagittal_); - - processingEvent_ = false; - - statusBar.SetMessage("Use the key \"t\" to toggle the fullscreen mode"); - statusBar.SetMessage("Use the key \"s\" to reinitialize the layout"); - } - - virtual void NotifySizeChange(const WorldSceneWidget& source, - ViewportGeometry& view) - { - view.FitContent(); - } - - virtual void NotifyViewChange(const WorldSceneWidget& source, - const ViewportGeometry& view) - { - if (!processingEvent_) // Avoid reentrant calls - { - processingEvent_ = true; - - SynchronizeView(source, view, *ctAxial_, *petAxial_, *fusionAxial_); - SynchronizeView(source, view, *ctCoronal_, *petCoronal_, *fusionCoronal_); - SynchronizeView(source, view, *ctSagittal_, *petSagittal_, *fusionSagittal_); - - processingEvent_ = false; - } - } - - virtual void NotifySliceContentChange(const LayeredSceneWidget& source, - const SliceGeometry& slice) - { - if (!processingEvent_) // Avoid reentrant calls - { - processingEvent_ = true; - - SynchronizeSlice(source, slice, *ctAxial_, *petAxial_, *fusionAxial_); - SynchronizeSlice(source, slice, *ctCoronal_, *petCoronal_, *fusionCoronal_); - SynchronizeSlice(source, slice, *ctSagittal_, *petSagittal_, *fusionSagittal_); - - processingEvent_ = false; - } - } - }; - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Qt/SampleMainWindow.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#include "SampleMainWindow.h" - -/** - * Don't use "ui_MainWindow.h" instead of <ui_MainWindow.h> below, as - * this makes CMake unable to detect when the UI file changes. - **/ -#include <ui_SampleMainWindow.h> -#include "../../../Applications/Samples/SampleApplicationBase.h" - -namespace OrthancStone -{ - namespace Samples - { - - SampleMainWindow::SampleMainWindow( - OrthancStone::NativeStoneApplicationContext& context, - OrthancStone::Samples::SampleSingleCanvasApplicationBase& stoneSampleApplication, - QWidget *parent) : - QStoneMainWindow(context, parent), - ui_(new Ui::SampleMainWindow), - stoneSampleApplication_(stoneSampleApplication) - { - ui_->setupUi(this); - SetCentralStoneWidget(*ui_->cairoCentralWidget); - } - - SampleMainWindow::~SampleMainWindow() - { - delete ui_; - } - - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Qt/SampleMainWindow.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ -#pragma once - -#include "../../../Qt/QCairoWidget.h" -#include "../../../Qt/QStoneMainWindow.h" - -namespace Ui -{ - class SampleMainWindow; -} - -namespace OrthancStone -{ - namespace Samples - { - - class SampleSingleCanvasApplicationBase; - - class SampleMainWindow : public QStoneMainWindow - { - Q_OBJECT - - private: - Ui::SampleMainWindow* ui_; - SampleSingleCanvasApplicationBase& stoneSampleApplication_; - - public: - explicit SampleMainWindow(OrthancStone::NativeStoneApplicationContext& context, SampleSingleCanvasApplicationBase& stoneSampleApplication, QWidget *parent = 0); - ~SampleMainWindow(); - }; - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Qt/SampleMainWindow.ui Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>SampleMainWindow</class> - <widget class="QMainWindow" name="SampleMainWindow"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>903</width> - <height>634</height> - </rect> - </property> - <property name="minimumSize"> - <size> - <width>500</width> - <height>300</height> - </size> - </property> - <property name="baseSize"> - <size> - <width>500</width> - <height>300</height> - </size> - </property> - <property name="windowTitle"> - <string>Stone of Orthanc</string> - </property> - <property name="layoutDirection"> - <enum>Qt::LeftToRight</enum> - </property> - <widget class="QWidget" name="centralwidget"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="layoutDirection"> - <enum>Qt::LeftToRight</enum> - </property> - <layout class="QVBoxLayout" name="verticalLayout_2" stretch="0"> - <property name="sizeConstraint"> - <enum>QLayout::SetDefaultConstraint</enum> - </property> - <item> - <widget class="QCairoWidget" name="cairoCentralWidget"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>500</height> - </size> - </property> - </widget> - </item> - </layout> - </widget> - <widget class="QMenuBar" name="menubar"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>903</width> - <height>22</height> - </rect> - </property> - <widget class="QMenu" name="menuTest"> - <property name="title"> - <string>Test</string> - </property> - </widget> - <addaction name="menuTest"/> - </widget> - <widget class="QStatusBar" name="statusbar"/> - </widget> - <customwidgets> - <customwidget> - <class>QCairoWidget</class> - <extends>QGraphicsView</extends> - <header location="global">QCairoWidget.h</header> - </customwidget> - </customwidgets> - <resources/> - <connections/> -</ui>
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Qt/SampleMainWindowWithButtons.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#include "SampleMainWindow.h" - -/** - * Don't use "ui_MainWindow.h" instead of <ui_MainWindow.h> below, as - * this makes CMake unable to detect when the UI file changes. - **/ -#include <ui_SampleMainWindowWithButtons.h> -#include "../../../Applications/Samples/SampleApplicationBase.h" - -namespace OrthancStone -{ - namespace Samples - { - - SampleMainWindowWithButtons::SampleMainWindowWithButtons( - OrthancStone::NativeStoneApplicationContext& context, - OrthancStone::Samples::SampleSingleCanvasWithButtonsApplicationBase& stoneSampleApplication, - QWidget *parent) : - QStoneMainWindow(context, parent), - ui_(new Ui::SampleMainWindowWithButtons), - stoneSampleApplication_(stoneSampleApplication) - { - ui_->setupUi(this); - SetCentralStoneWidget(*ui_->cairoCentralWidget); - -#if QT_VERSION >= 0x050000 - connect(ui_->toolButton1, &QToolButton::clicked, this, &SampleMainWindowWithButtons::tool1Clicked); - connect(ui_->toolButton2, &QToolButton::clicked, this, &SampleMainWindowWithButtons::tool2Clicked); - connect(ui_->pushButton1, &QPushButton::clicked, this, &SampleMainWindowWithButtons::pushButton1Clicked); - connect(ui_->pushButton1, &QPushButton::clicked, this, &SampleMainWindowWithButtons::pushButton2Clicked); -#else - connect(ui_->toolButton1, SIGNAL(clicked()), this, SLOT(tool1Clicked())); - connect(ui_->toolButton2, SIGNAL(clicked()), this, SLOT(tool2Clicked())); - connect(ui_->pushButton1, SIGNAL(clicked()), this, SLOT(pushButton1Clicked())); - connect(ui_->pushButton1, SIGNAL(clicked()), this, SLOT(pushButton2Clicked())); -#endif - - std::string pushButton1Name; - std::string pushButton2Name; - std::string tool1Name; - std::string tool2Name; - stoneSampleApplication_.GetButtonNames(pushButton1Name, pushButton2Name, tool1Name, tool2Name); - - ui_->toolButton1->setText(QString::fromStdString(tool1Name)); - ui_->toolButton2->setText(QString::fromStdString(tool2Name)); - ui_->pushButton1->setText(QString::fromStdString(pushButton1Name)); - ui_->pushButton2->setText(QString::fromStdString(pushButton2Name)); - } - - SampleMainWindowWithButtons::~SampleMainWindowWithButtons() - { - delete ui_; - } - - void SampleMainWindowWithButtons::tool1Clicked() - { - stoneSampleApplication_.OnTool1Clicked(); - } - - void SampleMainWindowWithButtons::tool2Clicked() - { - stoneSampleApplication_.OnTool2Clicked(); - } - - void SampleMainWindowWithButtons::pushButton1Clicked() - { - stoneSampleApplication_.OnPushButton1Clicked(); - } - - void SampleMainWindowWithButtons::pushButton2Clicked() - { - stoneSampleApplication_.OnPushButton2Clicked(); - } - - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Qt/SampleMainWindowWithButtons.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ -#pragma once - -#include "../../../Qt/QCairoWidget.h" -#include "../../../Qt/QStoneMainWindow.h" - -namespace Ui -{ - class SampleMainWindowWithButtons; -} - -namespace OrthancStone -{ - namespace Samples - { - - class SampleSingleCanvasWithButtonsApplicationBase; - - class SampleMainWindowWithButtons : public QStoneMainWindow - { - Q_OBJECT - - private: - Ui::SampleMainWindowWithButtons* ui_; - SampleSingleCanvasWithButtonsApplicationBase& stoneSampleApplication_; - - public: - explicit SampleMainWindowWithButtons(OrthancStone::NativeStoneApplicationContext& context, SampleSingleCanvasWithButtonsApplicationBase& stoneSampleApplication, QWidget *parent = 0); - ~SampleMainWindowWithButtons(); - - private slots: - void tool1Clicked(); - void tool2Clicked(); - void pushButton1Clicked(); - void pushButton2Clicked(); - }; - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Qt/SampleMainWindowWithButtons.ui Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,130 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>SampleMainWindowWithButtons</class> - <widget class="QMainWindow" name="SampleMainWindowWithButtons"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>903</width> - <height>634</height> - </rect> - </property> - <property name="minimumSize"> - <size> - <width>500</width> - <height>300</height> - </size> - </property> - <property name="baseSize"> - <size> - <width>500</width> - <height>300</height> - </size> - </property> - <property name="windowTitle"> - <string>Stone of Orthanc</string> - </property> - <property name="layoutDirection"> - <enum>Qt::LeftToRight</enum> - </property> - <widget class="QWidget" name="centralwidget"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="layoutDirection"> - <enum>Qt::LeftToRight</enum> - </property> - <layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,0"> - <property name="sizeConstraint"> - <enum>QLayout::SetDefaultConstraint</enum> - </property> - <item> - <widget class="QCairoWidget" name="cairoCentralWidget"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>500</height> - </size> - </property> - </widget> - </item> - <item> - <widget class="QGroupBox" name="horizontalGroupBox"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>100</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>100</height> - </size> - </property> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QToolButton" name="toolButton1"> - <property name="text"> - <string>tool1</string> - </property> - </widget> - </item> - <item> - <widget class="QToolButton" name="toolButton2"> - <property name="text"> - <string>tool2</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButton1"> - <property name="text"> - <string>action1</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButton2"> - <property name="text"> - <string>action2</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - <widget class="QMenuBar" name="menubar"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>903</width> - <height>22</height> - </rect> - </property> - <widget class="QMenu" name="menuTest"> - <property name="title"> - <string>Test</string> - </property> - </widget> - <addaction name="menuTest"/> - </widget> - <widget class="QStatusBar" name="statusbar"/> - </widget> - <customwidgets> - <customwidget> - <class>QCairoWidget</class> - <extends>QGraphicsView</extends> - <header location="global">QCairoWidget.h</header> - </customwidget> - </customwidgets> - <resources/> - <connections/> -</ui>
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Qt/SampleQtApplicationRunner.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../../Qt/QtStoneApplicationRunner.h" - -#if ORTHANC_ENABLE_QT != 1 -#error this file shall be included only with the ORTHANC_ENABLE_QT set to 1 -#endif - -namespace OrthancStone -{ - namespace Samples - { - class SampleQtApplicationRunner : public OrthancStone::QtStoneApplicationRunner - { - protected: - virtual void InitializeMainWindow(OrthancStone::NativeStoneApplicationContext& context) - { - window_.reset(application_.CreateQtMainWindow()); - } - public: - SampleQtApplicationRunner(MessageBroker& broker, - SampleApplicationBase& application) - : OrthancStone::QtStoneApplicationRunner(broker, application) - { - } - - }; - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SampleApplicationBase.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,133 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../../Applications/IStoneApplication.h" -#include "../../../Framework/Deprecated/Widgets/WorldSceneWidget.h" - -#if ORTHANC_ENABLE_WASM==1 -#include "../../../Platforms/Wasm/WasmPlatformApplicationAdapter.h" -#include "../../../Platforms/Wasm/Defaults.h" -#endif - -#if ORTHANC_ENABLE_QT==1 -#include "Qt/SampleMainWindow.h" -#include "Qt/SampleMainWindowWithButtons.h" -#endif - -namespace OrthancStone -{ - namespace Samples - { - class SampleApplicationBase : public IStoneApplication - { - private: - boost::shared_ptr<Deprecated::IWidget> mainWidget_; - - public: - virtual void Initialize(StoneApplicationContext* context, - Deprecated::IStatusBar& statusBar, - const boost::program_options::variables_map& parameters) ORTHANC_OVERRIDE - { - } - - virtual std::string GetTitle() const ORTHANC_OVERRIDE - { - return "Stone of Orthanc - Sample"; - } - - /** - * In the basic samples, the commands are handled by the platform adapter and NOT - * by the application handler - */ - virtual void HandleSerializedMessage(const char* data) ORTHANC_OVERRIDE {}; - - - virtual void Finalize() ORTHANC_OVERRIDE {} - - virtual void SetCentralWidget(boost::shared_ptr<Deprecated::IWidget> widget) ORTHANC_OVERRIDE - { - mainWidget_ = widget; - } - - virtual boost::shared_ptr<Deprecated::IWidget> GetCentralWidget() ORTHANC_OVERRIDE - { - return mainWidget_; - } - -#if ORTHANC_ENABLE_WASM==1 - // default implementations for a single canvas named "canvas" in the HTML and an emtpy WasmApplicationAdapter - - virtual void InitializeWasm() ORTHANC_OVERRIDE - { - AttachWidgetToWasmViewport("canvas", mainWidget_); - } - - virtual WasmPlatformApplicationAdapter* CreateWasmApplicationAdapter(MessageBroker& broker) - { - return new WasmPlatformApplicationAdapter(broker, *this); - } -#endif - - }; - - // this application actually works in Qt and WASM - class SampleSingleCanvasWithButtonsApplicationBase : public SampleApplicationBase - { -public: - virtual void OnPushButton1Clicked() {} - virtual void OnPushButton2Clicked() {} - virtual void OnTool1Clicked() {} - virtual void OnTool2Clicked() {} - - virtual void GetButtonNames(std::string& pushButton1, - std::string& pushButton2, - std::string& tool1, - std::string& tool2 - ) { - pushButton1 = "action1"; - pushButton2 = "action2"; - tool1 = "tool1"; - tool2 = "tool2"; - } - -#if ORTHANC_ENABLE_QT==1 - virtual QStoneMainWindow* CreateQtMainWindow() { - return new SampleMainWindowWithButtons(dynamic_cast<OrthancStone::NativeStoneApplicationContext&>(*context_), *this); - } -#endif - - }; - - // this application actually works in SDL and WASM - class SampleSingleCanvasApplicationBase : public SampleApplicationBase - { -public: - -#if ORTHANC_ENABLE_QT==1 - virtual QStoneMainWindow* CreateQtMainWindow() { - return new SampleMainWindow(dynamic_cast<OrthancStone::NativeStoneApplicationContext&>(*context_), *this); - } -#endif - }; - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SampleInteractor.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "SampleApplicationBase.h" - -#include "../../../Framework/Widgets/LayeredSceneWidget.h" -#include "../../../Framework/Widgets/IWorldSceneInteractor.h" -#include "../../../Framework/Toolbox/ParallelSlicesCursor.h" - -namespace OrthancStone -{ - namespace Samples - { - /** - * This is a basic mouse interactor for sample applications. It - * contains a set of parallel slices in the 3D space. The mouse - * wheel events make the widget change the slice that is - * displayed. - **/ - class SampleInteractor : public IWorldSceneInteractor - { - private: - ParallelSlicesCursor cursor_; - - public: - SampleInteractor(VolumeImage& volume, - VolumeProjection projection, - bool reverse) - { - std::unique_ptr<ParallelSlices> slices(volume.GetGeometry(projection, reverse)); - cursor_.SetGeometry(*slices); - } - - SampleInteractor(ISeriesLoader& series, - bool reverse) - { - if (reverse) - { - std::unique_ptr<ParallelSlices> slices(series.GetGeometry().Reverse()); - cursor_.SetGeometry(*slices); - } - else - { - cursor_.SetGeometry(series.GetGeometry()); - } - } - - SampleInteractor(const ParallelSlices& slices) - { - cursor_.SetGeometry(slices); - } - - ParallelSlicesCursor& GetCursor() - { - return cursor_; - } - - void AddWidget(LayeredSceneWidget& widget) - { - widget.SetInteractor(*this); - widget.SetSlice(cursor_.GetCurrentSlice()); - } - - virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, - const ViewportGeometry& view, - MouseButton button, - double x, - double y, - IStatusBar* statusBar) - { - return NULL; - } - - virtual void MouseOver(CairoContext& context, - WorldSceneWidget& widget, - const ViewportGeometry& view, - double x, - double y, - IStatusBar* statusBar) - { - } - - virtual void MouseWheel(WorldSceneWidget& widget, - MouseWheelDirection direction, - KeyboardModifiers modifiers, - IStatusBar* statusBar) - { - if (cursor_.ApplyWheelEvent(direction, modifiers)) - { - dynamic_cast<LayeredSceneWidget&>(widget).SetSlice(cursor_.GetCurrentSlice()); - } - } - - virtual void KeyPressed(WorldSceneWidget& widget, - char key, - KeyboardModifiers modifiers, - IStatusBar* statusBar) - { - } - - void LookupSliceContainingPoint(LayeredSceneWidget& widget, - const Vector& p) - { - if (cursor_.LookupSliceContainingPoint(p)) - { - widget.SetSlice(cursor_.GetCurrentSlice()); - } - } - }; - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SampleList.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -// The macro "ORTHANC_STONE_SAMPLE" must be set by the CMake script - -#if ORTHANC_STONE_SAMPLE == 1 -#include "EmptyApplication.h" -typedef OrthancStone::Samples::EmptyApplication SampleApplication; - -#elif ORTHANC_STONE_SAMPLE == 2 -#include "TestPatternApplication.h" -typedef OrthancStone::Samples::TestPatternApplication SampleApplication; - -#elif ORTHANC_STONE_SAMPLE == 3 -#include "SingleFrameApplication.h" -typedef OrthancStone::Samples::SingleFrameApplication SampleApplication; - -#elif ORTHANC_STONE_SAMPLE == 4 -#include "SingleVolumeApplication.h" -typedef OrthancStone::Samples::SingleVolumeApplication SampleApplication; - -#elif ORTHANC_STONE_SAMPLE == 5 -#include "BasicPetCtFusionApplication.h" -typedef OrthancStone::Samples::BasicPetCtFusionApplication SampleApplication; - -#elif ORTHANC_STONE_SAMPLE == 6 -#include "SynchronizedSeriesApplication.h" -typedef OrthancStone::Samples::SynchronizedSeriesApplication SampleApplication; - -#elif ORTHANC_STONE_SAMPLE == 7 -#include "LayoutPetCtFusionApplication.h" -typedef OrthancStone::Samples::LayoutPetCtFusionApplication SampleApplication; - -#elif ORTHANC_STONE_SAMPLE == 8 -#include "SimpleViewerApplicationSingleFile.h" -typedef OrthancStone::Samples::SimpleViewerApplication SampleApplication; - -#elif ORTHANC_STONE_SAMPLE == 9 -#include "SingleFrameEditorApplication.h" -typedef OrthancStone::Samples::SingleFrameEditorApplication SampleApplication; - -#else -#error Please set the ORTHANC_STONE_SAMPLE macro -#endif
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SampleMainNative.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "SampleList.h" -#if ORTHANC_ENABLE_SDL==1 -#include "../../Sdl/SdlStoneApplicationRunner.h" -#endif -#if ORTHANC_ENABLE_QT==1 -#include "Qt/SampleQtApplicationRunner.h" -#endif - -int main(int argc, char* argv[]) -{ - boost::shared_ptr<SampleApplication> sampleStoneApplication(new SampleApplication); - -#if ORTHANC_ENABLE_SDL==1 - OrthancStone::SdlStoneApplicationRunner sdlApplicationRunner(sampleStoneApplication); - return sdlApplicationRunner.Execute(argc, argv); -#endif - -#if ORTHANC_ENABLE_QT==1 - OrthancStone::Samples::SampleQtApplicationRunner qtAppRunner(sampleStoneApplication); - return qtAppRunner.Execute(argc, argv); -#endif -} -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SampleMainWasm.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#include "Platforms/Wasm/WasmWebService.h" -#include "Platforms/Wasm/WasmViewport.h" - -#include <emscripten/emscripten.h> - -#include "SampleList.h" - - -OrthancStone::IStoneApplication* CreateUserApplication(OrthancStone::MessageBroker& broker) -{ - return new SampleApplication(broker); -} - -OrthancStone::WasmPlatformApplicationAdapter* CreateWasmApplicationAdapter(OrthancStone::MessageBroker& broker, OrthancStone::IStoneApplication* application) -{ - return dynamic_cast<SampleApplication*>(application)->CreateWasmApplicationAdapter(broker); -} \ No newline at end of file
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Samples-status.md Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -Executable versions -================ -Generic options ----------------------- -``` -("help", "Display this help and exit") -("verbose", "Be verbose in logs") -("orthanc", boost::program_options::value<std::string>() - ->default_value("http://localhost:8042/"), - "URL to the Orthanc server") -("username", "Username for the Orthanc server") -("password", "Password for the Orthanc server") -("https-verify", boost::program_options::value<bool>() - ->default_value(true), "Check HTTPS certificates") -``` -OrthancStoneSimpleViewer -------------------------------------- -- Options: - ``` - - "studyId", std::string, "Orthanc ID of the study" - ``` -- study loading works OK -- Invert does not work: -``` -void SimpleViewerApplication::ExecuteAction(SimpleViewerApplication::Actions action) - { - // TODO - } -``` - -OrthancStoneSimpleViewerSingleFile -------------------------------------- -- Options: - ``` - - "studyId", std::string, "Orthanc ID of the study" - ``` - -Study loading works. - -The `line` and `circle` buttons work and call this: -``` -virtual void OnTool1Clicked() -{ - currentTool_ = Tools_LineMeasure; -} - -virtual void OnTool2Clicked() -{ - currentTool_ = Tools_CircleMeasure; -} -``` -The `action1` and `action2` buttons are not connected - -The following is displayed in the console at launch time: -``` -W0313 12:20:12.790449 NativeStoneApplicationRunner.cpp:55] Use the key "s" to reinitialize the layout -W0313 12:20:12.790449 NativeStoneApplicationRunner.cpp:55] Use the key "n" to go to next image in the main viewport -``` -However, when looking at `MainWidgetInteractor::KeyPressed` (`SimpleViewerApplicationSingleFile.h:169`), only the following is processed: -- 's': reset layout -- 'l': select line tool -- 'c': select circle tool - -OrthancStoneSingleFrame -------------------------------------- -``` -generic.add_options() -("instance", boost::program_options::value<std::string>(), -"Orthanc ID of the instance") -("frame", boost::program_options::value<unsigned int>() - ->default_value(0), -"Number of the frame, for multi-frame DICOM instances") -("smooth", boost::program_options::value<bool>() - ->default_value(true), -"Enable bilinear interpolation to smooth the image"); -``` -only key handled in `KeyPressed` is `s` to call `widget.FitContent()` - - -OrthancStoneSingleFrameEditor -------------------------------------- -``` -generic.add_options() -("instance", boost::program_options::value<std::string>(), -"Orthanc ID of the instance") -("frame", boost::program_options::value<unsigned int>() - ->default_value(0), -"Number of the frame, for multi-frame DICOM instances"); -``` -Available commands in `KeyPressed` (`SingleFrameEditorApplication.h:280`): -- 'a' widget.FitContent() -- 'c' Crop tool -- 'm' Mask tool -- 'd' dump to json and diplay result (?) -- 'e' export current view to Dicom with dummy tags (?) -- 'i' wdiget.SwitchInvert -- 't' Move tool -- 'n' switch between nearest and bilinear interpolation -- 'r' Rotate tool -- 's' Resize tool -- 'w' Windowing tool -- 'ctrl+y' redo -- 'ctrl+z' undo
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/AppStatus.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include <string> - - -namespace SimpleViewer -{ - struct AppStatus - { - std::string patientId; - std::string studyDescription; - std::string currentInstanceIdInMainViewport; - // note: if you add members here, update the serialization code below and deserialization in simple-viewer.ts -> onAppStatusUpdated() - - - AppStatus() - { - } - - void ToJson(Json::Value &output) const - { - output["patientId"] = patientId; - output["studyDescription"] = studyDescription; - output["currentInstanceIdInMainViewport"] = currentInstanceIdInMainViewport; - } - }; -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/MainWidgetInteractor.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#include "MainWidgetInteractor.h" - -#include "SimpleViewerApplication.h" - -namespace SimpleViewer { - - Deprecated::IWorldSceneMouseTracker* MainWidgetInteractor::CreateMouseTracker(Deprecated::WorldSceneWidget& widget, - const Deprecated::ViewportGeometry& view, - MouseButton button, - KeyboardModifiers modifiers, - int viewportX, - int viewportY, - double x, - double y, - Deprecated::IStatusBar* statusBar, - const std::vector<Deprecated::Touch>& displayTouches) - { - if (button == MouseButton_Left) - { - if (application_.GetCurrentTool() == Tool_LineMeasure) - { - return new Deprecated::LineMeasureTracker(statusBar, dynamic_cast<Deprecated::SliceViewerWidget&>(widget).GetSlice(), - x, y, 255, 0, 0, application_.GetFont()); - } - else if (application_.GetCurrentTool() == Tool_CircleMeasure) - { - return new Deprecated::CircleMeasureTracker(statusBar, dynamic_cast<Deprecated::SliceViewerWidget&>(widget).GetSlice(), - x, y, 255, 0, 0, application_.GetFont()); - } - else if (application_.GetCurrentTool() == Tool_Crop) - { - // TODO - } - else if (application_.GetCurrentTool() == Tool_Windowing) - { - // TODO - } - else if (application_.GetCurrentTool() == Tool_Zoom) - { - // TODO - } - else if (application_.GetCurrentTool() == Tool_Pan) - { - // TODO - } - } - return NULL; - } - - void MainWidgetInteractor::MouseOver(CairoContext& context, - Deprecated::WorldSceneWidget& widget, - const Deprecated::ViewportGeometry& view, - double x, - double y, - Deprecated::IStatusBar* statusBar) - { - if (statusBar != NULL) - { - Vector p = dynamic_cast<Deprecated::SliceViewerWidget&>(widget).GetSlice().MapSliceToWorldCoordinates(x, y); - - char buf[64]; - sprintf(buf, "X = %.02f Y = %.02f Z = %.02f (in cm)", - p[0] / 10.0, p[1] / 10.0, p[2] / 10.0); - statusBar->SetMessage(buf); - } - } - - void MainWidgetInteractor::MouseWheel(Deprecated::WorldSceneWidget& widget, - MouseWheelDirection direction, - KeyboardModifiers modifiers, - Deprecated::IStatusBar* statusBar) - { - } - - void MainWidgetInteractor::KeyPressed(Deprecated::WorldSceneWidget& widget, - KeyboardKeys key, - char keyChar, - KeyboardModifiers modifiers, - Deprecated::IStatusBar* statusBar) - { - switch (keyChar) - { - case 's': - widget.FitContent(); - break; - - default: - break; - } - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/MainWidgetInteractor.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#pragma once - -#include "../../../../Framework/Deprecated/Widgets/IWorldSceneInteractor.h" - -using namespace OrthancStone; - -namespace SimpleViewer { - - class SimpleViewerApplication; - - class MainWidgetInteractor : public Deprecated::IWorldSceneInteractor - { - private: - SimpleViewerApplication& application_; - - public: - MainWidgetInteractor(SimpleViewerApplication& application) : - application_(application) - { - } - - /** - WorldSceneWidget: - */ - virtual Deprecated::IWorldSceneMouseTracker* CreateMouseTracker(Deprecated::WorldSceneWidget& widget, - const Deprecated::ViewportGeometry& view, - MouseButton button, - KeyboardModifiers modifiers, - int viewportX, - int viewportY, - double x, - double y, - Deprecated::IStatusBar* statusBar, - const std::vector<Deprecated::Touch>& displayTouches); - - virtual void MouseOver(CairoContext& context, - Deprecated::WorldSceneWidget& widget, - const Deprecated::ViewportGeometry& view, - double x, - double y, - Deprecated::IStatusBar* statusBar); - - virtual void MouseWheel(Deprecated::WorldSceneWidget& widget, - MouseWheelDirection direction, - KeyboardModifiers modifiers, - Deprecated::IStatusBar* statusBar); - - virtual void KeyPressed(Deprecated::WorldSceneWidget& widget, - KeyboardKeys key, - char keyChar, - KeyboardModifiers modifiers, - Deprecated::IStatusBar* statusBar); - }; - - -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/Qt/SimpleViewerMainWindow.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,109 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#include "SimpleViewerMainWindow.h" - -/** - * Don't use "ui_MainWindow.h" instead of <ui_MainWindow.h> below, as - * this makes CMake unable to detect when the UI file changes. - **/ -#include <ui_SimpleViewerMainWindow.h> -#include "../../SimpleViewerApplication.h" - - -namespace SimpleViewer -{ - template<typename T, typename U> - bool ExecuteCommand(U* handler, const T& command) - { - std::string serializedCommand = StoneSerialize(command); - StoneDispatchToHandler(serializedCommand, handler); - } - - SimpleViewerMainWindow::SimpleViewerMainWindow( - OrthancStone::NativeStoneApplicationContext& context, - SimpleViewerApplication& stoneApplication, - QWidget *parent) : - QStoneMainWindow(context, parent), - ui_(new Ui::SimpleViewerMainWindow), - stoneApplication_(stoneApplication) - { - ui_->setupUi(this); - SetCentralStoneWidget(*ui_->cairoCentralWidget); - -#if QT_VERSION >= 0x050000 - connect(ui_->toolButtonCrop, &QToolButton::clicked, this, &SimpleViewerMainWindow::cropClicked); - connect(ui_->pushButtonUndoCrop, &QToolButton::clicked, this, &SimpleViewerMainWindow::undoCropClicked); - connect(ui_->toolButtonLine, &QToolButton::clicked, this, &SimpleViewerMainWindow::lineClicked); - connect(ui_->toolButtonCircle, &QToolButton::clicked, this, &SimpleViewerMainWindow::circleClicked); - connect(ui_->toolButtonWindowing, &QToolButton::clicked, this, &SimpleViewerMainWindow::windowingClicked); - connect(ui_->pushButtonRotate, &QPushButton::clicked, this, &SimpleViewerMainWindow::rotateClicked); - connect(ui_->pushButtonInvert, &QPushButton::clicked, this, &SimpleViewerMainWindow::invertClicked); -#else - connect(ui_->toolButtonCrop, SIGNAL(clicked()), this, SLOT(cropClicked())); - connect(ui_->toolButtonLine, SIGNAL(clicked()), this, SLOT(lineClicked())); - connect(ui_->toolButtonCircle, SIGNAL(clicked()), this, SLOT(circleClicked())); - connect(ui_->toolButtonWindowing, SIGNAL(clicked()), this, SLOT(windowingClicked())); - connect(ui_->pushButtonUndoCrop, SIGNAL(clicked()), this, SLOT(undoCropClicked())); - connect(ui_->pushButtonRotate, SIGNAL(clicked()), this, SLOT(rotateClicked())); - connect(ui_->pushButtonInvert, SIGNAL(clicked()), this, SLOT(invertClicked())); -#endif - } - - SimpleViewerMainWindow::~SimpleViewerMainWindow() - { - delete ui_; - } - - void SimpleViewerMainWindow::cropClicked() - { - stoneApplication_.ExecuteCommand(SelectTool(Tool_Crop)); - } - - void SimpleViewerMainWindow::undoCropClicked() - { - stoneApplication_.ExecuteCommand(Action(ActionType_UndoCrop)); - } - - void SimpleViewerMainWindow::lineClicked() - { - stoneApplication_.ExecuteCommand(SelectTool(Tool_LineMeasure)); - } - - void SimpleViewerMainWindow::circleClicked() - { - stoneApplication_.ExecuteCommand(SelectTool(Tool_CircleMeasure)); - } - - void SimpleViewerMainWindow::windowingClicked() - { - stoneApplication_.ExecuteCommand(SelectTool(Tool_Windowing)); - } - - void SimpleViewerMainWindow::rotateClicked() - { - stoneApplication_.ExecuteCommand(Action(ActionType_Rotate)); - } - - void SimpleViewerMainWindow::invertClicked() - { - stoneApplication_.ExecuteCommand(Action(ActionType_Invert)); - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/Qt/SimpleViewerMainWindow.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ -#pragma once - -#include <Applications/Qt/QCairoWidget.h> -#include <Applications/Qt/QStoneMainWindow.h> - -namespace Ui -{ - class SimpleViewerMainWindow; -} - -using namespace OrthancStone; - -namespace SimpleViewer -{ - class SimpleViewerApplication; - - class SimpleViewerMainWindow : public QStoneMainWindow - { - Q_OBJECT - - private: - Ui::SimpleViewerMainWindow* ui_; - SimpleViewerApplication& stoneApplication_; - - public: - explicit SimpleViewerMainWindow(OrthancStone::NativeStoneApplicationContext& context, SimpleViewerApplication& stoneApplication, QWidget *parent = 0); - ~SimpleViewerMainWindow(); - - private slots: - void cropClicked(); - void undoCropClicked(); - void rotateClicked(); - void windowingClicked(); - void lineClicked(); - void circleClicked(); - void invertClicked(); - }; -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/Qt/SimpleViewerMainWindow.ui Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,151 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>SimpleViewerMainWindow</class> - <widget class="QMainWindow" name="SimpleViewerMainWindow"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>903</width> - <height>634</height> - </rect> - </property> - <property name="minimumSize"> - <size> - <width>500</width> - <height>300</height> - </size> - </property> - <property name="baseSize"> - <size> - <width>500</width> - <height>300</height> - </size> - </property> - <property name="windowTitle"> - <string>Stone of Orthanc</string> - </property> - <property name="layoutDirection"> - <enum>Qt::LeftToRight</enum> - </property> - <widget class="QWidget" name="centralwidget"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="layoutDirection"> - <enum>Qt::LeftToRight</enum> - </property> - <layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,0"> - <property name="sizeConstraint"> - <enum>QLayout::SetDefaultConstraint</enum> - </property> - <item> - <widget class="QCairoWidget" name="cairoCentralWidget"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>500</height> - </size> - </property> - </widget> - </item> - <item> - <widget class="QGroupBox" name="horizontalGroupBox"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>100</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>100</height> - </size> - </property> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QToolButton" name="toolButtonWindowing"> - <property name="text"> - <string>windowing</string> - </property> - </widget> - </item> - <item> - <widget class="QToolButton" name="toolButtonCrop"> - <property name="text"> - <string>crop</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButtonUndoCrop"> - <property name="text"> - <string>undo crop</string> - </property> - </widget> - </item> - <item> - <widget class="QToolButton" name="toolButtonLine"> - <property name="text"> - <string>line</string> - </property> - </widget> - </item> - <item> - <widget class="QToolButton" name="toolButtonCircle"> - <property name="text"> - <string>circle</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButtonRotate"> - <property name="text"> - <string>rotate</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButtonInvert"> - <property name="text"> - <string>invert</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - <widget class="QMenuBar" name="menubar"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>903</width> - <height>22</height> - </rect> - </property> - <widget class="QMenu" name="menuTest"> - <property name="title"> - <string>Test</string> - </property> - </widget> - <addaction name="menuTest"/> - </widget> - <widget class="QStatusBar" name="statusbar"/> - </widget> - <customwidgets> - <customwidget> - <class>QCairoWidget</class> - <extends>QGraphicsView</extends> - <header location="global">QCairoWidget.h</header> - </customwidget> - </customwidgets> - <resources/> - <connections/> -</ui>
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/Qt/mainQt.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "Applications/Qt/QtStoneApplicationRunner.h" - -#include "../../SimpleViewerApplication.h" -#include "Framework/Messages/MessageBroker.h" - - -int main(int argc, char* argv[]) -{ - OrthancStone::MessageBroker broker; - SimpleViewer::SimpleViewerApplication stoneApplication(broker); - - OrthancStone::QtStoneApplicationRunner qtAppRunner(broker, stoneApplication); - return qtAppRunner.Execute(argc, argv); -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/SimpleViewerApplication.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,225 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "SimpleViewerApplication.h" - -#if ORTHANC_ENABLE_QT == 1 -# include "Qt/SimpleViewerMainWindow.h" -#endif - -#if ORTHANC_ENABLE_WASM == 1 -# include <Platforms/Wasm/WasmViewport.h> -#endif - -namespace SimpleViewer -{ - - void SimpleViewerApplication::Initialize(StoneApplicationContext* context, - Deprecated::IStatusBar& statusBar, - const boost::program_options::variables_map& parameters) - { - context_ = context; - statusBar_ = &statusBar; - - {// initialize viewports and layout - mainLayout_ = new Deprecated::LayoutWidget("main-layout"); - mainLayout_->SetPadding(10); - mainLayout_->SetBackgroundCleared(true); - mainLayout_->SetBackgroundColor(0, 0, 0); - mainLayout_->SetHorizontal(); - - thumbnailsLayout_ = new Deprecated::LayoutWidget("thumbnail-layout"); - thumbnailsLayout_->SetPadding(10); - thumbnailsLayout_->SetBackgroundCleared(true); - thumbnailsLayout_->SetBackgroundColor(50, 50, 50); - thumbnailsLayout_->SetVertical(); - - mainWidget_ = new Deprecated::SliceViewerWidget(IObserver::GetBroker(), "main-viewport"); - //mainWidget_->RegisterObserver(*this); - - // hierarchy - mainLayout_->AddWidget(thumbnailsLayout_); - mainLayout_->AddWidget(mainWidget_); - - // sources - smartLoader_.reset(new Deprecated::SmartLoader(IObserver::GetBroker(), context->GetOrthancApiClient())); - smartLoader_->SetImageQuality(Deprecated::SliceImageQuality_FullPam); - - mainLayout_->SetTransmitMouseOver(true); - mainWidgetInteractor_.reset(new MainWidgetInteractor(*this)); - mainWidget_->SetInteractor(*mainWidgetInteractor_); - thumbnailInteractor_.reset(new ThumbnailInteractor(*this)); - } - - statusBar.SetMessage("Use the key \"s\" to reinitialize the layout"); - statusBar.SetMessage("Use the key \"n\" to go to next image in the main viewport"); - - - if (parameters.count("studyId") < 1) - { - LOG(WARNING) << "The study ID is missing, will take the first studyId found in Orthanc"; - context->GetOrthancApiClient().GetJsonAsync("/studies", new Callable<SimpleViewerApplication, Deprecated::OrthancApiClient::JsonResponseReadyMessage>(*this, &SimpleViewerApplication::OnStudyListReceived)); - } - else - { - SelectStudy(parameters["studyId"].as<std::string>()); - } - } - - - void SimpleViewerApplication::DeclareStartupOptions(boost::program_options::options_description& options) - { - boost::program_options::options_description generic("Sample options"); - generic.add_options() - ("studyId", boost::program_options::value<std::string>(), - "Orthanc ID of the study") - ; - - options.add(generic); - } - - void SimpleViewerApplication::OnStudyListReceived(const Deprecated::OrthancApiClient::JsonResponseReadyMessage& message) - { - const Json::Value& response = message.GetJson(); - - if (response.isArray() && - response.size() >= 1) - { - SelectStudy(response[0].asString()); - } - } - void SimpleViewerApplication::OnStudyReceived(const Deprecated::OrthancApiClient::JsonResponseReadyMessage& message) - { - const Json::Value& response = message.GetJson(); - - if (response.isObject() && response["Series"].isArray()) - { - for (size_t i=0; i < response["Series"].size(); i++) - { - context_->GetOrthancApiClient().GetJsonAsync("/series/" + response["Series"][(int)i].asString(), new Callable<SimpleViewerApplication, Deprecated::OrthancApiClient::JsonResponseReadyMessage>(*this, &SimpleViewerApplication::OnSeriesReceived)); - } - } - } - - void SimpleViewerApplication::OnSeriesReceived(const Deprecated::OrthancApiClient::JsonResponseReadyMessage& message) - { - const Json::Value& response = message.GetJson(); - - if (response.isObject() && - response["Instances"].isArray() && - response["Instances"].size() > 0) - { - // keep track of all instances IDs - const std::string& seriesId = response["ID"].asString(); - seriesTags_[seriesId] = response; - instancesIdsPerSeriesId_[seriesId] = std::vector<std::string>(); - for (size_t i = 0; i < response["Instances"].size(); i++) - { - const std::string& instanceId = response["Instances"][static_cast<int>(i)].asString(); - instancesIdsPerSeriesId_[seriesId].push_back(instanceId); - } - - // load the first instance in the thumbnail - LoadThumbnailForSeries(seriesId, instancesIdsPerSeriesId_[seriesId][0]); - - // if this is the first thumbnail loaded, load the first instance in the mainWidget - if (mainWidget_->GetLayerCount() == 0) - { - smartLoader_->SetFrameInWidget(*mainWidget_, 0, instancesIdsPerSeriesId_[seriesId][0], 0); - } - } - } - - void SimpleViewerApplication::LoadThumbnailForSeries(const std::string& seriesId, const std::string& instanceId) - { - LOG(INFO) << "Loading thumbnail for series " << seriesId; - - Deprecated::SliceViewerWidget* thumbnailWidget = - new Deprecated::SliceViewerWidget(IObserver::GetBroker(), "thumbnail-series-" + seriesId); - thumbnails_.push_back(thumbnailWidget); - thumbnailsLayout_->AddWidget(thumbnailWidget); - - thumbnailWidget->RegisterObserverCallback( - new Callable<SimpleViewerApplication, Deprecated::SliceViewerWidget::GeometryChangedMessage> - (*this, &SimpleViewerApplication::OnWidgetGeometryChanged)); - - smartLoader_->SetFrameInWidget(*thumbnailWidget, 0, instanceId, 0); - thumbnailWidget->SetInteractor(*thumbnailInteractor_); - } - - void SimpleViewerApplication::SelectStudy(const std::string& studyId) - { - context_->GetOrthancApiClient().GetJsonAsync("/studies/" + studyId, new Callable<SimpleViewerApplication, Deprecated::OrthancApiClient::JsonResponseReadyMessage>(*this, &SimpleViewerApplication::OnStudyReceived)); - } - - void SimpleViewerApplication::OnWidgetGeometryChanged(const Deprecated::SliceViewerWidget::GeometryChangedMessage& message) - { - // TODO: The "const_cast" could probably be replaced by "mainWidget_" - const_cast<Deprecated::SliceViewerWidget&>(message.GetOrigin()).FitContent(); - } - - void SimpleViewerApplication::SelectSeriesInMainViewport(const std::string& seriesId) - { - smartLoader_->SetFrameInWidget(*mainWidget_, 0, instancesIdsPerSeriesId_[seriesId][0], 0); - } - - bool SimpleViewerApplication::Handle(const StoneSampleCommands::SelectTool& value) - { - currentTool_ = value.tool; - return true; - } - - bool SimpleViewerApplication::Handle(const StoneSampleCommands::Action& value) - { - switch (value.type) - { - case ActionType_Invert: - // TODO - break; - case ActionType_UndoCrop: - // TODO - break; - case ActionType_Rotate: - // TODO - break; - default: - throw std::runtime_error("Action type not supported"); - } - return true; - } - -#if ORTHANC_ENABLE_QT==1 - QStoneMainWindow* SimpleViewerApplication::CreateQtMainWindow() - { - return new SimpleViewerMainWindow(dynamic_cast<OrthancStone::NativeStoneApplicationContext&>(*context_), *this); - } -#endif - -#if ORTHANC_ENABLE_WASM==1 - void SimpleViewerApplication::InitializeWasm() { - - AttachWidgetToWasmViewport("canvasThumbnails", thumbnailsLayout_); - AttachWidgetToWasmViewport("canvasMain", mainWidget_); - } -#endif - - -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/SimpleViewerApplication.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,175 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - - /* - This header contains the command definitions for the sample applications - */ -#include "Applications/Samples/StoneSampleCommands_generated.hpp" -using namespace StoneSampleCommands; - -#include "Applications/IStoneApplication.h" - -#include "../../../../Framework/Deprecated/Layers/CircleMeasureTracker.h" -#include "../../../../Framework/Deprecated/Layers/LineMeasureTracker.h" -#include "../../../../Framework/Deprecated/SmartLoader.h" -#include "../../../../Framework/Deprecated/Widgets/LayoutWidget.h" -#include "../../../../Framework/Deprecated/Widgets/SliceViewerWidget.h" -#include "../../../../Framework/Messages/IObserver.h" - -#if ORTHANC_ENABLE_WASM==1 -#include "Platforms/Wasm/WasmPlatformApplicationAdapter.h" -#include "Platforms/Wasm/Defaults.h" -#endif - -#if ORTHANC_ENABLE_QT==1 -#include "Qt/SimpleViewerMainWindow.h" -#endif - -#include <Core/Images/Font.h> -#include <Core/Logging.h> - -#include "ThumbnailInteractor.h" -#include "MainWidgetInteractor.h" -#include "AppStatus.h" - -using namespace OrthancStone; - - -namespace SimpleViewer -{ - - class SimpleViewerApplication - : public IStoneApplication - , public IObserver - , public IObservable - , public StoneSampleCommands::IHandler - { - public: - - struct StatusUpdatedMessage : public IMessage - { - ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); - - const AppStatus& status_; - - StatusUpdatedMessage(const AppStatus& status) - : status_(status) - { - } - }; - - private: - Tool currentTool_; - - std::unique_ptr<MainWidgetInteractor> mainWidgetInteractor_; - std::unique_ptr<ThumbnailInteractor> thumbnailInteractor_; - Deprecated::LayoutWidget* mainLayout_; - Deprecated::LayoutWidget* thumbnailsLayout_; - Deprecated::SliceViewerWidget* mainWidget_; - std::vector<Deprecated::SliceViewerWidget*> thumbnails_; - std::map<std::string, std::vector<std::string> > instancesIdsPerSeriesId_; - std::map<std::string, Json::Value> seriesTags_; - unsigned int currentInstanceIndex_; - Deprecated::WidgetViewport* wasmViewport1_; - Deprecated::WidgetViewport* wasmViewport2_; - - Deprecated::IStatusBar* statusBar_; - std::unique_ptr<Deprecated::SmartLoader> smartLoader_; - - Orthanc::Font font_; - - public: - SimpleViewerApplication(MessageBroker& broker) : - IObserver(broker), - IObservable(broker), - currentTool_(StoneSampleCommands::Tool_LineMeasure), - mainLayout_(NULL), - currentInstanceIndex_(0), - wasmViewport1_(NULL), - wasmViewport2_(NULL) - { - font_.LoadFromResource(Orthanc::EmbeddedResources::FONT_UBUNTU_MONO_BOLD_16); - } - - virtual void Finalize() ORTHANC_OVERRIDE {} - virtual Deprecated::IWidget* GetCentralWidget() ORTHANC_OVERRIDE {return mainLayout_;} - - virtual void DeclareStartupOptions(boost::program_options::options_description& options) ORTHANC_OVERRIDE; - virtual void Initialize(StoneApplicationContext* context, - Deprecated::IStatusBar& statusBar, - const boost::program_options::variables_map& parameters) ORTHANC_OVERRIDE; - - void OnStudyListReceived(const Deprecated::OrthancApiClient::JsonResponseReadyMessage& message); - - void OnStudyReceived(const Deprecated::OrthancApiClient::JsonResponseReadyMessage& message); - - void OnSeriesReceived(const Deprecated::OrthancApiClient::JsonResponseReadyMessage& message); - - void LoadThumbnailForSeries(const std::string& seriesId, const std::string& instanceId); - - void SelectStudy(const std::string& studyId); - - void OnWidgetGeometryChanged(const Deprecated::SliceViewerWidget::GeometryChangedMessage& message); - - void SelectSeriesInMainViewport(const std::string& seriesId); - - - Tool GetCurrentTool() const - { - return currentTool_; - } - - const Orthanc::Font& GetFont() const - { - return font_; - } - - // ExecuteAction method was empty (its body was a single "TODO" comment) - virtual bool Handle(const SelectTool& value) ORTHANC_OVERRIDE; - virtual bool Handle(const Action& value) ORTHANC_OVERRIDE; - - template<typename T> - bool ExecuteCommand(const T& cmd) - { - std::string cmdStr = StoneSampleCommands::StoneSerialize(cmd); - return StoneSampleCommands::StoneDispatchToHandler(cmdStr, this); - } - - virtual void HandleSerializedMessage(const char* data) ORTHANC_OVERRIDE - { - StoneSampleCommands::StoneDispatchToHandler(data, this); - } - - virtual std::string GetTitle() const ORTHANC_OVERRIDE {return "SimpleViewer";} - -#if ORTHANC_ENABLE_WASM==1 - virtual void InitializeWasm() ORTHANC_OVERRIDE; -#endif - -#if ORTHANC_ENABLE_QT==1 - virtual QStoneMainWindow* CreateQtMainWindow(); -#endif - }; - - -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/ThumbnailInteractor.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#include "ThumbnailInteractor.h" - -#include "SimpleViewerApplication.h" - -namespace SimpleViewer { - - Deprecated::IWorldSceneMouseTracker* ThumbnailInteractor::CreateMouseTracker(Deprecated::WorldSceneWidget& widget, - const Deprecated::ViewportGeometry& view, - MouseButton button, - KeyboardModifiers modifiers, - int viewportX, - int viewportY, - double x, - double y, - Deprecated::IStatusBar* statusBar, - const std::vector<Deprecated::Touch>& displayTouches) - { - if (button == MouseButton_Left) - { - statusBar->SetMessage("selected thumbnail " + widget.GetName()); - std::string seriesId = widget.GetName().substr(strlen("thumbnail-series-")); - application_.SelectSeriesInMainViewport(seriesId); - } - return NULL; - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/ThumbnailInteractor.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../../../Framework/Deprecated/Widgets/IWorldSceneInteractor.h" - -using namespace OrthancStone; - -namespace SimpleViewer { - - class SimpleViewerApplication; - - class ThumbnailInteractor : public Deprecated::IWorldSceneInteractor - { - private: - SimpleViewerApplication& application_; - public: - ThumbnailInteractor(SimpleViewerApplication& application) : - application_(application) - { - } - - virtual Deprecated::IWorldSceneMouseTracker* CreateMouseTracker(Deprecated::WorldSceneWidget& widget, - const Deprecated::ViewportGeometry& view, - MouseButton button, - KeyboardModifiers modifiers, - int viewportX, - int viewportY, - double x, - double y, - Deprecated::IStatusBar* statusBar, - const std::vector<Deprecated::Touch>& displayTouches); - - virtual void MouseOver(CairoContext& context, - Deprecated::WorldSceneWidget& widget, - const Deprecated::ViewportGeometry& view, - double x, - double y, - Deprecated::IStatusBar* statusBar) - {} - - virtual void MouseWheel(Deprecated::WorldSceneWidget& widget, - MouseWheelDirection direction, - KeyboardModifiers modifiers, - Deprecated::IStatusBar* statusBar) - {} - - virtual void KeyPressed(Deprecated::WorldSceneWidget& widget, - KeyboardKeys key, - char keyChar, - KeyboardModifiers modifiers, - Deprecated::IStatusBar* statusBar) - {} - - }; - - -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/Wasm/SimpleViewerWasmApplicationAdapter.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#include "SimpleViewerWasmApplicationAdapter.h" - -namespace SimpleViewer -{ - - SimpleViewerWasmApplicationAdapter::SimpleViewerWasmApplicationAdapter(MessageBroker &broker, SimpleViewerApplication &application) - : WasmPlatformApplicationAdapter(broker, application), - viewerApplication_(application) - { - application.RegisterObserverCallback(new Callable<SimpleViewerWasmApplicationAdapter, SimpleViewerApplication::StatusUpdatedMessage>(*this, &SimpleViewerWasmApplicationAdapter::OnStatusUpdated)); - } - - void SimpleViewerWasmApplicationAdapter::OnStatusUpdated(const SimpleViewerApplication::StatusUpdatedMessage &message) - { - Json::Value statusJson; - message.status_.ToJson(statusJson); - - Json::Value event; - event["event"] = "appStatusUpdated"; - event["data"] = statusJson; - - Json::StreamWriterBuilder builder; - std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter()); - std::ostringstream outputStr; - - writer->write(event, &outputStr); - - NotifyStatusUpdateFromCppToWebWithString(outputStr.str()); - } - -} // namespace SimpleViewer \ No newline at end of file
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/Wasm/SimpleViewerWasmApplicationAdapter.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#pragma once - -#include <string> -#include "../../../../../../Framework/Messages/IObserver.h" -#include <Platforms/Wasm/WasmPlatformApplicationAdapter.h> - -#include "../../SimpleViewerApplication.h" - -namespace SimpleViewer { - - class SimpleViewerWasmApplicationAdapter : public WasmPlatformApplicationAdapter - { - SimpleViewerApplication& viewerApplication_; - - public: - SimpleViewerWasmApplicationAdapter(MessageBroker& broker, SimpleViewerApplication& application); - - private: - void OnStatusUpdated(const SimpleViewerApplication::StatusUpdatedMessage& message); - - }; - -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/Wasm/mainWasm.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#include "Platforms/Wasm/WasmWebService.h" -#include "Platforms/Wasm/WasmViewport.h" - -#include <emscripten/emscripten.h> - -#include "../../SimpleViewerApplication.h" -#include "SimpleViewerWasmApplicationAdapter.h" - - -OrthancStone::IStoneApplication* CreateUserApplication(OrthancStone::MessageBroker& broker) { - - return new SimpleViewer::SimpleViewerApplication(broker); -} - -OrthancStone::WasmPlatformApplicationAdapter* CreateWasmApplicationAdapter(OrthancStone::MessageBroker& broker, IStoneApplication* application) -{ - return new SimpleViewer::SimpleViewerWasmApplicationAdapter(broker, *(dynamic_cast<SimpleViewer::SimpleViewerApplication*>(application))); -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/Wasm/simple-viewer.html Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -<!doctype html> - -<html lang="us"> - <head> - <meta charset="utf-8" /> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> - - <!-- Disable pinch zoom on mobile devices --> - <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> - <meta name="HandheldFriendly" content="true" /> - - <title>Simple Viewer</title> - <link href="styles.css" rel="stylesheet" /> - -<body> - <div id="breadcrumb"> - <span id="label-patient-id"></span> - <span id="label-study-description"></span> - <span id="label-series-description"></span> - </div> - <div style="height: calc(100% - 50px)"> - <div style="width: 20%; height: 100%; display: inline-block"> - <canvas id="canvasThumbnails"></canvas> - </div> - <div style="width: 70%; height: 100%; display: inline-block"> - <canvas id="canvasMain"></canvas> - </div> - </div> - <div id="toolbox" style="height: 50px"> - <button tool-selector="line-measure" class="tool-selector">line</button> - <button tool-selector="circle-measure" class="tool-selector">circle</button> - <button tool-selector="crop" class="tool-selector">crop</button> - <button tool-selector="windowing" class="tool-selector">windowing</button> - <button tool-selector="zoom" class="tool-selector">zoom</button> - <button tool-selector="pan" class="tool-selector">pan</button> - <button action-trigger="rotate-left" class="action-trigger">rotate left</button> - <button action-trigger="rotate-right" class="action-trigger">rotate right</button> - <button action-trigger="invert" class="action-trigger">invert</button> - </div> - <script type="text/javascript" src="app-simple-viewer.js"></script> -</body> - -</html> \ No newline at end of file
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/Wasm/simple-viewer.ts Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -import wasmApplicationRunner = require('../../../../Platforms/Wasm/wasm-application-runner'); - -wasmApplicationRunner.InitializeWasmApplication("OrthancStoneSimpleViewer", "/orthanc"); - -function SelectTool(toolName: string) { - var command = { - command: "selectTool:" + toolName, - commandType: "generic-no-arg-command", - args: { - } - }; - wasmApplicationRunner.SendSerializedMessageToStoneApplication(JSON.stringify(command)); -} - -function PerformAction(actionName: string) { - var command = { - command: "action:" + actionName, - commandType: "generic-no-arg-command", - args: { - } - }; - wasmApplicationRunner.SendSerializedMessageToStoneApplication(JSON.stringify(command)); -} - -class SimpleViewerUI { - - private _labelPatientId: HTMLSpanElement; - private _labelStudyDescription: HTMLSpanElement; - - public constructor() { - // install "SelectTool" handlers - document.querySelectorAll("[tool-selector]").forEach((e) => { - (e as HTMLButtonElement).addEventListener("click", () => { - SelectTool(e.attributes["tool-selector"].value); - }); - }); - - // install "PerformAction" handlers - document.querySelectorAll("[action-trigger]").forEach((e) => { - (e as HTMLButtonElement).addEventListener("click", () => { - PerformAction(e.attributes["action-trigger"].value); - }); - }); - - // connect all ui elements to members - this._labelPatientId = document.getElementById("label-patient-id") as HTMLSpanElement; - this._labelStudyDescription = document.getElementById("label-study-description") as HTMLSpanElement; - } - - public onAppStatusUpdated(status: any) { - this._labelPatientId.innerText = status["patientId"]; - this._labelStudyDescription.innerText = status["studyDescription"]; - // this.highlighThumbnail(status["currentInstanceIdInMainViewport"]); - } - -} - -var ui = new SimpleViewerUI(); - -// this method is called "from the C++ code" when the StoneApplication is updated. -// it can be used to update the UI of the application -function UpdateWebApplicationWithString(statusUpdateMessageString: string) { - console.log("updating web application with string: ", statusUpdateMessageString); - let statusUpdateMessage = JSON.parse(statusUpdateMessageString); - - if ("event" in statusUpdateMessage) { - let eventName = statusUpdateMessage["event"]; - if (eventName == "appStatusUpdated") { - ui.onAppStatusUpdated(statusUpdateMessage["data"]); - } - } -} - -function UpdateWebApplicationWithSerializedMessage(statusUpdateMessageString: string) { - console.log("updating web application with serialized message: ", statusUpdateMessageString); - console.log("<not supported in the simple viewer!>"); -} - -// make it available to other js scripts in the application -(<any> window).UpdateWebApplicationWithString = UpdateWebApplicationWithString; -(<any> window).UpdateWebApplicationWithSerializedMessage = UpdateWebApplicationWithSerializedMessage;
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/Wasm/styles.css Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -html, body { - width: 100%; - height: 100%; - margin: 0px; - border: 0; - overflow: hidden; /* Disable scrollbars */ - display: block; /* No floating content on sides */ - background-color: black; - color: white; - font-family: Arial, Helvetica, sans-serif; -} - -canvas { - left:0px; - top:0px; -} - -#canvas-group { - padding:5px; - background-color: grey; -} - -#status-group { - padding:5px; -} - -#worklist-group { - padding:5px; -} - -.vsol-button { - height: 40px; -} - -#thumbnails-group ul li { - display: inline; - list-style: none; -} - -.thumbnail { - width: 100px; - height: 100px; - padding: 3px; -} - -.thumbnail-selected { - border-width: 1px; - border-color: red; - border-style: solid; -} - -#template-thumbnail-li { - display: none !important; -} \ No newline at end of file
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewer/Wasm/tsconfig-simple-viewer.json Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -{ - "extends" : "../../Web/tsconfig-samples", - "compilerOptions": { - }, - "include" : [ - "simple-viewer.ts", - "../../build-wasm/ApplicationCommands_generated.ts" - ] -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SimpleViewerApplicationSingleFile.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,461 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "SampleApplicationBase.h" - -#include "../../../Framework/Deprecated/Layers/CircleMeasureTracker.h" -#include "../../../Framework/Deprecated/Layers/LineMeasureTracker.h" -#include "../../../Framework/Deprecated/SmartLoader.h" -#include "../../../Framework/Deprecated/Widgets/LayoutWidget.h" -#include "../../../Framework/Deprecated/Widgets/SliceViewerWidget.h" -#include "../../../Framework/Messages/IObserver.h" - -#if ORTHANC_ENABLE_WASM==1 -#include "../../../Platforms/Wasm/WasmPlatformApplicationAdapter.h" -#include "../../../Platforms/Wasm/Defaults.h" -#endif - -#include <Core/Images/Font.h> -#include <Core/Logging.h> - -namespace OrthancStone -{ - namespace Samples - { - class SimpleViewerApplication : - public SampleSingleCanvasWithButtonsApplicationBase, - public ObserverBase<SimpleViewerApplication> - { - private: - class ThumbnailInteractor : public Deprecated::IWorldSceneInteractor - { - private: - SimpleViewerApplication& application_; - - public: - ThumbnailInteractor(SimpleViewerApplication& application) : - application_(application) - { - } - - virtual Deprecated::IWorldSceneMouseTracker* CreateMouseTracker(Deprecated::WorldSceneWidget& widget, - const Deprecated::ViewportGeometry& view, - MouseButton button, - KeyboardModifiers modifiers, - int viewportX, - int viewportY, - double x, - double y, - Deprecated::IStatusBar* statusBar, - const std::vector<Deprecated::Touch>& displayTouches) - { - if (button == MouseButton_Left) - { - statusBar->SetMessage("selected thumbnail " + widget.GetName()); - std::string seriesId = widget.GetName().substr(strlen("thumbnail-series-")); - application_.SelectSeriesInMainViewport(seriesId); - } - return NULL; - } - - virtual void MouseOver(CairoContext& context, - Deprecated::WorldSceneWidget& widget, - const Deprecated::ViewportGeometry& view, - double x, - double y, - Deprecated::IStatusBar* statusBar) - { - } - - virtual void MouseWheel(Deprecated::WorldSceneWidget& widget, - MouseWheelDirection direction, - KeyboardModifiers modifiers, - Deprecated::IStatusBar* statusBar) - { - } - - virtual void KeyPressed(Deprecated::WorldSceneWidget& widget, - KeyboardKeys key, - char keyChar, - KeyboardModifiers modifiers, - Deprecated::IStatusBar* statusBar) - { - } - }; - - class MainWidgetInteractor : public Deprecated::IWorldSceneInteractor - { - private: - SimpleViewerApplication& application_; - - public: - MainWidgetInteractor(SimpleViewerApplication& application) : - application_(application) - { - } - - virtual Deprecated::IWorldSceneMouseTracker* CreateMouseTracker(Deprecated::WorldSceneWidget& widget, - const Deprecated::ViewportGeometry& view, - MouseButton button, - KeyboardModifiers modifiers, - int viewportX, - int viewportY, - double x, - double y, - Deprecated::IStatusBar* statusBar, - const std::vector<Deprecated::Touch>& displayTouches) - { - if (button == MouseButton_Left) - { - if (application_.currentTool_ == Tool_LineMeasure) - { - return new Deprecated::LineMeasureTracker(statusBar, dynamic_cast<Deprecated::SliceViewerWidget&>(widget).GetSlice(), - x, y, 255, 0, 0, application_.GetFont()); - } - else if (application_.currentTool_ == Tool_CircleMeasure) - { - return new Deprecated::CircleMeasureTracker(statusBar, dynamic_cast<Deprecated::SliceViewerWidget&>(widget).GetSlice(), - x, y, 255, 0, 0, application_.GetFont()); - } - } - return NULL; - } - - virtual void MouseOver(CairoContext& context, - Deprecated::WorldSceneWidget& widget, - const Deprecated::ViewportGeometry& view, - double x, - double y, - Deprecated::IStatusBar* statusBar) - { - if (statusBar != NULL) - { - Vector p = dynamic_cast<Deprecated::SliceViewerWidget&>(widget).GetSlice().MapSliceToWorldCoordinates(x, y); - - char buf[64]; - sprintf(buf, "X = %.02f Y = %.02f Z = %.02f (in cm)", - p[0] / 10.0, p[1] / 10.0, p[2] / 10.0); - statusBar->SetMessage(buf); - } - } - - virtual void MouseWheel(Deprecated::WorldSceneWidget& widget, - MouseWheelDirection direction, - KeyboardModifiers modifiers, - Deprecated::IStatusBar* statusBar) - { - } - - virtual void KeyPressed(Deprecated::WorldSceneWidget& widget, - KeyboardKeys key, - char keyChar, - KeyboardModifiers modifiers, - Deprecated::IStatusBar* statusBar) - { - switch (keyChar) - { - case 's': - widget.FitContent(); - break; - - case 'l': - application_.currentTool_ = Tool_LineMeasure; - break; - - case 'c': - application_.currentTool_ = Tool_CircleMeasure; - break; - - default: - break; - } - } - }; - - -#if ORTHANC_ENABLE_WASM==1 - class SimpleViewerApplicationAdapter : public WasmPlatformApplicationAdapter - { - SimpleViewerApplication& viewerApplication_; - - public: - SimpleViewerApplicationAdapter(SimpleViewerApplication& application) - : WasmPlatformApplicationAdapter(application), - viewerApplication_(application) - { - } - - virtual void HandleSerializedMessageFromWeb(std::string& output, const std::string& input) - { - if (input == "select-tool:line-measure") - { - viewerApplication_.currentTool_ = Tool_LineMeasure; - NotifyStatusUpdateFromCppToWebWithString("currentTool=line-measure"); - } - else if (input == "select-tool:circle-measure") - { - viewerApplication_.currentTool_ = Tool_CircleMeasure; - NotifyStatusUpdateFromCppToWebWithString("currentTool=circle-measure"); - } - - output = "ok"; - } - - virtual void NotifySerializedMessageFromCppToWeb(const std::string& statusUpdateMessage) - { - UpdateStoneApplicationStatusFromCppWithSerializedMessage(statusUpdateMessage.c_str()); - } - - virtual void NotifyStatusUpdateFromCppToWebWithString(const std::string& statusUpdateMessage) - { - UpdateStoneApplicationStatusFromCppWithString(statusUpdateMessage.c_str()); - } - - }; -#endif - enum Tool { - Tool_LineMeasure, - Tool_CircleMeasure - }; - - Tool currentTool_; - std::unique_ptr<MainWidgetInteractor> mainWidgetInteractor_; - std::unique_ptr<ThumbnailInteractor> thumbnailInteractor_; - Deprecated::LayoutWidget* mainLayout_; - Deprecated::LayoutWidget* thumbnailsLayout_; - std::vector<boost::shared_ptr<Deprecated::SliceViewerWidget> > thumbnails_; - - std::map<std::string, std::vector<std::string> > instancesIdsPerSeriesId_; - std::map<std::string, Json::Value> seriesTags_; - - unsigned int currentInstanceIndex_; - Deprecated::WidgetViewport* wasmViewport1_; - Deprecated::WidgetViewport* wasmViewport2_; - - Deprecated::IStatusBar* statusBar_; - std::unique_ptr<Deprecated::SmartLoader> smartLoader_; - - Orthanc::Font font_; - - public: - SimpleViewerApplication() : - currentTool_(Tool_LineMeasure), - mainLayout_(NULL), - currentInstanceIndex_(0), - wasmViewport1_(NULL), - wasmViewport2_(NULL) - { - font_.LoadFromResource(Orthanc::EmbeddedResources::FONT_UBUNTU_MONO_BOLD_16); -// DeclareIgnoredMessage(MessageType_Widget_ContentChanged); - } - - virtual void DeclareStartupOptions(boost::program_options::options_description& options) - { - boost::program_options::options_description generic("Sample options"); - generic.add_options() - ("studyId", boost::program_options::value<std::string>(), - "Orthanc ID of the study") - ; - - options.add(generic); - } - - virtual void Initialize(StoneApplicationContext* context, - Deprecated::IStatusBar& statusBar, - const boost::program_options::variables_map& parameters) - { - using namespace OrthancStone; - - context_ = context; - statusBar_ = &statusBar; - - {// initialize viewports and layout - mainLayout_ = new Deprecated::LayoutWidget("main-layout"); - mainLayout_->SetPadding(10); - mainLayout_->SetBackgroundCleared(true); - mainLayout_->SetBackgroundColor(0, 0, 0); - mainLayout_->SetHorizontal(); - - boost::shared_ptr<Deprecated::LayoutWidget> thumbnailsLayout_(new Deprecated::LayoutWidget("thumbnail-layout")); - thumbnailsLayout_->SetPadding(10); - thumbnailsLayout_->SetBackgroundCleared(true); - thumbnailsLayout_->SetBackgroundColor(50, 50, 50); - thumbnailsLayout_->SetVertical(); - - boost::shared_ptr<Deprecated::SliceViewerWidget> widget - (new Deprecated::SliceViewerWidget("main-viewport")); - SetCentralWidget(widget); - //mainWidget_->RegisterObserver(*this); - - // hierarchy - mainLayout_->AddWidget(thumbnailsLayout_); - mainLayout_->AddWidget(widget); - - // sources - smartLoader_.reset(new Deprecated::SmartLoader(context->GetOrthancApiClient())); - smartLoader_->SetImageQuality(Deprecated::SliceImageQuality_FullPam); - - mainLayout_->SetTransmitMouseOver(true); - mainWidgetInteractor_.reset(new MainWidgetInteractor(*this)); - widget->SetInteractor(*mainWidgetInteractor_); - thumbnailInteractor_.reset(new ThumbnailInteractor(*this)); - } - - statusBar.SetMessage("Use the key \"s\" to reinitialize the layout"); - statusBar.SetMessage("Use the key \"n\" to go to next image in the main viewport"); - - - if (parameters.count("studyId") < 1) - { - LOG(WARNING) << "The study ID is missing, will take the first studyId found in Orthanc"; - context->GetOrthancApiClient()->GetJsonAsync( - "/studies", - new Deprecated::DeprecatedCallable<SimpleViewerApplication, Deprecated::OrthancApiClient::JsonResponseReadyMessage> - (GetSharedObserver(), &SimpleViewerApplication::OnStudyListReceived)); - } - else - { - SelectStudy(parameters["studyId"].as<std::string>()); - } - } - - void OnStudyListReceived(const Deprecated::OrthancApiClient::JsonResponseReadyMessage& message) - { - const Json::Value& response = message.GetJson(); - - if (response.isArray() && - response.size() >= 1) - { - SelectStudy(response[0].asString()); - } - } - - void OnStudyReceived(const Deprecated::OrthancApiClient::JsonResponseReadyMessage& message) - { - const Json::Value& response = message.GetJson(); - - if (response.isObject() && response["Series"].isArray()) - { - for (size_t i=0; i < response["Series"].size(); i++) - { - context_->GetOrthancApiClient()->GetJsonAsync( - "/series/" + response["Series"][(int)i].asString(), - new Deprecated::DeprecatedCallable<SimpleViewerApplication, Deprecated::OrthancApiClient::JsonResponseReadyMessage> - (GetSharedObserver(), &SimpleViewerApplication::OnSeriesReceived)); - } - } - } - - void OnSeriesReceived(const Deprecated::OrthancApiClient::JsonResponseReadyMessage& message) - { - const Json::Value& response = message.GetJson(); - - if (response.isObject() && - response["Instances"].isArray() && - response["Instances"].size() > 0) - { - // keep track of all instances IDs - const std::string& seriesId = response["ID"].asString(); - seriesTags_[seriesId] = response; - instancesIdsPerSeriesId_[seriesId] = std::vector<std::string>(); - for (size_t i = 0; i < response["Instances"].size(); i++) - { - const std::string& instanceId = response["Instances"][static_cast<int>(i)].asString(); - instancesIdsPerSeriesId_[seriesId].push_back(instanceId); - } - - // load the first instance in the thumbnail - LoadThumbnailForSeries(seriesId, instancesIdsPerSeriesId_[seriesId][0]); - - // if this is the first thumbnail loaded, load the first instance in the mainWidget - Deprecated::SliceViewerWidget& widget = dynamic_cast<Deprecated::SliceViewerWidget&>(*GetCentralWidget()); - if (widget.GetLayerCount() == 0) - { - smartLoader_->SetFrameInWidget(widget, 0, instancesIdsPerSeriesId_[seriesId][0], 0); - } - } - } - - void LoadThumbnailForSeries(const std::string& seriesId, const std::string& instanceId) - { - LOG(INFO) << "Loading thumbnail for series " << seriesId; - boost::shared_ptr<Deprecated::SliceViewerWidget> thumbnailWidget(new Deprecated::SliceViewerWidget("thumbnail-series-" + seriesId)); - thumbnails_.push_back(thumbnailWidget); - thumbnailsLayout_->AddWidget(thumbnailWidget); - Register<Deprecated::SliceViewerWidget::GeometryChangedMessage>(*thumbnailWidget, &SimpleViewerApplication::OnWidgetGeometryChanged); - smartLoader_->SetFrameInWidget(*thumbnailWidget, 0, instanceId, 0); - thumbnailWidget->SetInteractor(*thumbnailInteractor_); - } - - void SelectStudy(const std::string& studyId) - { - LOG(INFO) << "Selecting study: " << studyId; - context_->GetOrthancApiClient()->GetJsonAsync( - "/studies/" + studyId, new Deprecated::DeprecatedCallable<SimpleViewerApplication, Deprecated::OrthancApiClient::JsonResponseReadyMessage> - (GetSharedObserver(), &SimpleViewerApplication::OnStudyReceived)); - } - - void OnWidgetGeometryChanged(const Deprecated::SliceViewerWidget::GeometryChangedMessage& message) - { - // TODO: The "const_cast" could probably be replaced by "mainWidget" - const_cast<Deprecated::SliceViewerWidget&>(message.GetOrigin()).FitContent(); - } - - void SelectSeriesInMainViewport(const std::string& seriesId) - { - Deprecated::SliceViewerWidget& widget = dynamic_cast<Deprecated::SliceViewerWidget&>(*GetCentralWidget()); - smartLoader_->SetFrameInWidget(widget, 0, instancesIdsPerSeriesId_[seriesId][0], 0); - } - - const Orthanc::Font& GetFont() const - { - return font_; - } - - virtual void OnPushButton1Clicked() {} - virtual void OnPushButton2Clicked() {} - virtual void OnTool1Clicked() { currentTool_ = Tool_LineMeasure;} - virtual void OnTool2Clicked() { currentTool_ = Tool_CircleMeasure;} - - virtual void GetButtonNames(std::string& pushButton1, - std::string& pushButton2, - std::string& tool1, - std::string& tool2) - { - tool1 = "line"; - tool2 = "circle"; - pushButton1 = "action1"; - pushButton2 = "action2"; - } - -#if ORTHANC_ENABLE_WASM==1 - virtual void InitializeWasm() - { - AttachWidgetToWasmViewport("canvas", thumbnailsLayout_); - AttachWidgetToWasmViewport("canvas2", widget); - } -#endif - - }; - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SingleFrameApplication.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,268 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "SampleApplicationBase.h" - -#include "../../../Framework/Deprecated/Layers/DicomSeriesVolumeSlicer.h" -#include "../../../Framework/Deprecated/Widgets/SliceViewerWidget.h" - -#include <Core/Logging.h> -#include <Core/OrthancException.h> - -#include <boost/math/constants/constants.hpp> - - -namespace OrthancStone -{ - namespace Samples - { - class SingleFrameApplication : - public SampleSingleCanvasApplicationBase, - public ObserverBase<SingleFrameApplication> - { - private: - class Interactor : public Deprecated::IWorldSceneInteractor - { - private: - SingleFrameApplication& application_; - - public: - Interactor(SingleFrameApplication& application) : - application_(application) - { - } - - virtual Deprecated::IWorldSceneMouseTracker* CreateMouseTracker(Deprecated::WorldSceneWidget& widget, - const Deprecated::ViewportGeometry& view, - MouseButton button, - KeyboardModifiers modifiers, - int viewportX, - int viewportY, - double x, - double y, - Deprecated::IStatusBar* statusBar, - const std::vector<Deprecated::Touch>& displayTouches) - { - return NULL; - } - - virtual void MouseOver(CairoContext& context, - Deprecated::WorldSceneWidget& widget, - const Deprecated::ViewportGeometry& view, - double x, - double y, - Deprecated::IStatusBar* statusBar) - { - if (statusBar != NULL) - { - Vector p = dynamic_cast<Deprecated::SliceViewerWidget&>(widget).GetSlice().MapSliceToWorldCoordinates(x, y); - - char buf[64]; - sprintf(buf, "X = %.02f Y = %.02f Z = %.02f (in cm)", - p[0] / 10.0, p[1] / 10.0, p[2] / 10.0); - statusBar->SetMessage(buf); - } - } - - virtual void MouseWheel(Deprecated::WorldSceneWidget& widget, - MouseWheelDirection direction, - KeyboardModifiers modifiers, - Deprecated::IStatusBar* statusBar) - { - int scale = (modifiers & KeyboardModifiers_Control ? 10 : 1); - - switch (direction) - { - case MouseWheelDirection_Up: - application_.OffsetSlice(-scale); - break; - - case MouseWheelDirection_Down: - application_.OffsetSlice(scale); - break; - - default: - break; - } - } - - virtual void KeyPressed(Deprecated::WorldSceneWidget& widget, - KeyboardKeys key, - char keyChar, - KeyboardModifiers modifiers, - Deprecated::IStatusBar* statusBar) - { - switch (keyChar) - { - case 's': - widget.FitContent(); - break; - - default: - break; - } - } - }; - - - void OffsetSlice(int offset) - { - if (source_) - { - int slice = static_cast<int>(slice_) + offset; - - if (slice < 0) - { - slice = 0; - } - - if (slice >= static_cast<int>(source_->GetSlicesCount())) - { - slice = static_cast<int>(source_->GetSlicesCount()) - 1; - } - - if (slice != static_cast<int>(slice_)) - { - SetSlice(slice); - } - } - } - - - void SetSlice(size_t index) - { - if (source_ && - index < source_->GetSlicesCount()) - { - slice_ = static_cast<unsigned int>(index); - -#if 1 - widget_->SetSlice(source_->GetSlice(slice_).GetGeometry()); -#else - // TEST for scene extents - Rotate the axes - double a = 15.0 / 180.0 * boost::math::constants::pi<double>(); - -#if 1 - Vector x; GeometryToolbox::AssignVector(x, cos(a), sin(a), 0); - Vector y; GeometryToolbox::AssignVector(y, -sin(a), cos(a), 0); -#else - // Flip the normal - Vector x; GeometryToolbox::AssignVector(x, cos(a), sin(a), 0); - Vector y; GeometryToolbox::AssignVector(y, sin(a), -cos(a), 0); -#endif - - SliceGeometry s(source_->GetSlice(slice_).GetGeometry().GetOrigin(), x, y); - widget_->SetSlice(s); -#endif - } - } - - - void OnMainWidgetGeometryReady(const Deprecated::IVolumeSlicer::GeometryReadyMessage& message) - { - // Once the geometry of the series is downloaded from Orthanc, - // display its middle slice, and adapt the viewport to fit this - // slice - if (source_ && - source_.get() == &message.GetOrigin()) - { - SetSlice(source_->GetSlicesCount() / 2); - } - - widget_->FitContent(); - } - - boost::shared_ptr<Deprecated::SliceViewerWidget> widget_; - std::unique_ptr<Interactor> mainWidgetInteractor_; - boost::shared_ptr<Deprecated::DicomSeriesVolumeSlicer> source_; - unsigned int slice_; - - public: - SingleFrameApplication() : - slice_(0) - { - } - - virtual void DeclareStartupOptions(boost::program_options::options_description& options) - { - boost::program_options::options_description generic("Sample options"); - generic.add_options() - ("instance", boost::program_options::value<std::string>(), - "Orthanc ID of the instance") - ("frame", boost::program_options::value<unsigned int>()->default_value(0), - "Number of the frame, for multi-frame DICOM instances") - ("smooth", boost::program_options::value<bool>()->default_value(true), - "Enable bilinear interpolation to smooth the image") - ; - - options.add(generic); - } - - virtual void Initialize(StoneApplicationContext* context, - Deprecated::IStatusBar& statusBar, - const boost::program_options::variables_map& parameters) - { - using namespace OrthancStone; - - context_ = context; - - statusBar.SetMessage("Use the key \"s\" to reinitialize the layout"); - - if (parameters.count("instance") != 1) - { - LOG(ERROR) << "The instance ID is missing"; - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - std::string instance = parameters["instance"].as<std::string>(); - int frame = parameters["frame"].as<unsigned int>(); - - widget_.reset(new Deprecated::SliceViewerWidget("main-widget")); - SetCentralWidget(widget_); - - boost::shared_ptr<Deprecated::DicomSeriesVolumeSlicer> layer(new Deprecated::DicomSeriesVolumeSlicer); - layer->Connect(context->GetOrthancApiClient()); - source_ = layer; - - layer->LoadFrame(instance, frame); - Register<Deprecated::IVolumeSlicer::GeometryReadyMessage>(*layer, &SingleFrameApplication::OnMainWidgetGeometryReady); - widget_->AddLayer(layer); - - Deprecated::RenderStyle s; - - if (parameters["smooth"].as<bool>()) - { - s.interpolation_ = ImageInterpolation_Bilinear; - } - - widget_->SetLayerStyle(0, s); - widget_->SetTransmitMouseOver(true); - - mainWidgetInteractor_.reset(new Interactor(*this)); - widget_->SetInteractor(*mainWidgetInteractor_); - } - }; - - - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SingleFrameEditorApplication.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,531 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "SampleApplicationBase.h" - -#include "../../../Framework/Radiography/RadiographyLayerCropTracker.h" -#include "../../../Framework/Radiography/RadiographyLayerMaskTracker.h" -#include "../../../Framework/Radiography/RadiographyLayerMoveTracker.h" -#include "../../../Framework/Radiography/RadiographyLayerResizeTracker.h" -#include "../../../Framework/Radiography/RadiographyLayerRotateTracker.h" -#include "../../../Framework/Radiography/RadiographyMaskLayer.h" -#include "../../../Framework/Radiography/RadiographyScene.h" -#include "../../../Framework/Radiography/RadiographySceneCommand.h" -#include "../../../Framework/Radiography/RadiographySceneReader.h" -#include "../../../Framework/Radiography/RadiographySceneWriter.h" -#include "../../../Framework/Radiography/RadiographyWidget.h" -#include "../../../Framework/Radiography/RadiographyWindowingTracker.h" -#include "../../../Framework/Toolbox/TextRenderer.h" - -#include <Core/HttpClient.h> -#include <Core/Logging.h> -#include <Core/OrthancException.h> -#include <Core/Images/PngWriter.h> -#include <Core/Images/PngReader.h> - - -// Export using PAM is faster than using PNG, but requires Orthanc -// core >= 1.4.3 -#define EXPORT_USING_PAM 1 - - -namespace OrthancStone -{ - namespace Samples - { - class RadiographyEditorInteractor : - public Deprecated::IWorldSceneInteractor, - public ObserverBase<RadiographyEditorInteractor> - { - private: - enum Tool - { - Tool_Move, - Tool_Rotate, - Tool_Crop, - Tool_Resize, - Tool_Mask, - Tool_Windowing - }; - - - StoneApplicationContext* context_; - UndoRedoStack undoRedoStack_; - Tool tool_; - RadiographyMaskLayer* maskLayer_; - - - static double GetHandleSize() - { - return 10.0; - } - - - public: - RadiographyEditorInteractor() : - context_(NULL), - tool_(Tool_Move), - maskLayer_(NULL) - { - } - - void SetContext(StoneApplicationContext& context) - { - context_ = &context; - } - - void SetMaskLayer(RadiographyMaskLayer* maskLayer) - { - maskLayer_ = maskLayer; - } - virtual Deprecated::IWorldSceneMouseTracker* CreateMouseTracker(Deprecated::WorldSceneWidget& worldWidget, - const Deprecated::ViewportGeometry& view, - MouseButton button, - KeyboardModifiers modifiers, - int viewportX, - int viewportY, - double x, - double y, - Deprecated::IStatusBar* statusBar, - const std::vector<Deprecated::Touch>& displayTouches) - { - RadiographyWidget& widget = dynamic_cast<RadiographyWidget&>(worldWidget); - - if (button == MouseButton_Left) - { - size_t selected; - - if (tool_ == Tool_Windowing) - { - return new RadiographyWindowingTracker( - undoRedoStack_, - widget.GetScene(), - widget, - OrthancStone::ImageInterpolation_Nearest, - viewportX, viewportY, - RadiographyWindowingTracker::Action_DecreaseWidth, - RadiographyWindowingTracker::Action_IncreaseWidth, - RadiographyWindowingTracker::Action_DecreaseCenter, - RadiographyWindowingTracker::Action_IncreaseCenter); - } - else if (!widget.LookupSelectedLayer(selected)) - { - // No layer is currently selected - size_t layer; - if (widget.GetScene().LookupLayer(layer, x, y)) - { - widget.Select(layer); - } - - return NULL; - } - else if (tool_ == Tool_Crop || - tool_ == Tool_Resize || - tool_ == Tool_Mask) - { - RadiographyScene::LayerAccessor accessor(widget.GetScene(), selected); - - ControlPoint controlPoint; - if (accessor.GetLayer().LookupControlPoint(controlPoint, x, y, view.GetZoom(), GetHandleSize())) - { - switch (tool_) - { - case Tool_Crop: - return new RadiographyLayerCropTracker - (undoRedoStack_, widget.GetScene(), view, selected, controlPoint); - - case Tool_Mask: - return new RadiographyLayerMaskTracker - (undoRedoStack_, widget.GetScene(), view, selected, controlPoint); - - case Tool_Resize: - return new RadiographyLayerResizeTracker - (undoRedoStack_, widget.GetScene(), selected, controlPoint, - (modifiers & KeyboardModifiers_Shift)); - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - } - else - { - size_t layer; - - if (widget.GetScene().LookupLayer(layer, x, y)) - { - widget.Select(layer); - } - else - { - widget.Unselect(); - } - - return NULL; - } - } - else - { - size_t layer; - - if (widget.GetScene().LookupLayer(layer, x, y)) - { - if (layer == selected) - { - switch (tool_) - { - case Tool_Move: - return new RadiographyLayerMoveTracker - (undoRedoStack_, widget.GetScene(), layer, x, y, - (modifiers & KeyboardModifiers_Shift)); - - case Tool_Rotate: - return new RadiographyLayerRotateTracker - (undoRedoStack_, widget.GetScene(), view, layer, x, y, - (modifiers & KeyboardModifiers_Shift)); - - default: - break; - } - - return NULL; - } - else - { - widget.Select(layer); - return NULL; - } - } - else - { - widget.Unselect(); - return NULL; - } - } - } - else - { - return NULL; - } - return NULL; - } - - virtual void MouseOver(CairoContext& context, - Deprecated::WorldSceneWidget& worldWidget, - const Deprecated::ViewportGeometry& view, - double x, - double y, - Deprecated::IStatusBar* statusBar) - { - RadiographyWidget& widget = dynamic_cast<RadiographyWidget&>(worldWidget); - -#if 0 - if (statusBar != NULL) - { - char buf[64]; - sprintf(buf, "X = %.02f Y = %.02f (in cm)", x / 10.0, y / 10.0); - statusBar->SetMessage(buf); - } -#endif - - size_t selected; - - if (widget.LookupSelectedLayer(selected) && - (tool_ == Tool_Crop || - tool_ == Tool_Resize || - tool_ == Tool_Mask)) - { - RadiographyScene::LayerAccessor accessor(widget.GetScene(), selected); - - ControlPoint controlPoint; - if (accessor.GetLayer().LookupControlPoint(controlPoint, x, y, view.GetZoom(), GetHandleSize())) - { - double z = 1.0 / view.GetZoom(); - - context.SetSourceColor(255, 0, 0); - cairo_t* cr = context.GetObject(); - cairo_set_line_width(cr, 2.0 * z); - cairo_move_to(cr, controlPoint.x - GetHandleSize() * z, controlPoint.y - GetHandleSize() * z); - cairo_line_to(cr, controlPoint.x + GetHandleSize() * z, controlPoint.y - GetHandleSize() * z); - cairo_line_to(cr, controlPoint.x + GetHandleSize() * z, controlPoint.y + GetHandleSize() * z); - cairo_line_to(cr, controlPoint.x - GetHandleSize() * z, controlPoint.y + GetHandleSize() * z); - cairo_line_to(cr, controlPoint.x - GetHandleSize() * z, controlPoint.y - GetHandleSize() * z); - cairo_stroke(cr); - } - } - } - - virtual void MouseWheel(Deprecated::WorldSceneWidget& widget, - MouseWheelDirection direction, - KeyboardModifiers modifiers, - Deprecated::IStatusBar* statusBar) - { - } - - virtual void KeyPressed(Deprecated::WorldSceneWidget& worldWidget, - KeyboardKeys key, - char keyChar, - KeyboardModifiers modifiers, - Deprecated::IStatusBar* statusBar) - { - RadiographyWidget& widget = dynamic_cast<RadiographyWidget&>(worldWidget); - - switch (keyChar) - { - case 'a': - widget.FitContent(); - break; - - case 'c': - tool_ = Tool_Crop; - break; - - case 'm': - tool_ = Tool_Mask; - widget.Select(1); - break; - - case 'd': - { - // dump to json and reload - Json::Value snapshot; - RadiographySceneWriter writer; - writer.Write(snapshot, widget.GetScene()); - - LOG(INFO) << "JSON export was successful: " - << snapshot.toStyledString(); - - boost::shared_ptr<RadiographyScene> scene(new RadiographyScene); - RadiographySceneReader reader(*scene, *context_->GetOrthancApiClient()); - reader.Read(snapshot); - - widget.SetScene(scene); - };break; - - case 'e': - { - Orthanc::DicomMap tags; - - // Minimal set of tags to generate a valid CR image - tags.SetValue(Orthanc::DICOM_TAG_ACCESSION_NUMBER, "NOPE", false); - tags.SetValue(Orthanc::DICOM_TAG_BODY_PART_EXAMINED, "PELVIS", false); - tags.SetValue(Orthanc::DICOM_TAG_INSTANCE_NUMBER, "1", false); - //tags.SetValue(Orthanc::DICOM_TAG_LATERALITY, "", false); - tags.SetValue(Orthanc::DICOM_TAG_MANUFACTURER, "OSIMIS", false); - tags.SetValue(Orthanc::DICOM_TAG_MODALITY, "CR", false); - tags.SetValue(Orthanc::DICOM_TAG_PATIENT_BIRTH_DATE, "20000101", false); - tags.SetValue(Orthanc::DICOM_TAG_PATIENT_ID, "hello", false); - tags.SetValue(Orthanc::DICOM_TAG_PATIENT_NAME, "HELLO^WORLD", false); - tags.SetValue(Orthanc::DICOM_TAG_PATIENT_ORIENTATION, "", false); - tags.SetValue(Orthanc::DICOM_TAG_PATIENT_SEX, "M", false); - tags.SetValue(Orthanc::DICOM_TAG_REFERRING_PHYSICIAN_NAME, "HOUSE^MD", false); - tags.SetValue(Orthanc::DICOM_TAG_SERIES_NUMBER, "1", false); - tags.SetValue(Orthanc::DICOM_TAG_SOP_CLASS_UID, "1.2.840.10008.5.1.4.1.1.1", false); - tags.SetValue(Orthanc::DICOM_TAG_STUDY_ID, "STUDY", false); - tags.SetValue(Orthanc::DICOM_TAG_VIEW_POSITION, "", false); - - if (context_ != NULL) - { - widget.GetScene().ExportDicom(*context_->GetOrthancApiClient(), - tags, std::string(), 0.1, 0.1, widget.IsInverted(), - false /* autoCrop */, widget.GetInterpolation(), EXPORT_USING_PAM); - } - - break; - } - - case 'i': - widget.SwitchInvert(); - break; - - case 't': - tool_ = Tool_Move; - break; - - case 'n': - { - switch (widget.GetInterpolation()) - { - case ImageInterpolation_Nearest: - LOG(INFO) << "Switching to bilinear interpolation"; - widget.SetInterpolation(ImageInterpolation_Bilinear); - break; - - case ImageInterpolation_Bilinear: - LOG(INFO) << "Switching to nearest neighbor interpolation"; - widget.SetInterpolation(ImageInterpolation_Nearest); - break; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - - break; - } - - case 'r': - tool_ = Tool_Rotate; - break; - - case 's': - tool_ = Tool_Resize; - break; - - case 'w': - tool_ = Tool_Windowing; - break; - - case 'y': - if (modifiers & KeyboardModifiers_Control) - { - undoRedoStack_.Redo(); - widget.NotifyContentChanged(); - } - break; - - case 'z': - if (modifiers & KeyboardModifiers_Control) - { - undoRedoStack_.Undo(); - widget.NotifyContentChanged(); - } - break; - - default: - break; - } - } - }; - - - - class SingleFrameEditorApplication : - public SampleSingleCanvasApplicationBase, - public IObserver - { - private: - boost::shared_ptr<RadiographyScene> scene_; - RadiographyEditorInteractor interactor_; - RadiographyMaskLayer* maskLayer_; - - public: - virtual ~SingleFrameEditorApplication() - { - LOG(WARNING) << "Destroying the application"; - } - - virtual void DeclareStartupOptions(boost::program_options::options_description& options) - { - boost::program_options::options_description generic("Sample options"); - generic.add_options() - ("instance", boost::program_options::value<std::string>(), - "Orthanc ID of the instance") - ("frame", boost::program_options::value<unsigned int>()->default_value(0), - "Number of the frame, for multi-frame DICOM instances") - ; - - options.add(generic); - } - - virtual void Initialize(StoneApplicationContext* context, - Deprecated::IStatusBar& statusBar, - const boost::program_options::variables_map& parameters) - { - using namespace OrthancStone; - - context_ = context; - interactor_.SetContext(*context); - - statusBar.SetMessage("Use the key \"a\" to reinitialize the layout"); - statusBar.SetMessage("Use the key \"c\" to crop"); - statusBar.SetMessage("Use the key \"e\" to export DICOM to the Orthanc server"); - statusBar.SetMessage("Use the key \"f\" to switch full screen"); - statusBar.SetMessage("Use the key \"i\" to invert contrast"); - statusBar.SetMessage("Use the key \"m\" to modify the mask"); - statusBar.SetMessage("Use the key \"n\" to switch between nearest neighbor and bilinear interpolation"); - statusBar.SetMessage("Use the key \"r\" to rotate objects"); - statusBar.SetMessage("Use the key \"s\" to resize objects (not applicable to DICOM layers)"); - statusBar.SetMessage("Use the key \"t\" to move (translate) objects"); - statusBar.SetMessage("Use the key \"w\" to change windowing"); - - statusBar.SetMessage("Use the key \"ctrl-z\" to undo action"); - statusBar.SetMessage("Use the key \"ctrl-y\" to redo action"); - - if (parameters.count("instance") != 1) - { - LOG(ERROR) << "The instance ID is missing"; - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - std::string instance = parameters["instance"].as<std::string>(); - //int frame = parameters["frame"].as<unsigned int>(); - - scene_.reset(new RadiographyScene); - - RadiographyLayer& dicomLayer = scene_->LoadDicomFrame(*context->GetOrthancApiClient(), instance, 0, false, NULL); - //scene_->LoadDicomFrame(instance, frame, false); //.SetPan(200, 0); - // = scene_->LoadDicomFrame(context->GetOrthancApiClient(), "61f3143e-96f34791-ad6bbb8d-62559e75-45943e1b", 0, false, NULL); - -#if !defined(ORTHANC_ENABLE_WASM) || ORTHANC_ENABLE_WASM != 1 - Orthanc::HttpClient::ConfigureSsl(true, "/etc/ssl/certs/ca-certificates.crt"); -#endif - - //scene_->LoadDicomWebFrame(context->GetWebService()); - - std::vector<Orthanc::ImageProcessing::ImagePoint> mask; - mask.push_back(Orthanc::ImageProcessing::ImagePoint(1100, 100)); - mask.push_back(Orthanc::ImageProcessing::ImagePoint(1100, 1000)); - mask.push_back(Orthanc::ImageProcessing::ImagePoint(2000, 1000)); - mask.push_back(Orthanc::ImageProcessing::ImagePoint(2200, 150)); - mask.push_back(Orthanc::ImageProcessing::ImagePoint(1500, 550)); - maskLayer_ = dynamic_cast<RadiographyMaskLayer*>(&(scene_->LoadMask(mask, dynamic_cast<RadiographyDicomLayer&>(dicomLayer), 128.0f, NULL))); - interactor_.SetMaskLayer(maskLayer_); - - { - std::unique_ptr<Orthanc::ImageAccessor> renderedTextAlpha(TextRenderer::Render(Orthanc::EmbeddedResources::UBUNTU_FONT, 100, - "%öÇaA&#")); - RadiographyLayer& layer = scene_->LoadAlphaBitmap(renderedTextAlpha.release(), NULL); - dynamic_cast<RadiographyAlphaLayer&>(layer).SetForegroundValue(200.0f * 256.0f); - } - - { - RadiographyTextLayer::RegisterFont("ubuntu", Orthanc::EmbeddedResources::UBUNTU_FONT); - RadiographyLayer& layer = scene_->LoadText("Hello\nworld", "ubuntu", 20, 128, NULL, false); - layer.SetResizeable(true); - } - - { - RadiographyLayer& layer = scene_->LoadTestBlock(100, 50, NULL); - layer.SetResizeable(true); - layer.SetPan(0, 200); - } - - boost::shared_ptr<RadiographyWidget> widget(new RadiographyWidget(scene_, "main-widget")); - widget->SetTransmitMouseOver(true); - widget->SetInteractor(interactor_); - SetCentralWidget(widget); - - //scene_->SetWindowing(128, 256); - } - }; - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SingleVolumeApplication.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,277 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "SampleApplicationBase.h" -#include "../../../Framework/dev.h" -#include "../../../Framework/Layers/LineMeasureTracker.h" -#include "../../../Framework/Layers/CircleMeasureTracker.h" - -#include <Core/Toolbox.h> -#include <Core/Logging.h> - -#include <Plugins/Samples/Common/OrthancHttpConnection.h> // TODO REMOVE -#include "../../../Framework/Layers/DicomStructureSetSlicer.h" // TODO REMOVE -#include "../../../Framework/Toolbox/MessagingToolbox.h" // TODO REMOVE - -namespace OrthancStone -{ - namespace Samples - { - class SingleVolumeApplication : public SampleApplicationBase - { - private: - class Interactor : public VolumeImageInteractor - { - private: - SliceViewerWidget& widget_; - size_t layer_; - - protected: - virtual void NotifySliceContentChange(const ISlicedVolume& volume, - const size_t& sliceIndex, - const Slice& slice) - { - const OrthancVolumeImage& image = dynamic_cast<const OrthancVolumeImage&>(volume); - - RenderStyle s = widget_.GetLayerStyle(layer_); - - if (image.FitWindowingToRange(s, slice.GetConverter())) - { - //printf("Windowing: %f => %f\n", s.customWindowCenter_, s.customWindowWidth_); - widget_.SetLayerStyle(layer_, s); - } - } - - virtual void MouseOver(CairoContext& context, - WorldSceneWidget& widget, - const ViewportGeometry& view, - double x, - double y, - IStatusBar* statusBar) - { - const SliceViewerWidget& w = dynamic_cast<const SliceViewerWidget&>(widget); - Vector p = w.GetSlice().MapSliceToWorldCoordinates(x, y); - printf("%f %f %f\n", p[0], p[1], p[2]); - } - - public: - Interactor(OrthancVolumeImage& volume, - SliceViewerWidget& widget, - VolumeProjection projection, - size_t layer) : - VolumeImageInteractor(volume, widget, projection), - widget_(widget), - layer_(layer) - { - } - }; - - - public: - virtual void DeclareStartupOptions(boost::program_options::options_description& options) - { - boost::program_options::options_description generic("Sample options"); - generic.add_options() - ("series", boost::program_options::value<std::string>(), - "Orthanc ID of the series") - ("instance", boost::program_options::value<std::string>(), - "Orthanc ID of a multi-frame instance that describes a 3D volume") - ("threads", boost::program_options::value<unsigned int>()->default_value(3), - "Number of download threads") - ("projection", boost::program_options::value<std::string>()->default_value("axial"), - "Projection of interest (can be axial, sagittal or coronal)") - ("reverse", boost::program_options::value<bool>()->default_value(false), - "Reverse the normal direction of the volume") - ; - - options.add(generic); - } - - virtual void Initialize(IStatusBar& statusBar, - const boost::program_options::variables_map& parameters) - { - using namespace OrthancStone; - - if (parameters.count("series") > 1 || - parameters.count("instance") > 1) - { - LOG(ERROR) << "Only one series or instance is allowed"; - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - if (parameters.count("series") == 1 && - parameters.count("instance") == 1) - { - LOG(ERROR) << "Cannot specify both a series and an instance"; - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - std::string series; - if (parameters.count("series") == 1) - { - series = parameters["series"].as<std::string>(); - } - - std::string instance; - if (parameters.count("instance") == 1) - { - instance = parameters["instance"].as<std::string>(); - } - - if (series.empty() && - instance.empty()) - { - LOG(ERROR) << "The series ID or instance ID is missing"; - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - //unsigned int threads = parameters["threads"].as<unsigned int>(); - //bool reverse = parameters["reverse"].as<bool>(); - - std::string tmp = parameters["projection"].as<std::string>(); - Orthanc::Toolbox::ToLowerCase(tmp); - - VolumeProjection projection; - if (tmp == "axial") - { - projection = VolumeProjection_Axial; - } - else if (tmp == "sagittal") - { - projection = VolumeProjection_Sagittal; - } - else if (tmp == "coronal") - { - projection = VolumeProjection_Coronal; - } - else - { - LOG(ERROR) << "Unknown projection: " << tmp; - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - std::unique_ptr<SliceViewerWidget> widget(new SliceViewerWidget); - -#if 1 - std::unique_ptr<OrthancVolumeImage> volume(new OrthancVolumeImage(context.GetWebService(), true)); - if (series.empty()) - { - volume->ScheduleLoadInstance(instance); - } - else - { - volume->ScheduleLoadSeries(series); - } - - widget->AddLayer(new VolumeImageMPRSlicer(*volume)); - - context_->AddInteractor(new Interactor(*volume, *widget, projection, 0)); - context_->AddSlicedVolume(volume.release()); - - if (1) - { - RenderStyle s; - //s.drawGrid_ = true; - s.alpha_ = 1; - s.windowing_ = ImageWindowing_Bone; - widget->SetLayerStyle(0, s); - } - else - { - RenderStyle s; - s.alpha_ = 1; - s.applyLut_ = true; - s.lut_ = Orthanc::EmbeddedResources::COLORMAP_JET; - s.interpolation_ = ImageInterpolation_Bilinear; - widget->SetLayerStyle(0, s); - } -#else - std::unique_ptr<OrthancVolumeImage> ct(new OrthancVolumeImage(context_->GetWebService(), false)); - //ct->ScheduleLoadSeries("15a6f44a-ac7b88fe-19c462d9-dddd918e-b01550d8"); // 0178023P - //ct->ScheduleLoadSeries("dd069910-4f090474-7d2bba07-e5c10783-f9e4fb1d"); - //ct->ScheduleLoadSeries("a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa"); // IBA - //ct->ScheduleLoadSeries("03677739-1d8bca40-db1daf59-d74ff548-7f6fc9c0"); // 0522c0001 TCIA - ct->ScheduleLoadSeries("295e8a13-dfed1320-ba6aebb2-9a13e20f-1b3eb953"); // Captain - - std::unique_ptr<OrthancVolumeImage> pet(new OrthancVolumeImage(context_->GetWebService(), true)); - //pet->ScheduleLoadSeries("48d2997f-8e25cd81-dd715b64-bd79cdcc-e8fcee53"); // 0178023P - //pet->ScheduleLoadSeries("aabad2e7-80702b5d-e599d26c-4f13398e-38d58a9e"); - //pet->ScheduleLoadInstance("830a69ff-8e4b5ee3-b7f966c8-bccc20fb-d322dceb"); // IBA 1 - //pet->ScheduleLoadInstance("337876a1-a68a9718-f15abccd-38faafa1-b99b496a"); // IBA 2 - //pet->ScheduleLoadInstance("830a69ff-8e4b5ee3-b7f966c8-bccc20fb-d322dceb"); // IBA 3 - //pet->ScheduleLoadInstance("269f26f4-0c83eeeb-2e67abbd-5467a40f-f1bec90c"); // 0522c0001 TCIA - pet->ScheduleLoadInstance("f080888c-0ab7528a-f7d9c28c-84980eb1-ff3b0ae6"); // Captain 1 - //pet->ScheduleLoadInstance("4f78055b-6499a2c5-1e089290-394acc05-3ec781c1"); // Captain 2 - - std::unique_ptr<StructureSetLoader> rtStruct(new StructureSetLoader(context_->GetWebService())); - //rtStruct->ScheduleLoadInstance("c2ebc17b-6b3548db-5e5da170-b8ecab71-ea03add3"); // 0178023P - //rtStruct->ScheduleLoadInstance("54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9"); // IBA - //rtStruct->ScheduleLoadInstance("17cd032b-ad92a438-ca05f06a-f9e96668-7e3e9e20"); // 0522c0001 TCIA - rtStruct->ScheduleLoadInstance("96c889ab-29fe5c54-dda6e66c-3949e4da-58f90d75"); // Captain - - widget->AddLayer(new VolumeImageMPRSlicer(*ct)); - widget->AddLayer(new VolumeImageMPRSlicer(*pet)); - widget->AddLayer(new DicomStructureSetSlicer(*rtStruct)); - - context_->AddInteractor(new Interactor(*pet, *widget, projection, 1)); - //context_->AddInteractor(new VolumeImageInteractor(*ct, *widget, projection)); - - context_->AddSlicedVolume(ct.release()); - context_->AddSlicedVolume(pet.release()); - context_->AddVolumeLoader(rtStruct.release()); - - { - RenderStyle s; - //s.drawGrid_ = true; - s.alpha_ = 1; - s.windowing_ = ImageWindowing_Bone; - widget->SetLayerStyle(0, s); - } - - { - RenderStyle s; - //s.drawGrid_ = true; - s.SetColor(255, 0, 0); // Draw missing PET layer in red - s.alpha_ = 0.5; - s.applyLut_ = true; - s.lut_ = Orthanc::EmbeddedResources::COLORMAP_JET; - s.interpolation_ = ImageInterpolation_Bilinear; - s.windowing_ = ImageWindowing_Custom; - s.customWindowCenter_ = 0; - s.customWindowWidth_ = 128; - widget->SetLayerStyle(1, s); - } -#endif - - - statusBar.SetMessage("Use the keys \"b\", \"l\" and \"d\" to change Hounsfield windowing"); - statusBar.SetMessage("Use the keys \"t\" to track the (X,Y,Z) mouse coordinates"); - statusBar.SetMessage("Use the keys \"m\" to measure distances"); - statusBar.SetMessage("Use the keys \"c\" to draw circles"); - - widget->SetTransmitMouseOver(true); - context_->SetCentralWidget(widget.release()); - } - }; - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/StoneSampleCommands.yml Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -# -# 1 2 3 4 5 6 7 8 -# 345678901234567890123456789012345678901234567890123456789012345678901234567890 -# -rootName: StoneSampleCommands - -# +---------------------------------+ -# | Messages from TypeScript to C++ | -# +---------------------------------+ - -enum Tool: - - LineMeasure - - CircleMeasure - - Crop - - Windowing - - Zoom - - Pan - - Move - - Rotate - - Resize - - Mask - -struct SelectTool: - __handler: cpp - tool: Tool - -enum ActionType: - - UndoCrop - - Rotate - - Invert - -struct Action: - __handler: cpp - type: ActionType -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/StoneSampleCommands_generate.py Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -import sys -import os - -# add the generation script location to the search paths -sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'Resources', 'CodeGeneration')) - -# import the code generation tooling script -import stonegentool - -schemaFile = os.path.join(os.path.dirname(__file__), 'StoneSampleCommands.yml') -outDir = os.path.dirname(__file__) - -# ignition! -stonegentool.Process(schemaFile, outDir) - -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/StoneSampleCommands_generated.hpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,703 +0,0 @@ -/* - 1 2 3 4 5 6 7 -12345678901234567890123456789012345678901234567890123456789012345678901234567890 - -Generated on 2019-03-18 12:07:42.696093 by stonegentool - -*/ -#pragma once - -#include <exception> -#include <iostream> -#include <string> -#include <sstream> -#include <assert.h> -#include <memory> -#include <json/json.h> - -//#define STONEGEN_NO_CPP11 1 - -#ifdef STONEGEN_NO_CPP11 -#define StoneSmartPtr std::unique_ptr -#else -#define StoneSmartPtr std::unique_ptr -#endif - -namespace StoneSampleCommands -{ - /** Throws in case of problem */ - inline void _StoneDeserializeValue(int32_t& destValue, const Json::Value& jsonValue) - { - destValue = jsonValue.asInt(); - } - - inline Json::Value _StoneSerializeValue(int32_t value) - { - Json::Value result(value); - return result; - } - - inline void _StoneDeserializeValue(Json::Value& destValue, const Json::Value& jsonValue) - { - destValue = jsonValue; - } - - inline Json::Value _StoneSerializeValue(Json::Value value) - { - return value; - } - - /** Throws in case of problem */ - inline void _StoneDeserializeValue(double& destValue, const Json::Value& jsonValue) - { - destValue = jsonValue.asDouble(); - } - - inline Json::Value _StoneSerializeValue(double value) - { - Json::Value result(value); - return result; - } - - /** Throws in case of problem */ - inline void _StoneDeserializeValue(bool& destValue, const Json::Value& jsonValue) - { - destValue = jsonValue.asBool(); - } - - inline Json::Value _StoneSerializeValue(bool value) - { - Json::Value result(value); - return result; - } - - /** Throws in case of problem */ - inline void _StoneDeserializeValue( - std::string& destValue - , const Json::Value& jsonValue) - { - destValue = jsonValue.asString(); - } - - inline Json::Value _StoneSerializeValue(const std::string& value) - { - // the following is better than - Json::Value result(value.data(),value.data()+value.size()); - return result; - } - - inline std::string MakeIndent(size_t indent) - { - char* txt = reinterpret_cast<char*>(malloc(indent+1)); // NO EXCEPTION BELOW!!!!!!!!!!!! - for(size_t i = 0; i < indent; ++i) - txt[i] = ' '; - txt[indent] = 0; - std::string retVal(txt); - free(txt); // NO EXCEPTION ABOVE !!!!!!!!!! - return retVal; - } - - // generic dumper - template<typename T> - std::ostream& StoneDumpValue(std::ostream& out, const T& value, size_t indent) - { - out << MakeIndent(indent) << value; - return out; - } - - // string dumper - inline std::ostream& StoneDumpValue(std::ostream& out, const std::string& value, size_t indent) - { - out << MakeIndent(indent) << "\"" << value << "\""; - return out; - } - - /** Throws in case of problem */ - template<typename T> - void _StoneDeserializeValue( - std::map<std::string, T>& destValue, const Json::Value& jsonValue) - { - destValue.clear(); - for ( - Json::Value::const_iterator itr = jsonValue.begin(); - itr != jsonValue.end(); - itr++) - { - std::string key; - _StoneDeserializeValue(key, itr.key()); - - T innerDestValue; - _StoneDeserializeValue(innerDestValue, *itr); - - destValue[key] = innerDestValue; - } - } - - template<typename T> - Json::Value _StoneSerializeValue(const std::map<std::string,T>& value) - { - Json::Value result(Json::objectValue); - - for (typename std::map<std::string, T>::const_iterator it = value.cbegin(); - it != value.cend(); ++it) - { - // it->first it->second - result[it->first] = _StoneSerializeValue(it->second); - } - return result; - } - - template<typename T> - std::ostream& StoneDumpValue(std::ostream& out, const std::map<std::string,T>& value, size_t indent) - { - out << MakeIndent(indent) << "{\n"; - for (typename std::map<std::string, T>::const_iterator it = value.cbegin(); - it != value.cend(); ++it) - { - out << MakeIndent(indent+2) << "\"" << it->first << "\" : "; - StoneDumpValue(out, it->second, indent+2); - } - out << MakeIndent(indent) << "}\n"; - return out; - } - - /** Throws in case of problem */ - template<typename T> - void _StoneDeserializeValue( - std::vector<T>& destValue, const Json::Value& jsonValue) - { - destValue.clear(); - destValue.reserve(jsonValue.size()); - for (Json::Value::ArrayIndex i = 0; i != jsonValue.size(); i++) - { - T innerDestValue; - _StoneDeserializeValue(innerDestValue, jsonValue[i]); - destValue.push_back(innerDestValue); - } - } - - template<typename T> - Json::Value _StoneSerializeValue(const std::vector<T>& value) - { - Json::Value result(Json::arrayValue); - for (size_t i = 0; i < value.size(); ++i) - { - result.append(_StoneSerializeValue(value[i])); - } - return result; - } - - template<typename T> - std::ostream& StoneDumpValue(std::ostream& out, const std::vector<T>& value, size_t indent) - { - out << MakeIndent(indent) << "[\n"; - for (size_t i = 0; i < value.size(); ++i) - { - StoneDumpValue(out, value[i], indent+2); - } - out << MakeIndent(indent) << "]\n"; - return out; - } - - inline void StoneCheckSerializedValueTypeGeneric(const Json::Value& value) - { - if ((!value.isMember("type")) || (!value["type"].isString())) - { - std::stringstream ss; - ss << "Cannot deserialize value ('type' key invalid)"; - throw std::runtime_error(ss.str()); - } - } - - inline void StoneCheckSerializedValueType( - const Json::Value& value, std::string typeStr) - { - StoneCheckSerializedValueTypeGeneric(value); - - std::string actTypeStr = value["type"].asString(); - if (actTypeStr != typeStr) - { - std::stringstream ss; - ss << "Cannot deserialize type" << actTypeStr - << "into " << typeStr; - throw std::runtime_error(ss.str()); - } - } - - // end of generic methods - -// end of generic methods - - enum Tool { - Tool_LineMeasure, - Tool_CircleMeasure, - Tool_Crop, - Tool_Windowing, - Tool_Zoom, - Tool_Pan, - Tool_Move, - Tool_Rotate, - Tool_Resize, - Tool_Mask, - }; - - inline std::string ToString(const Tool& value) - { - if( value == Tool_LineMeasure) - { - return std::string("LineMeasure"); - } - if( value == Tool_CircleMeasure) - { - return std::string("CircleMeasure"); - } - if( value == Tool_Crop) - { - return std::string("Crop"); - } - if( value == Tool_Windowing) - { - return std::string("Windowing"); - } - if( value == Tool_Zoom) - { - return std::string("Zoom"); - } - if( value == Tool_Pan) - { - return std::string("Pan"); - } - if( value == Tool_Move) - { - return std::string("Move"); - } - if( value == Tool_Rotate) - { - return std::string("Rotate"); - } - if( value == Tool_Resize) - { - return std::string("Resize"); - } - if( value == Tool_Mask) - { - return std::string("Mask"); - } - std::stringstream ss; - ss << "Value \"" << value << "\" cannot be converted to Tool. Possible values are: " - << " LineMeasure = " << static_cast<int64_t>(Tool_LineMeasure) << ", " - << " CircleMeasure = " << static_cast<int64_t>(Tool_CircleMeasure) << ", " - << " Crop = " << static_cast<int64_t>(Tool_Crop) << ", " - << " Windowing = " << static_cast<int64_t>(Tool_Windowing) << ", " - << " Zoom = " << static_cast<int64_t>(Tool_Zoom) << ", " - << " Pan = " << static_cast<int64_t>(Tool_Pan) << ", " - << " Move = " << static_cast<int64_t>(Tool_Move) << ", " - << " Rotate = " << static_cast<int64_t>(Tool_Rotate) << ", " - << " Resize = " << static_cast<int64_t>(Tool_Resize) << ", " - << " Mask = " << static_cast<int64_t>(Tool_Mask) << ", " - << std::endl; - std::string msg = ss.str(); - throw std::runtime_error(msg); - } - - inline void FromString(Tool& value, std::string strValue) - { - if( strValue == std::string("LineMeasure") ) - { - value = Tool_LineMeasure; - return; - } - if( strValue == std::string("CircleMeasure") ) - { - value = Tool_CircleMeasure; - return; - } - if( strValue == std::string("Crop") ) - { - value = Tool_Crop; - return; - } - if( strValue == std::string("Windowing") ) - { - value = Tool_Windowing; - return; - } - if( strValue == std::string("Zoom") ) - { - value = Tool_Zoom; - return; - } - if( strValue == std::string("Pan") ) - { - value = Tool_Pan; - return; - } - if( strValue == std::string("Move") ) - { - value = Tool_Move; - return; - } - if( strValue == std::string("Rotate") ) - { - value = Tool_Rotate; - return; - } - if( strValue == std::string("Resize") ) - { - value = Tool_Resize; - return; - } - if( strValue == std::string("Mask") ) - { - value = Tool_Mask; - return; - } - - std::stringstream ss; - ss << "String \"" << strValue << "\" cannot be converted to Tool. Possible values are: LineMeasure CircleMeasure Crop Windowing Zoom Pan Move Rotate Resize Mask "; - std::string msg = ss.str(); - throw std::runtime_error(msg); - } - - - inline void _StoneDeserializeValue( - Tool& destValue, const Json::Value& jsonValue) - { - FromString(destValue, jsonValue.asString()); - } - - inline Json::Value _StoneSerializeValue(const Tool& value) - { - std::string strValue = ToString(value); - return Json::Value(strValue); - } - - inline std::ostream& StoneDumpValue(std::ostream& out, const Tool& value, size_t indent = 0) - { - if( value == Tool_LineMeasure) - { - out << MakeIndent(indent) << "LineMeasure" << std::endl; - } - if( value == Tool_CircleMeasure) - { - out << MakeIndent(indent) << "CircleMeasure" << std::endl; - } - if( value == Tool_Crop) - { - out << MakeIndent(indent) << "Crop" << std::endl; - } - if( value == Tool_Windowing) - { - out << MakeIndent(indent) << "Windowing" << std::endl; - } - if( value == Tool_Zoom) - { - out << MakeIndent(indent) << "Zoom" << std::endl; - } - if( value == Tool_Pan) - { - out << MakeIndent(indent) << "Pan" << std::endl; - } - if( value == Tool_Move) - { - out << MakeIndent(indent) << "Move" << std::endl; - } - if( value == Tool_Rotate) - { - out << MakeIndent(indent) << "Rotate" << std::endl; - } - if( value == Tool_Resize) - { - out << MakeIndent(indent) << "Resize" << std::endl; - } - if( value == Tool_Mask) - { - out << MakeIndent(indent) << "Mask" << std::endl; - } - return out; - } - - - enum ActionType { - ActionType_UndoCrop, - ActionType_Rotate, - ActionType_Invert, - }; - - inline std::string ToString(const ActionType& value) - { - if( value == ActionType_UndoCrop) - { - return std::string("UndoCrop"); - } - if( value == ActionType_Rotate) - { - return std::string("Rotate"); - } - if( value == ActionType_Invert) - { - return std::string("Invert"); - } - std::stringstream ss; - ss << "Value \"" << value << "\" cannot be converted to ActionType. Possible values are: " - << " UndoCrop = " << static_cast<int64_t>(ActionType_UndoCrop) << ", " - << " Rotate = " << static_cast<int64_t>(ActionType_Rotate) << ", " - << " Invert = " << static_cast<int64_t>(ActionType_Invert) << ", " - << std::endl; - std::string msg = ss.str(); - throw std::runtime_error(msg); - } - - inline void FromString(ActionType& value, std::string strValue) - { - if( strValue == std::string("UndoCrop") ) - { - value = ActionType_UndoCrop; - return; - } - if( strValue == std::string("Rotate") ) - { - value = ActionType_Rotate; - return; - } - if( strValue == std::string("Invert") ) - { - value = ActionType_Invert; - return; - } - - std::stringstream ss; - ss << "String \"" << strValue << "\" cannot be converted to ActionType. Possible values are: UndoCrop Rotate Invert "; - std::string msg = ss.str(); - throw std::runtime_error(msg); - } - - - inline void _StoneDeserializeValue( - ActionType& destValue, const Json::Value& jsonValue) - { - FromString(destValue, jsonValue.asString()); - } - - inline Json::Value _StoneSerializeValue(const ActionType& value) - { - std::string strValue = ToString(value); - return Json::Value(strValue); - } - - inline std::ostream& StoneDumpValue(std::ostream& out, const ActionType& value, size_t indent = 0) - { - if( value == ActionType_UndoCrop) - { - out << MakeIndent(indent) << "UndoCrop" << std::endl; - } - if( value == ActionType_Rotate) - { - out << MakeIndent(indent) << "Rotate" << std::endl; - } - if( value == ActionType_Invert) - { - out << MakeIndent(indent) << "Invert" << std::endl; - } - return out; - } - - - -#ifdef _MSC_VER -#pragma region SelectTool -#endif //_MSC_VER - - struct SelectTool - { - Tool tool; - - SelectTool(Tool tool = Tool()) - { - this->tool = tool; - } - }; - - inline void _StoneDeserializeValue(SelectTool& destValue, const Json::Value& value) - { - _StoneDeserializeValue(destValue.tool, value["tool"]); - } - - inline Json::Value _StoneSerializeValue(const SelectTool& value) - { - Json::Value result(Json::objectValue); - result["tool"] = _StoneSerializeValue(value.tool); - - return result; - } - - inline std::ostream& StoneDumpValue(std::ostream& out, const SelectTool& value, size_t indent = 0) - { - out << MakeIndent(indent) << "{\n"; - out << MakeIndent(indent) << "tool:\n"; - StoneDumpValue(out, value.tool,indent+2); - out << "\n"; - - out << MakeIndent(indent) << "}\n"; - return out; - } - - inline void StoneDeserialize(SelectTool& destValue, const Json::Value& value) - { - StoneCheckSerializedValueType(value, "StoneSampleCommands.SelectTool"); - _StoneDeserializeValue(destValue, value["value"]); - } - - inline Json::Value StoneSerializeToJson(const SelectTool& value) - { - Json::Value result(Json::objectValue); - result["type"] = "StoneSampleCommands.SelectTool"; - result["value"] = _StoneSerializeValue(value); - return result; - } - - inline std::string StoneSerialize(const SelectTool& value) - { - Json::Value resultJson = StoneSerializeToJson(value); - std::string resultStr = resultJson.toStyledString(); - return resultStr; - } - -#ifdef _MSC_VER -#pragma endregion SelectTool -#endif //_MSC_VER - -#ifdef _MSC_VER -#pragma region Action -#endif //_MSC_VER - - struct Action - { - ActionType type; - - Action(ActionType type = ActionType()) - { - this->type = type; - } - }; - - inline void _StoneDeserializeValue(Action& destValue, const Json::Value& value) - { - _StoneDeserializeValue(destValue.type, value["type"]); - } - - inline Json::Value _StoneSerializeValue(const Action& value) - { - Json::Value result(Json::objectValue); - result["type"] = _StoneSerializeValue(value.type); - - return result; - } - - inline std::ostream& StoneDumpValue(std::ostream& out, const Action& value, size_t indent = 0) - { - out << MakeIndent(indent) << "{\n"; - out << MakeIndent(indent) << "type:\n"; - StoneDumpValue(out, value.type,indent+2); - out << "\n"; - - out << MakeIndent(indent) << "}\n"; - return out; - } - - inline void StoneDeserialize(Action& destValue, const Json::Value& value) - { - StoneCheckSerializedValueType(value, "StoneSampleCommands.Action"); - _StoneDeserializeValue(destValue, value["value"]); - } - - inline Json::Value StoneSerializeToJson(const Action& value) - { - Json::Value result(Json::objectValue); - result["type"] = "StoneSampleCommands.Action"; - result["value"] = _StoneSerializeValue(value); - return result; - } - - inline std::string StoneSerialize(const Action& value) - { - Json::Value resultJson = StoneSerializeToJson(value); - std::string resultStr = resultJson.toStyledString(); - return resultStr; - } - -#ifdef _MSC_VER -#pragma endregion Action -#endif //_MSC_VER - -#ifdef _MSC_VER -#pragma region Dispatching code -#endif //_MSC_VER - - class IHandler - { - public: - virtual bool Handle(const SelectTool& value) = 0; - virtual bool Handle(const Action& value) = 0; - }; - - /** Service function for StoneDispatchToHandler */ - inline bool StoneDispatchJsonToHandler( - const Json::Value& jsonValue, IHandler* handler) - { - StoneCheckSerializedValueTypeGeneric(jsonValue); - std::string type = jsonValue["type"].asString(); - if (type == "") - { - // this should never ever happen - throw std::runtime_error("Caught empty type while dispatching"); - } - else if (type == "StoneSampleCommands.SelectTool") - { - SelectTool value; - _StoneDeserializeValue(value, jsonValue["value"]); - return handler->Handle(value); - } - else if (type == "StoneSampleCommands.Action") - { - Action value; - _StoneDeserializeValue(value, jsonValue["value"]); - return handler->Handle(value); - } - else - { - return false; - } - } - - /** Takes a serialized type and passes this to the handler */ - inline bool StoneDispatchToHandler(std::string strValue, IHandler* handler) - { - Json::Value readValue; - - Json::CharReaderBuilder builder; - Json::CharReader* reader = builder.newCharReader(); - - StoneSmartPtr<Json::CharReader> ptr(reader); - - std::string errors; - - bool ok = reader->parse( - strValue.c_str(), - strValue.c_str() + strValue.size(), - &readValue, - &errors - ); - if (!ok) - { - std::stringstream ss; - ss << "Jsoncpp parsing error: " << errors; - throw std::runtime_error(ss.str()); - } - return StoneDispatchJsonToHandler(readValue, handler); - } - -#ifdef _MSC_VER -#pragma endregion Dispatching code -#endif //_MSC_VER -} \ No newline at end of file
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/StoneSampleCommands_generated.ts Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,333 +0,0 @@ -/* - 1 2 3 4 5 6 7 -12345678901234567890123456789012345678901234567890123456789012345678901234567890 - -Generated on 2019-03-18 12:07:42.696093 by stonegentool - -*/ - -function StoneCheckSerializedValueType(value: any, typeStr: string) -{ - StoneCheckSerializedValueTypeGeneric(value); - - if (value['type'] != typeStr) - { - throw new Error( - `Cannot deserialize type ${value['type']} into ${typeStr}`); - } -} - -function isString(val: any) :boolean -{ - return ((typeof val === 'string') || (val instanceof String)); -} - -function StoneCheckSerializedValueTypeGeneric(value: any) -{ - // console.//log("+-------------------------------------------------+"); - // console.//log("| StoneCheckSerializedValueTypeGeneric |"); - // console.//log("+-------------------------------------------------+"); - // console.//log("value = "); - // console.//log(value); - if ( (!('type' in value)) || (!isString(value.type)) ) - { - throw new Error( - "Cannot deserialize value ('type' key invalid)"); - } -} - -// end of generic methods - -export enum Tool { - LineMeasure = "LineMeasure", - CircleMeasure = "CircleMeasure", - Crop = "Crop", - Windowing = "Windowing", - Zoom = "Zoom", - Pan = "Pan", - Move = "Move", - Rotate = "Rotate", - Resize = "Resize", - Mask = "Mask" -}; - -export function Tool_FromString(strValue:string) : Tool -{ - if( strValue == "LineMeasure" ) - { - return Tool.LineMeasure; - } - if( strValue == "CircleMeasure" ) - { - return Tool.CircleMeasure; - } - if( strValue == "Crop" ) - { - return Tool.Crop; - } - if( strValue == "Windowing" ) - { - return Tool.Windowing; - } - if( strValue == "Zoom" ) - { - return Tool.Zoom; - } - if( strValue == "Pan" ) - { - return Tool.Pan; - } - if( strValue == "Move" ) - { - return Tool.Move; - } - if( strValue == "Rotate" ) - { - return Tool.Rotate; - } - if( strValue == "Resize" ) - { - return Tool.Resize; - } - if( strValue == "Mask" ) - { - return Tool.Mask; - } - - let msg : string = `String ${strValue} cannot be converted to Tool. Possible values are: LineMeasure, CircleMeasure, Crop, Windowing, Zoom, Pan, Move, Rotate, Resize, Mask`; - throw new Error(msg); -} - -export function Tool_ToString(value:Tool) : string -{ - if( value == Tool.LineMeasure ) - { - return "LineMeasure"; - } - if( value == Tool.CircleMeasure ) - { - return "CircleMeasure"; - } - if( value == Tool.Crop ) - { - return "Crop"; - } - if( value == Tool.Windowing ) - { - return "Windowing"; - } - if( value == Tool.Zoom ) - { - return "Zoom"; - } - if( value == Tool.Pan ) - { - return "Pan"; - } - if( value == Tool.Move ) - { - return "Move"; - } - if( value == Tool.Rotate ) - { - return "Rotate"; - } - if( value == Tool.Resize ) - { - return "Resize"; - } - if( value == Tool.Mask ) - { - return "Mask"; - } - - let msg : string = `Value ${value} cannot be converted to Tool. Possible values are: `; - { - let _LineMeasure_enumValue : string = Tool.LineMeasure; // enums are strings in stonecodegen, so this will work. - let msg_LineMeasure : string = `LineMeasure (${_LineMeasure_enumValue}), `; - msg = msg + msg_LineMeasure; - } - { - let _CircleMeasure_enumValue : string = Tool.CircleMeasure; // enums are strings in stonecodegen, so this will work. - let msg_CircleMeasure : string = `CircleMeasure (${_CircleMeasure_enumValue}), `; - msg = msg + msg_CircleMeasure; - } - { - let _Crop_enumValue : string = Tool.Crop; // enums are strings in stonecodegen, so this will work. - let msg_Crop : string = `Crop (${_Crop_enumValue}), `; - msg = msg + msg_Crop; - } - { - let _Windowing_enumValue : string = Tool.Windowing; // enums are strings in stonecodegen, so this will work. - let msg_Windowing : string = `Windowing (${_Windowing_enumValue}), `; - msg = msg + msg_Windowing; - } - { - let _Zoom_enumValue : string = Tool.Zoom; // enums are strings in stonecodegen, so this will work. - let msg_Zoom : string = `Zoom (${_Zoom_enumValue}), `; - msg = msg + msg_Zoom; - } - { - let _Pan_enumValue : string = Tool.Pan; // enums are strings in stonecodegen, so this will work. - let msg_Pan : string = `Pan (${_Pan_enumValue}), `; - msg = msg + msg_Pan; - } - { - let _Move_enumValue : string = Tool.Move; // enums are strings in stonecodegen, so this will work. - let msg_Move : string = `Move (${_Move_enumValue}), `; - msg = msg + msg_Move; - } - { - let _Rotate_enumValue : string = Tool.Rotate; // enums are strings in stonecodegen, so this will work. - let msg_Rotate : string = `Rotate (${_Rotate_enumValue}), `; - msg = msg + msg_Rotate; - } - { - let _Resize_enumValue : string = Tool.Resize; // enums are strings in stonecodegen, so this will work. - let msg_Resize : string = `Resize (${_Resize_enumValue}), `; - msg = msg + msg_Resize; - } - { - let _Mask_enumValue : string = Tool.Mask; // enums are strings in stonecodegen, so this will work. - let msg_Mask : string = `Mask (${_Mask_enumValue})`; - msg = msg + msg_Mask; - } - throw new Error(msg); -} - -export enum ActionType { - UndoCrop = "UndoCrop", - Rotate = "Rotate", - Invert = "Invert" -}; - -export function ActionType_FromString(strValue:string) : ActionType -{ - if( strValue == "UndoCrop" ) - { - return ActionType.UndoCrop; - } - if( strValue == "Rotate" ) - { - return ActionType.Rotate; - } - if( strValue == "Invert" ) - { - return ActionType.Invert; - } - - let msg : string = `String ${strValue} cannot be converted to ActionType. Possible values are: UndoCrop, Rotate, Invert`; - throw new Error(msg); -} - -export function ActionType_ToString(value:ActionType) : string -{ - if( value == ActionType.UndoCrop ) - { - return "UndoCrop"; - } - if( value == ActionType.Rotate ) - { - return "Rotate"; - } - if( value == ActionType.Invert ) - { - return "Invert"; - } - - let msg : string = `Value ${value} cannot be converted to ActionType. Possible values are: `; - { - let _UndoCrop_enumValue : string = ActionType.UndoCrop; // enums are strings in stonecodegen, so this will work. - let msg_UndoCrop : string = `UndoCrop (${_UndoCrop_enumValue}), `; - msg = msg + msg_UndoCrop; - } - { - let _Rotate_enumValue : string = ActionType.Rotate; // enums are strings in stonecodegen, so this will work. - let msg_Rotate : string = `Rotate (${_Rotate_enumValue}), `; - msg = msg + msg_Rotate; - } - { - let _Invert_enumValue : string = ActionType.Invert; // enums are strings in stonecodegen, so this will work. - let msg_Invert : string = `Invert (${_Invert_enumValue})`; - msg = msg + msg_Invert; - } - throw new Error(msg); -} - - - -export class SelectTool { - tool:Tool; - - constructor() { - } - - public StoneSerialize(): string { - let container: object = {}; - container['type'] = 'StoneSampleCommands.SelectTool'; - container['value'] = this; - return JSON.stringify(container); - } - - public static StoneDeserialize(valueStr: string) : SelectTool - { - let value: any = JSON.parse(valueStr); - StoneCheckSerializedValueType(value, 'StoneSampleCommands.SelectTool'); - let result: SelectTool = value['value'] as SelectTool; - return result; - } -} -export class Action { - type:ActionType; - - constructor() { - } - - public StoneSerialize(): string { - let container: object = {}; - container['type'] = 'StoneSampleCommands.Action'; - container['value'] = this; - return JSON.stringify(container); - } - - public static StoneDeserialize(valueStr: string) : Action - { - let value: any = JSON.parse(valueStr); - StoneCheckSerializedValueType(value, 'StoneSampleCommands.Action'); - let result: Action = value['value'] as Action; - return result; - } -} - -export interface IHandler { -}; - -/** Service function for StoneDispatchToHandler */ -export function StoneDispatchJsonToHandler( - jsonValue: any, handler: IHandler): boolean -{ - StoneCheckSerializedValueTypeGeneric(jsonValue); - let type: string = jsonValue["type"]; - if (type == "") - { - // this should never ever happen - throw new Error("Caught empty type while dispatching"); - } - else - { - return false; - } -} - -/** Takes a serialized type and passes this to the handler */ -export function StoneDispatchToHandler( - strValue: string, handler: IHandler): boolean -{ - // console.//log("+------------------------------------------------+"); - // console.//log("| StoneDispatchToHandler |"); - // console.//log("+------------------------------------------------+"); - // console.//log("strValue = "); - // console.//log(strValue); - let jsonValue: any = JSON.parse(strValue) - return StoneDispatchJsonToHandler(jsonValue, handler); -} \ No newline at end of file
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/SynchronizedSeriesApplication.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,109 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "SampleInteractor.h" - -#include "../../../Framework/Toolbox/OrthancSeriesLoader.h" -#include "../../../Framework/Layers/SeriesFrameRendererFactory.h" -#include "../../../Framework/Layers/ReferenceLineFactory.h" -#include "../../../Framework/Widgets/LayoutWidget.h" - -#include <Core/Logging.h> - -namespace OrthancStone -{ - namespace Samples - { - class SynchronizedSeriesApplication : public SampleApplicationBase - { - private: - LayeredSceneWidget* CreateSeriesWidget(BasicApplicationContext& context, - const std::string& series) - { - std::unique_ptr<ISeriesLoader> loader - (new OrthancSeriesLoader(context.GetWebService().GetConnection(), series)); - - std::unique_ptr<SampleInteractor> interactor(new SampleInteractor(*loader, false)); - - std::unique_ptr<LayeredSceneWidget> widget(new LayeredSceneWidget); - widget->AddLayer(new SeriesFrameRendererFactory(loader.release(), false)); - widget->SetSlice(interactor->GetCursor().GetCurrentSlice()); - widget->SetInteractor(*interactor); - - context.AddInteractor(interactor.release()); - - return widget.release(); - } - - public: - virtual void DeclareCommandLineOptions(boost::program_options::options_description& options) - { - boost::program_options::options_description generic("Sample options"); - generic.add_options() - ("a", boost::program_options::value<std::string>(), - "Orthanc ID of the 1st series") - ("b", boost::program_options::value<std::string>(), - "Orthanc ID of the 2nd series") - ("c", boost::program_options::value<std::string>(), - "Orthanc ID of the 3rd series") - ; - - options.add(generic); - } - - virtual void Initialize(BasicApplicationContext& context, - IStatusBar& statusBar, - const boost::program_options::variables_map& parameters) - { - if (parameters.count("a") != 1 || - parameters.count("b") != 1 || - parameters.count("c") != 1) - { - LOG(ERROR) << "At least one of the three series IDs is missing"; - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - std::unique_ptr<LayeredSceneWidget> a(CreateSeriesWidget(context, parameters["a"].as<std::string>())); - std::unique_ptr<LayeredSceneWidget> b(CreateSeriesWidget(context, parameters["b"].as<std::string>())); - std::unique_ptr<LayeredSceneWidget> c(CreateSeriesWidget(context, parameters["c"].as<std::string>())); - - ReferenceLineFactory::Configure(*a, *b); - ReferenceLineFactory::Configure(*a, *c); - ReferenceLineFactory::Configure(*b, *c); - - std::unique_ptr<LayoutWidget> layout(new LayoutWidget); - layout->SetPadding(5); - layout->AddWidget(a.release()); - - std::unique_ptr<LayoutWidget> layoutB(new LayoutWidget); - layoutB->SetVertical(); - layoutB->SetPadding(5); - layoutB->AddWidget(b.release()); - layoutB->AddWidget(c.release()); - layout->AddWidget(layoutB.release()); - - context.SetCentralWidget(layout.release()); - } - }; - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/TestPatternApplication.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "SampleApplicationBase.h" - -#include "../../../Framework/Widgets/TestCairoWidget.h" -#include "../../../Framework/Widgets/TestWorldSceneWidget.h" -#include "../../../Framework/Widgets/LayoutWidget.h" - -namespace OrthancStone -{ - namespace Samples - { - class TestPatternApplication : public SampleApplicationBase - { - public: - virtual void DeclareStartupOptions(boost::program_options::options_description& options) - { - boost::program_options::options_description generic("Sample options"); - generic.add_options() - ("animate", boost::program_options::value<bool>()->default_value(true), "Animate the test pattern") - ; - - options.add(generic); - } - - virtual void Initialize(IStatusBar& statusBar, - const boost::program_options::variables_map& parameters) - { - using namespace OrthancStone; - - std::unique_ptr<LayoutWidget> layout(new LayoutWidget); - layout->SetPadding(10); - layout->SetBackgroundCleared(true); - layout->AddWidget(new TestCairoWidget(parameters["animate"].as<bool>())); - layout->AddWidget(new TestWorldSceneWidget(parameters["animate"].as<bool>())); - - context_->SetCentralWidget(layout.release()); - context_->SetUpdateDelay(25); // If animation, update the content each 25ms - } - }; - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/index.html Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -<!doctype html> - -<html lang="us"> - <head> - <meta charset="utf-8" /> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> - - <!-- Disable pinch zoom on mobile devices --> - <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> - <meta name="HandheldFriendly" content="true" /> - - <title>Wasm Samples</title> - -<body> - <ul> - <li><a href="simple-viewer/simple-viewer.html">Simple Viewer Project (you may add ?studyId=XXX in the url)</a></li> - <li><a href="single-frame.html?instance=XXX">Single frame application (you must replace XXX by a valid instance id in the url)</a></li> - <li><a href="single-frame-editor.html?instance=XXX">Single frame editor application (you must replace XXX by a valid instance id in the url)</a></li> - <li><a href="simple-viewer-single-file.html">Simple Viewer Single file (to be replaced by other samples)</a></li> - </ul> -</body> - -</html> \ No newline at end of file
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/samples-styles.css Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -html, body { - width: 100%; - height: 100%; - margin: 0px; - border: 0; - overflow: hidden; /* Disable scrollbars */ - display: block; /* No floating content on sides */ - background-color: black; - color: white; - font-family: Arial, Helvetica, sans-serif; -} - -canvas { - left:0px; - top:0px; -} \ No newline at end of file
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/simple-viewer-single-file.html Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -<!doctype html> - -<html lang="us"> - -<head> - <meta charset="utf-8" /> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> - - <!-- Disable pinch zoom on mobile devices --> - <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> - <meta name="HandheldFriendly" content="true" /> - - <title>Simple Viewer</title> - <link href="samples-styles.css" rel="stylesheet" /> - -<body> - <div id="breadcrumb"> - <span id="patient-id"></span> - <span id="study-description"></span> - <span id="series-description"></span> - </div> - <div style="height: calc(100% - 50px)"> - <div style="width: 20%; height: 100%; display: inline-block"> - <canvas id="canvas"></canvas> - </div> - <div style="width: 70%; height: 100%; display: inline-block"> - <canvas id="canvas2"></canvas> - </div> - </div> - <div id="toolbox" style="height: 50px"> - <input tool-selector="line-measure" type="radio" name="radio-tool-selector" class="tool-selector">line - <input tool-selector="circle-measure" type="radio" name="radio-tool-selector" class="tool-selector">circle - <button action-trigger="action1" class="action-trigger">action1</button> - <button action-trigger="action2" class="action-trigger">action2</button> - </div> - <script type="text/javascript" src="app-simple-viewer-single-file.js"></script> -</body> - -</html> \ No newline at end of file
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/simple-viewer-single-file.ts Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -import wasmApplicationRunner = require('../../../Platforms/Wasm/wasm-application-runner'); - -wasmApplicationRunner.InitializeWasmApplication("OrthancStoneSimpleViewerSingleFile", "/orthanc"); - -function SelectTool(toolName: string) { - var command = { - command: "selectTool", - args: { - toolName: toolName - } - }; - wasmApplicationRunner.SendSerializedMessageToStoneApplication(JSON.stringify(command)); - -} - -function PerformAction(commandName: string) { - var command = { - command: commandName, - commandType: "simple", - args: {} - }; - wasmApplicationRunner.SendSerializedMessageToStoneApplication(JSON.stringify(command)); -} - -//initializes the buttons -//----------------------- -// install "SelectTool" handlers -document.querySelectorAll("[tool-selector]").forEach((e) => { - console.log(e); - (e as HTMLInputElement).addEventListener("click", () => { - console.log(e); - SelectTool(e.attributes["tool-selector"].value); - }); -}); - -// install "PerformAction" handlers -document.querySelectorAll("[action-trigger]").forEach((e) => { - (e as HTMLInputElement).addEventListener("click", () => { - PerformAction(e.attributes["action-trigger"].value); - }); -}); - -// this method is called "from the C++ code" when the StoneApplication is updated. -// it can be used to update the UI of the application -function UpdateWebApplicationWithString(statusUpdateMessage: string) { - console.log(statusUpdateMessage); - - if (statusUpdateMessage.startsWith("series-description=")) { - document.getElementById("series-description").innerText = statusUpdateMessage.split("=")[1]; - } -} - -function UpdateWebApplicationWithSerializedMessage(statusUpdateMessageString: string) { - console.log("updating web application with serialized message: ", statusUpdateMessageString); - console.log("<not supported in the simple viewer (single file)!>"); -} - -// make it available to other js scripts in the application -(<any> window).UpdateWebApplicationWithString = UpdateWebApplicationWithString; - -(<any> window).UpdateWebApplicationWithSerializedMessage = UpdateWebApplicationWithSerializedMessage;
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/simple-viewer-single-file.tsconfig.json Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -{ - "extends" : "./tsconfig-samples", - "compilerOptions": { - // "outFile": "../build-web/app-simple-viewer-single-file.js" - }, - "include" : [ - "simple-viewer-single-file.ts" - ] -} \ No newline at end of file
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/single-frame-editor.html Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -<!doctype html> - -<html lang="us"> - <head> - <meta charset="utf-8" /> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> - - <!-- Disable pinch zoom on mobile devices --> - <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> - <meta name="HandheldFriendly" content="true" /> - - <title>Simple Viewer</title> - <link href="samples-styles.css" rel="stylesheet" /> - -<body> - <div style="width: 100%; height: 100%"> - <canvas id="canvas"></canvas> - </div> - <script type="text/javascript" src="app-single-frame-editor.js"></script> -</body> - -</html> \ No newline at end of file
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/single-frame-editor.ts Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -import wasmApplicationRunner = require('../../../Platforms/Wasm/wasm-application-runner'); - -wasmApplicationRunner.InitializeWasmApplication("OrthancStoneSingleFrameEditor", "/orthanc");
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/single-frame-editor.tsconfig.json Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -{ - "extends" : "./tsconfig-samples", - "compilerOptions": { - }, - "include" : [ - "single-frame-editor.ts" - ] -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/single-frame.html Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -<!doctype html> - -<html lang="us"> - <head> - <meta charset="utf-8" /> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> - - <!-- Disable pinch zoom on mobile devices --> - <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> - <meta name="HandheldFriendly" content="true" /> - - <title>Simple Viewer</title> - <link href="samples-styles.css" rel="stylesheet" /> - -<body> - <div style="width: 100%; height: 100%"> - <canvas id="canvas"></canvas> - </div> - <script type="text/javascript" src="app-single-frame.js"></script> -</body> - -</html> \ No newline at end of file
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/single-frame.ts Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -import wasmApplicationRunner = require('../../../Platforms/Wasm/wasm-application-runner'); - -wasmApplicationRunner.InitializeWasmApplication("OrthancStoneSingleFrame", "/orthanc"); -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/single-frame.tsconfig.json Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -{ - "extends" : "./tsconfig-samples", - "compilerOptions": { - }, - "include" : [ - "single-frame.ts" - ] -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/Web/tsconfig-samples.json Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -{ - "extends" : "../../../Platforms/Wasm/tsconfig-stone", - "compilerOptions": { - "sourceMap": false, - "lib" : [ - "es2017", - "dom", - "dom.iterable" - ] - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/build-wasm.sh Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -#!/bin/bash -# -# usage: -# to build all targets in Debug: -# ./build-wasm.sh -# -# to build a single target in release: -# ./build-wasm.sh OrthancStoneSingleFrameEditor Release - -set -e - -target=${1:-all} -buildType=${2:-Debug} - -currentDir=$(pwd) -samplesRootDir=$(pwd) - -mkdir -p $samplesRootDir/build-wasm -cd $samplesRootDir/build-wasm - -source ~/apps/emsdk/emsdk_env.sh -cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=~/apps/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake -DCMAKE_BUILD_TYPE=$buildType -DSTONE_SOURCES_DIR=$currentDir/../../../orthanc-stone -DORTHANC_FRAMEWORK_SOURCE=path -DORTHANC_FRAMEWORK_ROOT=$currentDir/../../../orthanc -DALLOW_DOWNLOADS=ON .. -DENABLE_WASM=ON -ninja $target - -echo "-- building the web application -- " -cd $currentDir -./build-web.sh \ No newline at end of file
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/build-wasm.sh.old Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -#!/bin/bash -# -# usage: -# to build all targets: -# ./build-wasm.sh -# -# to build a single target: -# ./build-wasm.sh OrthancStoneSingleFrameEditor - -set -e - -target=${1:-all} - -currentDir=$(pwd) -samplesRootDir=$(pwd) - -mkdir -p $samplesRootDir/build-wasm -cd $samplesRootDir/build-wasm - -source ~/apps/emsdk/emsdk_env.sh -cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=${EMSCRIPTEN}/cmake/Modules/Platform/Emscripten.cmake \ - -DCMAKE_BUILD_TYPE=Release \ - -DSTONE_SOURCES_DIR=$currentDir/../../../orthanc-stone \ - -DORTHANC_FRAMEWORK_SOURCE=path \ - -DORTHANC_FRAMEWORK_ROOT=$currentDir/../../../orthanc \ - -DALLOW_DOWNLOADS=ON .. \ - -DENABLE_WASM=ON - -ninja $target - -echo "-- building the web application -- " -cd $currentDir -./build-web.sh
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/build-web-ext.sh Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -#!/bin/bash - -set -e - -target=${1:-all} -# this script currently assumes that the wasm code has been built on its side and is availabie in build-wasm/ - -currentDir=$(pwd) - -scriptDirRel=$(dirname $0) -#echo $scriptDirRel -scriptDirAbs=$(realpath $scriptDirRel) -echo $scriptDirAbs - -samplesRootDir=scriptDirAbs - -outputDir=$samplesRootDir/build-web/ -mkdir -p $outputDir - -# files used by all single files samples -cp $samplesRootDir/Web/index.html $outputDir -cp $samplesRootDir/Web/samples-styles.css $outputDir - -# build simple-viewer-single-file (obsolete project) -if [[ $target == "all" || $target == "OrthancStoneSimpleViewerSingleFile" ]]; then - cp $samplesRootDir/Web/simple-viewer-single-file.html $outputDir - tsc --allowJs --project $samplesRootDir/Web/simple-viewer-single-file.tsconfig.json - cp $currentDir/build-wasm/OrthancStoneSimpleViewerSingleFile.js $outputDir - cp $currentDir/build-wasm/OrthancStoneSimpleViewerSingleFile.wasm $outputDir -fi - -# build single-frame -if [[ $target == "all" || $target == "OrthancStoneSingleFrame" ]]; then - cp $samplesRootDir/Web/single-frame.html $outputDir - tsc --allowJs --project $samplesRootDir/Web/single-frame.tsconfig.json - cp $currentDir/build-wasm/OrthancStoneSingleFrame.js $outputDir - cp $currentDir/build-wasm/OrthancStoneSingleFrame.wasm $outputDir -fi - -# build single-frame-editor -if [[ $target == "all" || $target == "OrthancStoneSingleFrameEditor" ]]; then - cp $samplesRootDir/Web/single-frame-editor.html $outputDir - tsc --allowJs --project $samplesRootDir/Web/single-frame-editor.tsconfig.json - cp $currentDir/build-wasm/OrthancStoneSingleFrameEditor.js $outputDir - cp $currentDir/build-wasm/OrthancStoneSingleFrameEditor.wasm $outputDir -fi - -# build simple-viewer project -if [[ $target == "all" || $target == "OrthancStoneSimpleViewer" ]]; then - mkdir -p $outputDir/simple-viewer/ - cp $samplesRootDir/SimpleViewer/Wasm/simple-viewer.html $outputDir/simple-viewer/ - cp $samplesRootDir/SimpleViewer/Wasm/styles.css $outputDir/simple-viewer/ - tsc --allowJs --project $samplesRootDir/SimpleViewer/Wasm/tsconfig-simple-viewer.json - cp $currentDir/build-wasm/OrthancStoneSimpleViewer.js $outputDir/simple-viewer/ - cp $currentDir/build-wasm/OrthancStoneSimpleViewer.wasm $outputDir/simple-viewer/ -fi - -cd $currentDir
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/build-web.sh Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -#!/bin/bash - -set -e - -target=${1:-all} -# this script currently assumes that the wasm code has been built on its side and is availabie in build-wasm/ - -currentDir=$(pwd) -samplesRootDir=$(pwd) - -echo "*************************************************************************" -echo "samplesRootDir = $samplesRootDir" -echo "*************************************************************************" - -outputDir=$samplesRootDir/build-web/ -mkdir -p "$outputDir" - -# files used by all single files samples -cp "$samplesRootDir/Web/index.html" "$outputDir" -cp "$samplesRootDir/Web/samples-styles.css" "$outputDir" - -# # build simple-viewer-single-file (obsolete project) -# if [[ $target == "all" || $target == "OrthancStoneSimpleViewerSingleFile" ]]; then -# cp $samplesRootDir/Web/simple-viewer-single-file.html $outputDir -# tsc --project $samplesRootDir/Web/simple-viewer-single-file.tsconfig.json --outDir "$outputDir" -# browserify \ -# "$outputDir/Platforms/Wasm/wasm-application-runner.js" \ -# "$outputDir/Applications/Samples/Web/simple-viewer-single-file.js" \ -# -o "$outputDir/app-simple-viewer-single-file.js" -# cp "$currentDir/build-wasm/OrthancStoneSimpleViewerSingleFile.js" $outputDir -# cp "$currentDir/build-wasm/OrthancStoneSimpleViewerSingleFile.wasm" $outputDir -# fi - -# # build single-frame -# if [[ $target == "all" || $target == "OrthancStoneSingleFrame" ]]; then -# cp $samplesRootDir/Web/single-frame.html $outputDir -# tsc --project $samplesRootDir/Web/single-frame.tsconfig.json --outDir "$outputDir" -# browserify \ -# "$outputDir/Platforms/Wasm/wasm-application-runner.js" \ -# "$outputDir/Applications/Samples/Web/single-frame.js" \ -# -o "$outputDir/app-single-frame.js" -# cp "$currentDir/build-wasm/OrthancStoneSingleFrame.js" $outputDir -# cp "$currentDir/build-wasm/OrthancStoneSingleFrame.wasm" $outputDir -# fi - -# build single-frame-editor -if [[ $target == "all" || $target == "OrthancStoneSingleFrameEditor" ]]; then - cp $samplesRootDir/Web/single-frame-editor.html $outputDir - tsc --project $samplesRootDir/Web/single-frame-editor.tsconfig.json --outDir "$outputDir" - browserify \ - "$outputDir/Platforms/Wasm/wasm-application-runner.js" \ - "$outputDir/Applications/Samples/Web/single-frame-editor.js" \ - -o "$outputDir/app-single-frame-editor.js" - cp "$currentDir/build-wasm/OrthancStoneSingleFrameEditor.js" $outputDir - cp "$currentDir/build-wasm/OrthancStoneSingleFrameEditor.wasm" $outputDir -fi - -# build simple-viewer project -if [[ $target == "all" || $target == "OrthancStoneSimpleViewer" ]]; then - mkdir -p $outputDir/simple-viewer/ - cp $samplesRootDir/SimpleViewer/Wasm/simple-viewer.html $outputDir/simple-viewer/ - cp $samplesRootDir/SimpleViewer/Wasm/styles.css $outputDir/simple-viewer/ - - # the root dir must contain all the source files for the whole project - tsc --module commonjs --allowJs --project "$samplesRootDir/SimpleViewer/Wasm/tsconfig-simple-viewer.json" --rootDir "$samplesRootDir/../.." --outDir "$outputDir/simple-viewer/" - browserify \ - "$outputDir/simple-viewer/Platforms/Wasm/wasm-application-runner.js" \ - "$outputDir/simple-viewer/Applications/Samples/SimpleViewer/Wasm/simple-viewer.js" \ - -o "$outputDir/simple-viewer/app-simple-viewer.js" - cp "$currentDir/build-wasm/OrthancStoneSimpleViewer.js" "$outputDir/simple-viewer/" - cp "$currentDir/build-wasm/OrthancStoneSimpleViewer.wasm" "$outputDir/simple-viewer/" -fi - -cd $currentDir
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/get-requirements-windows.ps1 Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ - -if ($true) { - - Write-Error "This script is obsolete. Please work under WSL and run build-wasm.sh" - -} else { - - param( - [IO.DirectoryInfo] $EmsdkRootDir = "C:\Emscripten", - [bool] $Overwrite = $false - ) - - if (Test-Path -Path $EmsdkRootDir) { - if( $Override) { - Remove-Item -Path $EmsdkRootDir -Force -Recurse - } else { - throw "The `"$EmsdkRootDir`" folder may not exist! Use the Overwrite flag to bypass this check." - } - } - - # TODO: detect whether git is installed - # choco install -y git - - Write-Host "Will retrieve the Emscripten SDK to the `"$EmsdkRootDir`" folder" - - $EmsdkParentDir = split-path -Parent $EmsdkRootDir - $EmsdkRootName = split-path -Leaf $EmsdkRootDir - - Push-Location $EmsdkParentDir - - git clone https://github.com/juj/emsdk.git $EmsdkRootName - cd $EmsdkRootName - - git pull - - ./emsdk install latest - - ./emsdk activate latest - - echo "INFO: the ~/.emscripten file has been configured for this installation of Emscripten." - - Write-Host "emsdk is now installed in $EmsdkRootDir" - - Pop-Location - -} - - - -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/nginx.local.conf Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -# Local config to serve the WASM samples static files and reverse proxy Orthanc. -# Uses port 9977 instead of 80. - -# `events` section is mandatory -events { - worker_connections 1024; # Default: 1024 -} - -http { - - # prevent nginx sync issues on OSX - proxy_buffering off; - - server { - listen 9977 default_server; - client_max_body_size 4G; - - # location may have to be adjusted depending on your OS and nginx install - include /etc/nginx/mime.types; - # if not in your system mime.types, add this line to support WASM: - # types { - # application/wasm wasm; - # } - - # serve WASM static files - root build-web/; - location / { - } - - # reverse proxy orthanc - location /orthanc/ { - rewrite /orthanc(.*) $1 break; - proxy_pass http://127.0.0.1:8042; - proxy_set_header Host $http_host; - proxy_set_header my-auth-header good-token; - proxy_request_buffering off; - proxy_max_temp_file_size 0; - client_max_body_size 0; - } - - - } - -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/package-lock.json Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -{ - "requires": true, - "lockfileVersion": 1, - "dependencies": { - "typescript": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.2.tgz", - "integrity": "sha512-VCj5UiSyHBjwfYacmDuc/NOk4QQixbE+Wn7MFJuS0nRuPQbof132Pw4u53dm264O8LPc2MVsc7RJNml5szurkg==" - } - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/CMakeLists.txt Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,142 +0,0 @@ -cmake_minimum_required(VERSION 2.8.3) -project(RtViewerDemo) - -if(MSVC) - add_definitions(/MP) - if (CMAKE_BUILD_TYPE MATCHES DEBUG) - add_definitions(/JMC) - endif() -endif() - -message("-------------------------------------------------------------------------------------------------------------------") -message("ORTHANC_FRAMEWORK_ROOT is set to ${ORTHANC_FRAMEWORK_ROOT}") -message("-------------------------------------------------------------------------------------------------------------------") - -if(NOT DEFINED ORTHANC_FRAMEWORK_ROOT) - message(FATAL_ERROR "The location of the Orthanc source repository must be set in the ORTHANC_FRAMEWORK_ROOT CMake variable") -endif() - -message("-------------------------------------------------------------------------------------------------------------------") -message("STONE_SOURCES_DIR is set to ${STONE_SOURCES_DIR}") -message("-------------------------------------------------------------------------------------------------------------------") - -if(NOT DEFINED STONE_SOURCES_DIR) - message(FATAL_ERROR "The location of the Stone of Orthanc source repository must be set in the STONE_SOURCES_DIR CMake variable") -endif() - -include(${STONE_SOURCES_DIR}/Resources/CMake/OrthancStoneParameters.cmake) - -if (OPENSSL_NO_CAPIENG) -add_definitions(-DOPENSSL_NO_CAPIENG=1) -endif() - -set(ENABLE_SDL OFF CACHE BOOL "Target SDL Native application") -set(ENABLE_QT OFF CACHE BOOL "Target Qt Native application") -set(ENABLE_WASM OFF CACHE BOOL "Target WASM application") - -if (ENABLE_WASM) - ##################################################################### - ## Configuration of the Emscripten compiler for WebAssembly target - ##################################################################### - - set(WASM_FLAGS "-s WASM=1") - set(WASM_FLAGS "${WASM_FLAGS} -s STRICT=1") # drops support for all deprecated build options - set(WASM_FLAGS "${WASM_FLAGS} -s FILESYSTEM=1") # if we don't include it, gen_uuid.c fails to build because srand, getpid(), ... are not defined - set(WASM_FLAGS "${WASM_FLAGS} -s DISABLE_EXCEPTION_CATCHING=0") # actually enable exception catching - set(WASM_FLAGS "${WASM_FLAGS} -s ERROR_ON_MISSING_LIBRARIES=1") - - if (CMAKE_BUILD_TYPE MATCHES DEBUG) - set(WASM_FLAGS "${WASM_FLAGS} -g4") # generate debug information - set(WASM_FLAGS "${WASM_FLAGS} -s ASSERTIONS=2") # more runtime checks - else() - set(WASM_FLAGS "${WASM_FLAGS} -Os") # optimize for web (speed and size) - endif() - - set(WASM_MODULE_NAME "StoneFrameworkModule" CACHE STRING "Name of the WebAssembly module") - - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WASM_FLAGS}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WASM_FLAGS}") - - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${WASM_FLAGS}") # not always clear which flags are for the compiler and which one are for the linker -> pass them all to the linker too - # set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --js-library ${STONE_SOURCES_DIR}/Applications/Samples/samples-library.js") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --js-library ${STONE_SOURCES_DIR}/Platforms/Wasm/WasmWebService.js") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --js-library ${STONE_SOURCES_DIR}/Platforms/Wasm/WasmDelayedCallExecutor.js") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --js-library ${STONE_SOURCES_DIR}/Platforms/Wasm/default-library.js") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"ccall\", \"cwrap\"]'") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s EXPORT_NAME='\"${WASM_MODULE_NAME}\"'") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s ALLOW_MEMORY_GROWTH=1") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s TOTAL_MEMORY=536870912") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s TOTAL_STACK=128000000") - - add_definitions(-DORTHANC_ENABLE_WASM=1) - set(ORTHANC_SANDBOXED ON) - -elseif (ENABLE_QT OR ENABLE_SDL) - - set(ENABLE_NATIVE ON) - set(ORTHANC_SANDBOXED OFF) - set(ENABLE_CRYPTO_OPTIONS ON) - set(ENABLE_GOOGLE_TEST ON) - set(ENABLE_WEB_CLIENT ON) - -endif() - - -##################################################################### -## Configuration for Orthanc -##################################################################### - -if (ORTHANC_STONE_VERSION STREQUAL "mainline") - set(ORTHANC_FRAMEWORK_VERSION "mainline") - set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "hg") -else() - set(ORTHANC_FRAMEWORK_VERSION "1.4.1") - set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "web") -endif() - -set(ORTHANC_FRAMEWORK_SOURCE "${ORTHANC_FRAMEWORK_DEFAULT_SOURCE}" CACHE STRING "Source of the Orthanc source code (can be \"hg\", \"archive\", \"web\" or \"path\")") -set(ORTHANC_FRAMEWORK_ARCHIVE "" CACHE STRING "Path to the Orthanc archive, if ORTHANC_FRAMEWORK_SOURCE is \"archive\"") -set(ORTHANC_FRAMEWORK_ROOT "" CACHE STRING "Path to the Orthanc source directory, if ORTHANC_FRAMEWORK_SOURCE is \"path\"") - -add_definitions( - -DORTHANC_ENABLE_LOGGING_PLUGIN=0 - ) - - -##################################################################### -## Build a static library containing the Orthanc Stone framework -##################################################################### - -LIST(APPEND ORTHANC_BOOST_COMPONENTS program_options) - -include(${STONE_SOURCES_DIR}/Resources/CMake/OrthancStoneConfiguration.cmake) - -add_library(OrthancStone STATIC - ${ORTHANC_STONE_SOURCES} - ) - -##################################################################### -## Build all the sample applications -##################################################################### - -include_directories(${ORTHANC_STONE_ROOT}) - -list(APPEND RTVIEWERDEMO_APPLICATION_SOURCES - ${ORTHANC_STONE_ROOT}/Applications/Samples/SampleInteractor.h - ${ORTHANC_STONE_ROOT}/Applications/Samples/SampleApplicationBase.h - ) - -if (ENABLE_WASM) - list(APPEND RTVIEWERDEMO_APPLICATION_SOURCES - ${STONE_WASM_SOURCES} - ) -endif() - -add_executable(RtViewerDemo - main.cpp - ${RTVIEWERDEMO_APPLICATION_SOURCES} -) -set_target_properties(RtViewerDemo PROPERTIES COMPILE_DEFINITIONS ORTHANC_STONE_SAMPLE=3) -target_include_directories(RtViewerDemo PRIVATE ${ORTHANC_STONE_ROOT}) -target_link_libraries(RtViewerDemo OrthancStone) -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/build-sdl-msvc15.ps1 Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -if (-not (Test-Path "build-sdl-msvc15")) { - mkdir -p "build-sdl-msvc15" -} - -cd build-sdl-msvc15 - -cmake -G "Visual Studio 15 2017 Win64" -DSTATIC_BUILD=ON -DOPENSSL_NO_CAPIENG=ON -DORTHANC_FRAMEWORK_SOURCE=path -DSTONE_SOURCES_DIR="$($pwd)\..\..\..\.." -DORTHANC_FRAMEWORK_ROOT="$($pwd)\..\..\..\..\..\orthanc" -DALLOW_DOWNLOADS=ON -DENABLE_SDL=ON .. - -if (!$?) { - Write-Error 'cmake configuration failed' -ErrorAction Stop -} - -cmake --build . --target RtViewerDemo --config Debug - -if (!$?) { - Write-Error 'cmake build failed' -ErrorAction Stop -} - -cd Debug - -.\RtViewerDemo.exe --ct-series=a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa --dose-instance=830a69ff-8e4b5ee3-b7f966c8-bccc20fb-d322dceb --struct-instance=54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9 - - -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/build-wasm.sh Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -#!/bin/bash -# -# usage: -# build-wasm BUILD_TYPE -# where BUILD_TYPE is Debug, RelWithDebInfo or Release - -set -e - -buildType=${1:-Debug} - -currentDir=$(pwd) -currentDirAbs=$(realpath $currentDir) - -mkdir -p build-wasm -cd build-wasm - -source ~/apps/emsdk/emsdk_env.sh -cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=${EMSCRIPTEN}/cmake/Modules/Platform/Emscripten.cmake \ --DCMAKE_BUILD_TYPE=$buildType -DSTONE_SOURCES_DIR=$currentDirAbs/../../../../orthanc-stone \ --DORTHANC_FRAMEWORK_SOURCE=path -DORTHANC_FRAMEWORK_ROOT=$currentDirAbs/../../../../orthanc \ --DALLOW_DOWNLOADS=ON .. -DENABLE_WASM=ON - -ninja $target - -echo "-- building the web application -- " -cd $currentDir -./build-web.sh - -echo "Launch start-serving-files.sh to access the web sample application locally"
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/build-web.sh Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -#!/bin/bash - -set -e - -target=${1:-all} -# this script currently assumes that the wasm code has been built on its side and is availabie in build-wasm/ - -currentDir=$(pwd) -samplesRootDir=$(pwd) - -tscOutput=$samplesRootDir/build-tsc-output/ -outputDir=$samplesRootDir/build-web/ -mkdir -p "$outputDir" - -# files used by all single files samples -cp "$samplesRootDir/index.html" "$outputDir" -cp "$samplesRootDir/samples-styles.css" "$outputDir" - -# build rt-viewer-demo -cp $samplesRootDir/rt-viewer-demo.html $outputDir -tsc --project $samplesRootDir/rt-viewer-demo.tsconfig.json --outDir "$tscOutput" -browserify \ - "$tscOutput/orthanc-stone/Platforms/Wasm/logger.js" \ - "$tscOutput/orthanc-stone/Platforms/Wasm/stone-framework-loader.js" \ - "$tscOutput/orthanc-stone/Platforms/Wasm/wasm-application-runner.js" \ - "$tscOutput/orthanc-stone/Platforms/Wasm/wasm-viewport.js" \ - "$tscOutput/rt-viewer-sample/rt-viewer-demo.js" \ - -o "$outputDir/app-rt-viewer-demo.js" -cp "$currentDir/build-wasm/RtViewerDemo.js" $outputDir -cp "$currentDir/build-wasm/RtViewerDemo.wasm" $outputDir - -cd $currentDir
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/index.html Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -<!doctype html> - -<html lang="us"> - <head> - <meta charset="utf-8" /> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> - - <!-- Disable pinch zoom on mobile devices --> - <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> - <meta name="HandheldFriendly" content="true" /> - - <title>Wasm Samples</title> - -<body> - <ul> - <li><a href="rt-viewer-demo.html?ct-series=a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa&dose-instance=830a69ff-8e4b5ee3-b7f966c8-bccc20fb-d322dceb&struct-instance=54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9">RTSTRUCT + CT + RTDOSE viewer demo. Pplease replace the url arguments with suitable IDs (you can find those in the Orthanc Explorer, for instance)</a></li> - </ul> -</body> - -</html>
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/main.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,893 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#include "Applications/IStoneApplication.h" -#include "Framework/Widgets/WorldSceneWidget.h" -#include "Framework/Widgets/LayoutWidget.h" - -#if ORTHANC_ENABLE_WASM==1 - #include "Platforms/Wasm/WasmPlatformApplicationAdapter.h" - #include "Platforms/Wasm/Defaults.h" - #include "Platforms/Wasm/WasmViewport.h" -#endif - -#if ORTHANC_ENABLE_QT==1 - #include "Qt/SampleMainWindow.h" - #include "Qt/SampleMainWindowWithButtons.h" -#endif - -#include "Framework/Layers/DicomSeriesVolumeSlicer.h" -#include "Framework/Widgets/SliceViewerWidget.h" -#include "Framework/Volumes/StructureSetLoader.h" - -#include <Core/Logging.h> -#include <Core/OrthancException.h> -#include <Core/Images/ImageTraits.h> - -#include <boost/math/constants/constants.hpp> -#include "Framework/dev.h" -#include "Framework/Widgets/LayoutWidget.h" -#include "Framework/Layers/DicomStructureSetSlicer.h" - -namespace OrthancStone -{ - namespace Samples - { - class RtViewerDemoBaseApplication : public IStoneApplication - { - protected: - // ownership is transferred to the application context -#ifndef RESTORE_NON_RTVIEWERDEMO_BEHAVIOR - LayoutWidget* mainWidget_; -#else - WorldSceneWidget* mainWidget_; -#endif - - public: - virtual void Initialize(StoneApplicationContext* context, - IStatusBar& statusBar, - const boost::program_options::variables_map& parameters) ORTHANC_OVERRIDE - { - } - - virtual std::string GetTitle() const ORTHANC_OVERRIDE - { - return "Stone of Orthanc - Sample"; - } - - /** - * In the basic samples, the commands are handled by the platform adapter and NOT - * by the application handler - */ - virtual void HandleSerializedMessage(const char* data) ORTHANC_OVERRIDE {}; - - - virtual void Finalize() ORTHANC_OVERRIDE {} - virtual IWidget* GetCentralWidget() ORTHANC_OVERRIDE {return mainWidget_;} - -#if ORTHANC_ENABLE_WASM==1 - // default implementations for a single canvas named "canvas" in the HTML and an empty WasmApplicationAdapter - - virtual void InitializeWasm() ORTHANC_OVERRIDE - { - AttachWidgetToWasmViewport("canvas", mainWidget_); - } - - virtual WasmPlatformApplicationAdapter* CreateWasmApplicationAdapter(MessageBroker& broker) - { - return new WasmPlatformApplicationAdapter(broker, *this); - } -#endif - - }; - - // this application actually works in Qt and WASM - class RtViewerDemoBaseSingleCanvasWithButtonsApplication : public RtViewerDemoBaseApplication - { -public: - virtual void OnPushButton1Clicked() {} - virtual void OnPushButton2Clicked() {} - virtual void OnTool1Clicked() {} - virtual void OnTool2Clicked() {} - - virtual void GetButtonNames(std::string& pushButton1, - std::string& pushButton2, - std::string& tool1, - std::string& tool2 - ) { - pushButton1 = "action1"; - pushButton2 = "action2"; - tool1 = "tool1"; - tool2 = "tool2"; - } - -#if ORTHANC_ENABLE_QT==1 - virtual QStoneMainWindow* CreateQtMainWindow() { - return new SampleMainWindowWithButtons(dynamic_cast<OrthancStone::NativeStoneApplicationContext&>(*context_), *this); - } -#endif - - }; - - // this application actually works in SDL and WASM - class RtViewerDemoBaseApplicationSingleCanvas : public RtViewerDemoBaseApplication - { -public: - -#if ORTHANC_ENABLE_QT==1 - virtual QStoneMainWindow* CreateQtMainWindow() { - return new SampleMainWindow(dynamic_cast<OrthancStone::NativeStoneApplicationContext&>(*context_), *this); - } -#endif - }; - } -} - - - -namespace OrthancStone -{ - namespace Samples - { - template <Orthanc::PixelFormat T> - void ReadDistributionInternal(std::vector<float>& distribution, - const Orthanc::ImageAccessor& image) - { - const unsigned int width = image.GetWidth(); - const unsigned int height = image.GetHeight(); - - distribution.resize(width * height); - size_t pos = 0; - - for (unsigned int y = 0; y < height; y++) - { - for (unsigned int x = 0; x < width; x++, pos++) - { - distribution[pos] = Orthanc::ImageTraits<T>::GetFloatPixel(image, x, y); - } - } - } - - void ReadDistribution(std::vector<float>& distribution, - const Orthanc::ImageAccessor& image) - { - switch (image.GetFormat()) - { - case Orthanc::PixelFormat_Grayscale8: - ReadDistributionInternal<Orthanc::PixelFormat_Grayscale8>(distribution, image); - break; - - case Orthanc::PixelFormat_Grayscale16: - ReadDistributionInternal<Orthanc::PixelFormat_Grayscale16>(distribution, image); - break; - - case Orthanc::PixelFormat_SignedGrayscale16: - ReadDistributionInternal<Orthanc::PixelFormat_SignedGrayscale16>(distribution, image); - break; - - case Orthanc::PixelFormat_Grayscale32: - ReadDistributionInternal<Orthanc::PixelFormat_Grayscale32>(distribution, image); - break; - - case Orthanc::PixelFormat_Grayscale64: - ReadDistributionInternal<Orthanc::PixelFormat_Grayscale64>(distribution, image); - break; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); - } - } - - - class DoseInteractor : public VolumeImageInteractor - { - private: - SliceViewerWidget& widget_; - size_t layer_; - DicomFrameConverter converter_; - - - - protected: - virtual void NotifySliceChange(const ISlicedVolume& slicedVolume, - const size_t& sliceIndex, - const Slice& slice) - { - converter_ = slice.GetConverter(); - - #if 0 - const OrthancVolumeImage& volume = dynamic_cast<const OrthancVolumeImage&>(slicedVolume); - - RenderStyle s = widget_.GetLayerStyle(layer_); - - if (volume.FitWindowingToRange(s, slice.GetConverter())) - { - printf("Windowing: %f => %f\n", s.customWindowCenter_, s.customWindowWidth_); - widget_.SetLayerStyle(layer_, s); - } - #endif - } - - virtual void NotifyVolumeReady(const ISlicedVolume& slicedVolume) - { - const float percentile = 0.01f; - const OrthancVolumeImage& volume = dynamic_cast<const OrthancVolumeImage&>(slicedVolume); - - std::vector<float> distribution; - ReadDistribution(distribution, volume.GetImage().GetInternalImage()); - std::sort(distribution.begin(), distribution.end()); - - int start = static_cast<int>(std::ceil(distribution.size() * percentile)); - int end = static_cast<int>(std::floor(distribution.size() * (1.0f - percentile))); - - float a = 0; - float b = 0; - - if (start < end && - start >= 0 && - end < static_cast<int>(distribution.size())) - { - a = distribution[start]; - b = distribution[end]; - } - else if (!distribution.empty()) - { - // Too small distribution: Use full range - a = distribution.front(); - b = distribution.back(); - } - - //printf("%f %f\n", a, b); - - RenderStyle s = widget_.GetLayerStyle(layer_); - s.windowing_ = ImageWindowing_Custom; - s.customWindowCenter_ = static_cast<float>(converter_.Apply((a + b) / 2.0f)); - s.customWindowWidth_ = static_cast<float>(converter_.Apply(b - a)); - - // 96.210556 => 192.421112 - widget_.SetLayerStyle(layer_, s); - printf("Windowing: %f => %f\n", s.customWindowCenter_, s.customWindowWidth_); - } - - public: - DoseInteractor(MessageBroker& broker, OrthancVolumeImage& volume, - SliceViewerWidget& widget, - VolumeProjection projection, - size_t layer) : - VolumeImageInteractor(broker, volume, widget, projection), - widget_(widget), - layer_(layer) - { - } - }; - - class RtViewerDemoApplication : - public RtViewerDemoBaseApplicationSingleCanvas, - public IObserver - { - public: - std::vector<std::pair<SliceViewerWidget*, size_t> > doseCtWidgetLayerPairs_; - std::list<OrthancStone::IWorldSceneInteractor*> interactors_; - - class Interactor : public IWorldSceneInteractor - { - private: - RtViewerDemoApplication& application_; - - public: - Interactor(RtViewerDemoApplication& application) : - application_(application) - { - } - - virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, - const ViewportGeometry& view, - MouseButton button, - KeyboardModifiers modifiers, - int viewportX, - int viewportY, - double x, - double y, - IStatusBar* statusBar, - const std::vector<Touch>& displayTouches) - { - return NULL; - } - - virtual void MouseOver(CairoContext& context, - WorldSceneWidget& widget, - const ViewportGeometry& view, - double x, - double y, - IStatusBar* statusBar) - { - if (statusBar != NULL) - { - Vector p = dynamic_cast<SliceViewerWidget&>(widget).GetSlice().MapSliceToWorldCoordinates(x, y); - - char buf[64]; - sprintf(buf, "X = %.02f Y = %.02f Z = %.02f (in cm)", - p[0] / 10.0, p[1] / 10.0, p[2] / 10.0); - statusBar->SetMessage(buf); - } - } - - virtual void MouseWheel(WorldSceneWidget& widget, - MouseWheelDirection direction, - KeyboardModifiers modifiers, - IStatusBar* statusBar) - { - int scale = (modifiers & KeyboardModifiers_Control ? 10 : 1); - - switch (direction) - { - case MouseWheelDirection_Up: - application_.OffsetSlice(-scale); - break; - - case MouseWheelDirection_Down: - application_.OffsetSlice(scale); - break; - - default: - break; - } - } - - virtual void KeyPressed(WorldSceneWidget& widget, - KeyboardKeys key, - char keyChar, - KeyboardModifiers modifiers, - IStatusBar* statusBar) - { - switch (keyChar) - { - case 's': - // TODO: recursively traverse children - widget.FitContent(); - break; - - default: - break; - } - } - }; - - void OffsetSlice(int offset) - { - if (source_ != NULL) - { - int slice = static_cast<int>(slice_) + offset; - - if (slice < 0) - { - slice = 0; - } - - if (slice >= static_cast<int>(source_->GetSliceCount())) - { - slice = static_cast<int>(source_->GetSliceCount()) - 1; - } - - if (slice != static_cast<int>(slice_)) - { - SetSlice(slice); - } - } - } - - - SliceViewerWidget& GetMainWidget() - { - return *dynamic_cast<SliceViewerWidget*>(mainWidget_); - } - - - void SetSlice(size_t index) - { - if (source_ != NULL && - index < source_->GetSliceCount()) - { - slice_ = static_cast<unsigned int>(index); - -#if 1 - GetMainWidget().SetSlice(source_->GetSlice(slice_).GetGeometry()); -#else - // TEST for scene extents - Rotate the axes - double a = 15.0 / 180.0 * boost::math::constants::pi<double>(); - -#if 1 - Vector x; GeometryToolbox::AssignVector(x, cos(a), sin(a), 0); - Vector y; GeometryToolbox::AssignVector(y, -sin(a), cos(a), 0); -#else - // Flip the normal - Vector x; GeometryToolbox::AssignVector(x, cos(a), sin(a), 0); - Vector y; GeometryToolbox::AssignVector(y, sin(a), -cos(a), 0); -#endif - - SliceGeometry s(source_->GetSlice(slice_).GetGeometry().GetOrigin(), x, y); - widget_->SetSlice(s); -#endif - } - } - - - void OnMainWidgetGeometryReady(const IVolumeSlicer::GeometryReadyMessage& message) - { - // Once the geometry of the series is downloaded from Orthanc, - // display its middle slice, and adapt the viewport to fit this - // slice - if (source_ == &message.GetOrigin()) - { - SetSlice(source_->GetSliceCount() / 2); - } - - GetMainWidget().FitContent(); - } - - DicomFrameConverter converter_; - - void OnSliceContentChangedMessage(const ISlicedVolume::SliceContentChangedMessage& message) - { - converter_ = message.GetSlice().GetConverter(); - } - - void OnVolumeReadyMessage(const ISlicedVolume::VolumeReadyMessage& message) - { - const float percentile = 0.01f; - - auto& slicedVolume = message.GetOrigin(); - const OrthancVolumeImage& volume = dynamic_cast<const OrthancVolumeImage&>(slicedVolume); - - std::vector<float> distribution; - ReadDistribution(distribution, volume.GetImage().GetInternalImage()); - std::sort(distribution.begin(), distribution.end()); - - int start = static_cast<int>(std::ceil(distribution.size() * percentile)); - int end = static_cast<int>(std::floor(distribution.size() * (1.0f - percentile))); - - float a = 0; - float b = 0; - - if (start < end && - start >= 0 && - end < static_cast<int>(distribution.size())) - { - a = distribution[start]; - b = distribution[end]; - } - else if (!distribution.empty()) - { - // Too small distribution: Use full range - a = distribution.front(); - b = distribution.back(); - } - - //printf("WINDOWING %f %f\n", a, b); - - for (const auto& pair : doseCtWidgetLayerPairs_) - { - auto widget = pair.first; - auto layer = pair.second; - RenderStyle s = widget->GetLayerStyle(layer); - s.windowing_ = ImageWindowing_Custom; - s.customWindowCenter_ = static_cast<float>(converter_.Apply((a + b) / 2.0f)); - s.customWindowWidth_ = static_cast<float>(converter_.Apply(b - a)); - - // 96.210556 => 192.421112 - widget->SetLayerStyle(layer, s); - printf("Windowing: %f => %f\n", s.customWindowCenter_, s.customWindowWidth_); - } - } - - - - size_t AddDoseLayer(SliceViewerWidget& widget, - OrthancVolumeImage& volume, VolumeProjection projection); - - void AddStructLayer( - SliceViewerWidget& widget, StructureSetLoader& loader); - - SliceViewerWidget* CreateDoseCtWidget( - std::unique_ptr<OrthancVolumeImage>& ct, - std::unique_ptr<OrthancVolumeImage>& dose, - std::unique_ptr<StructureSetLoader>& structLoader, - VolumeProjection projection); - - void AddCtLayer(SliceViewerWidget& widget, OrthancVolumeImage& volume); - - std::unique_ptr<Interactor> mainWidgetInteractor_; - const DicomSeriesVolumeSlicer* source_; - unsigned int slice_; - - std::string ctSeries_; - std::string doseInstance_; - std::string doseSeries_; - std::string structInstance_; - std::unique_ptr<OrthancStone::OrthancVolumeImage> dose_; - std::unique_ptr<OrthancStone::OrthancVolumeImage> ct_; - std::unique_ptr<OrthancStone::StructureSetLoader> struct_; - - public: - RtViewerDemoApplication(MessageBroker& broker) : - IObserver(broker), - source_(NULL), - slice_(0) - { - } - - /* - dev options on bgo xps15 - - COMMAND LINE - --ct-series=a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa --dose-instance=830a69ff-8e4b5ee3-b7f966c8-bccc20fb-d322dceb --struct-instance=54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9 - - URL PARAMETERS - ?ct-series=a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa&dose-instance=830a69ff-8e4b5ee3-b7f966c8-bccc20fb-d322dceb&struct-instance=54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9 - - */ - - void ParseParameters(const boost::program_options::variables_map& parameters) - { - // Generic - { - if (parameters.count("verbose")) - { - Orthanc::Logging::EnableInfoLevel(true); - LOG(INFO) << "Verbose logs (info) are enabled"; - } - } - - { - if (parameters.count("trace")) - { - LOG(INFO) << "parameters.count(\"trace\") != 0"; - Orthanc::Logging::EnableTraceLevel(true); - VLOG(1) << "Trace logs (debug) are enabled"; - } - } - - // CT series - { - - if (parameters.count("ct-series") != 1) - { - LOG(ERROR) << "There must be exactly one CT series specified"; - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - ctSeries_ = parameters["ct-series"].as<std::string>(); - } - - // RTDOSE - { - if (parameters.count("dose-instance") == 1) - { - doseInstance_ = parameters["dose-instance"].as<std::string>(); - } - else - { -#ifdef BGO_NOT_IMPLEMENTED_YET - // Dose series - if (parameters.count("dose-series") != 1) - { - LOG(ERROR) << "the RTDOSE series is missing"; - throw Orthanc::OrthancException( - Orthanc::ErrorCode_ParameterOutOfRange); - } - doseSeries_ = parameters["ct"].as<std::string>(); -#endif - LOG(ERROR) << "the RTSTRUCT instance is missing"; - throw Orthanc::OrthancException( - Orthanc::ErrorCode_ParameterOutOfRange); - } - } - - // RTSTRUCT - { - if (parameters.count("struct-instance") == 1) - { - structInstance_ = parameters["struct-instance"].as<std::string>(); - } - else - { -#ifdef BGO_NOT_IMPLEMENTED_YET - // Struct series - if (parameters.count("struct-series") != 1) - { - LOG(ERROR) << "the RTSTRUCT series is missing"; - throw Orthanc::OrthancException( - Orthanc::ErrorCode_ParameterOutOfRange); - } - structSeries_ = parameters["struct-series"].as<std::string>(); -#endif - LOG(ERROR) << "the RTSTRUCT instance is missing"; - throw Orthanc::OrthancException( - Orthanc::ErrorCode_ParameterOutOfRange); - } - } - } - - virtual void DeclareStartupOptions( - boost::program_options::options_description& options) - { - boost::program_options::options_description generic( - "RtViewerDemo options. Please note that some of these options " - "are mutually exclusive"); - generic.add_options() - ("ct-series", boost::program_options::value<std::string>(), - "Orthanc ID of the CT series") - ("dose-instance", boost::program_options::value<std::string>(), - "Orthanc ID of the RTDOSE instance (incompatible with dose-series)") - ("dose-series", boost::program_options::value<std::string>(), - "NOT IMPLEMENTED YET. Orthanc ID of the RTDOSE series (incompatible" - " with dose-instance)") - ("struct-instance", boost::program_options::value<std::string>(), - "Orthanc ID of the RTSTRUCT instance (incompatible with struct-" - "series)") - ("struct-series", boost::program_options::value<std::string>(), - "NOT IMPLEMENTED YET. Orthanc ID of the RTSTRUCT (incompatible with" - " struct-instance)") - ("smooth", boost::program_options::value<bool>()->default_value(true), - "Enable bilinear image smoothing") - ; - - options.add(generic); - } - - virtual void Initialize( - StoneApplicationContext* context, - IStatusBar& statusBar, - const boost::program_options::variables_map& parameters) - { - using namespace OrthancStone; - - ParseParameters(parameters); - - context_ = context; - - statusBar.SetMessage("Use the key \"s\" to reinitialize the layout"); - - if (!ctSeries_.empty()) - { - printf("CT = [%s]\n", ctSeries_.c_str()); - - ct_.reset(new OrthancStone::OrthancVolumeImage( - IObserver::GetBroker(), context->GetOrthancApiClient(), false)); - ct_->ScheduleLoadSeries(ctSeries_); - //ct_->ScheduleLoadSeries( - // "a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa"); - //ct_->ScheduleLoadSeries( - // "03677739-1d8bca40-db1daf59-d74ff548-7f6fc9c0"); - } - - if (!doseSeries_.empty() || - !doseInstance_.empty()) - { - dose_.reset(new OrthancStone::OrthancVolumeImage( - IObserver::GetBroker(), context->GetOrthancApiClient(), true)); - - - dose_->RegisterObserverCallback( - new Callable<RtViewerDemoApplication, ISlicedVolume::VolumeReadyMessage> - (*this, &RtViewerDemoApplication::OnVolumeReadyMessage)); - - dose_->RegisterObserverCallback( - new Callable<RtViewerDemoApplication, ISlicedVolume::SliceContentChangedMessage> - (*this, &RtViewerDemoApplication::OnSliceContentChangedMessage)); - - if (doseInstance_.empty()) - { - dose_->ScheduleLoadSeries(doseSeries_); - } - else - { - dose_->ScheduleLoadInstance(doseInstance_); - } - - //dose_->ScheduleLoadInstance( - //"830a69ff-8e4b5ee3-b7f966c8-bccc20fb-d322dceb"); // 1 - //dose_->ScheduleLoadInstance( - //"269f26f4-0c83eeeb-2e67abbd-5467a40f-f1bec90c"); //0522c0001 TCIA - } - - if (!structInstance_.empty()) - { - struct_.reset(new OrthancStone::StructureSetLoader( - IObserver::GetBroker(), context->GetOrthancApiClient())); - - struct_->ScheduleLoadInstance(structInstance_); - - //struct_->ScheduleLoadInstance( - //"54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9"); - //struct_->ScheduleLoadInstance( - //"17cd032b-ad92a438-ca05f06a-f9e96668-7e3e9e20"); // 0522c0001 TCIA - } - - mainWidget_ = new LayoutWidget("main-layout"); - mainWidget_->SetBackgroundColor(0, 0, 0); - mainWidget_->SetBackgroundCleared(true); - mainWidget_->SetPadding(0); - - auto axialWidget = CreateDoseCtWidget - (ct_, dose_, struct_, OrthancStone::VolumeProjection_Axial); - mainWidget_->AddWidget(axialWidget); - - std::unique_ptr<OrthancStone::LayoutWidget> subLayout( - new OrthancStone::LayoutWidget("main-layout")); - subLayout->SetVertical(); - subLayout->SetPadding(5); - - auto coronalWidget = CreateDoseCtWidget - (ct_, dose_, struct_, OrthancStone::VolumeProjection_Coronal); - subLayout->AddWidget(coronalWidget); - - auto sagittalWidget = CreateDoseCtWidget - (ct_, dose_, struct_, OrthancStone::VolumeProjection_Sagittal); - subLayout->AddWidget(sagittalWidget); - - mainWidget_->AddWidget(subLayout.release()); - } - }; - - - size_t RtViewerDemoApplication::AddDoseLayer( - SliceViewerWidget& widget, - OrthancVolumeImage& volume, VolumeProjection projection) - { - size_t layer = widget.AddLayer( - new VolumeImageMPRSlicer(IObserver::GetBroker(), volume)); - - RenderStyle s; - //s.drawGrid_ = true; - s.SetColor(255, 0, 0); // Draw missing PET layer in red - s.alpha_ = 0.3f; - s.applyLut_ = true; - s.lut_ = Orthanc::EmbeddedResources::COLORMAP_JET; - s.interpolation_ = ImageInterpolation_Bilinear; - widget.SetLayerStyle(layer, s); - - return layer; - } - - void RtViewerDemoApplication::AddStructLayer( - SliceViewerWidget& widget, StructureSetLoader& loader) - { - widget.AddLayer(new DicomStructureSetSlicer( - IObserver::GetBroker(), loader)); - } - - SliceViewerWidget* RtViewerDemoApplication::CreateDoseCtWidget( - std::unique_ptr<OrthancVolumeImage>& ct, - std::unique_ptr<OrthancVolumeImage>& dose, - std::unique_ptr<StructureSetLoader>& structLoader, - VolumeProjection projection) - { - std::unique_ptr<OrthancStone::SliceViewerWidget> widget( - new OrthancStone::SliceViewerWidget(IObserver::GetBroker(), - "ct-dose-widget")); - - if (ct.get() != NULL) - { - AddCtLayer(*widget, *ct); - } - - if (dose.get() != NULL) - { - size_t layer = AddDoseLayer(*widget, *dose, projection); - - // we need to store the dose rendering widget because we'll update them - // according to various asynchronous events - doseCtWidgetLayerPairs_.push_back(std::make_pair(widget.get(), layer)); -#if 0 - interactors_.push_back(new VolumeImageInteractor( - IObserver::GetBroker(), *dose, *widget, projection)); -#else - interactors_.push_back(new DoseInteractor( - IObserver::GetBroker(), *dose, *widget, projection, layer)); -#endif - } - else if (ct.get() != NULL) - { - interactors_.push_back( - new VolumeImageInteractor( - IObserver::GetBroker(), *ct, *widget, projection)); - } - - if (structLoader.get() != NULL) - { - AddStructLayer(*widget, *structLoader); - } - - return widget.release(); - } - - void RtViewerDemoApplication::AddCtLayer( - SliceViewerWidget& widget, - OrthancVolumeImage& volume) - { - size_t layer = widget.AddLayer( - new VolumeImageMPRSlicer(IObserver::GetBroker(), volume)); - - RenderStyle s; - //s.drawGrid_ = true; - s.alpha_ = 1; - s.windowing_ = ImageWindowing_Bone; - widget.SetLayerStyle(layer, s); - } - } -} - - - -#if ORTHANC_ENABLE_WASM==1 - -#include "Platforms/Wasm/WasmWebService.h" -#include "Platforms/Wasm/WasmViewport.h" - -#include <emscripten/emscripten.h> - -//#include "SampleList.h" - - -OrthancStone::IStoneApplication* CreateUserApplication(OrthancStone::MessageBroker& broker) -{ - return new OrthancStone::Samples::RtViewerDemoApplication(broker); -} - -OrthancStone::WasmPlatformApplicationAdapter* CreateWasmApplicationAdapter(OrthancStone::MessageBroker& broker, OrthancStone::IStoneApplication* application) -{ - return dynamic_cast<OrthancStone::Samples::RtViewerDemoApplication*>(application)->CreateWasmApplicationAdapter(broker); -} - -#else - -//#include "SampleList.h" -#if ORTHANC_ENABLE_SDL==1 -#include "Applications/Sdl/SdlStoneApplicationRunner.h" -#endif -#if ORTHANC_ENABLE_QT==1 -#include "Applications/Qt/SampleQtApplicationRunner.h" -#endif -#include "Framework/Messages/MessageBroker.h" - -int main(int argc, char* argv[]) -{ - OrthancStone::MessageBroker broker; - OrthancStone::Samples::RtViewerDemoApplication sampleStoneApplication(broker); - -#if ORTHANC_ENABLE_SDL==1 - OrthancStone::SdlStoneApplicationRunner sdlApplicationRunner(broker, sampleStoneApplication); - return sdlApplicationRunner.Execute(argc, argv); -#endif -#if ORTHANC_ENABLE_QT==1 - OrthancStone::Samples::SampleQtApplicationRunner qtAppRunner(broker, sampleStoneApplication); - return qtAppRunner.Execute(argc, argv); -#endif -} - - -#endif - - - - - - -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/nginx.local.conf Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -# Local config to serve the WASM samples static files and reverse proxy Orthanc. -# Uses port 9977 instead of 80. - -# `events` section is mandatory -events { - worker_connections 1024; # Default: 1024 -} - -http { - - # prevent nginx sync issues on OSX - proxy_buffering off; - - server { - listen 9977 default_server; - client_max_body_size 4G; - - # location may have to be adjusted depending on your OS and nginx install - include /etc/nginx/mime.types; - # if not in your system mime.types, add this line to support WASM: - # types { - # application/wasm wasm; - # } - - # serve WASM static files - root build-web/; - location / { - } - - # reverse proxy orthanc - location /orthanc/ { - rewrite /orthanc(.*) $1 break; - proxy_pass http://127.0.0.1:8042; - proxy_set_header Host $http_host; - proxy_set_header my-auth-header good-token; - proxy_request_buffering off; - proxy_max_temp_file_size 0; - client_max_body_size 0; - } - - - } - -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/rt-viewer-demo.html Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -<!doctype html> - -<html lang="us"> - <head> - <meta charset="utf-8" /> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> - - <!-- Disable pinch zoom on mobile devices --> - <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> - <meta name="HandheldFriendly" content="true" /> - - <title>Simple Viewer</title> - <link href="samples-styles.css" rel="stylesheet" /> - -<body> - <div style="width: 100%; height: 5%"> - <p>RTSTRUCT viewer demonstration</p> - </div> - <div style="width: 100%; height: 95%"> - <canvas id="canvas"></canvas> - </div> - <script type="text/javascript" src="app-rt-viewer-demo.js"></script> -</body> - -</html> \ No newline at end of file
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/rt-viewer-demo.ts Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -import { InitializeWasmApplication } from '../../../Platforms/Wasm/wasm-application-runner'; - - -InitializeWasmApplication("RtViewerDemo", "/orthanc"); -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/rt-viewer-demo.tsconfig.json Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -{ - "extends" : "./tsconfig-samples", - "compilerOptions": { - }, - "include" : [ - "rt-viewer-demo.ts" - ] -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/samples-styles.css Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -html, body { - width: 100%; - height: 100%; - margin: 0px; - border: 0; - overflow: hidden; /* Disable scrollbars */ - display: block; /* No floating content on sides */ - background-color: black; - color: white; - font-family: Arial, Helvetica, sans-serif; -} - -canvas { - left:0px; - top:0px; -} \ No newline at end of file
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/start-serving-files.sh Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -#!/bin/bash - -sudo nginx -p $(pwd) -c nginx.local.conf - -echo "Please browse to :" - -echo "http://localhost:9977/rt-viewer-demo.html?ct-series=a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa&dose-instance=830a69ff-8e4b5ee3-b7f966c8-bccc20fb-d322dceb&struct-instance=54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9" - -echo "(This requires you have uploaded the correct files to your local Orthanc instance)"
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/stop-serving-files.sh Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -#!/bin/bash - -sudo nginx -s stop -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/rt-viewer-demo/tsconfig-samples.json Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -{ - "extends" : "../../../Platforms/Wasm/tsconfig-stone.json", - "compilerOptions": { - "sourceMap": false, - "lib" : [ - "es2017", - "dom", - "dom.iterable" - ] - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Samples/Deprecated/tsconfig-stone.json Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -{ - "include" : [ - "../../Platforms/Wasm/stone-framework-loader.ts", - "../../Platforms/Wasm/wasm-application-runner.ts", - "../../Platforms/Wasm/wasm-viewport.ts" - ] -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Sdl/SdlCairoSurface.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "SdlCairoSurface.h" - -#if ORTHANC_ENABLE_SDL == 1 - -#include <Core/Logging.h> -#include <Core/OrthancException.h> - -namespace OrthancStone -{ - SdlCairoSurface::SdlCairoSurface(SdlWindow& window) : - window_(window), - sdlSurface_(NULL) - { - } - - - SdlCairoSurface::~SdlCairoSurface() - { - if (sdlSurface_) - { - SDL_FreeSurface(sdlSurface_); - } - } - - - void SdlCairoSurface::SetSize(unsigned int width, - unsigned int height) - { - if (cairoSurface_.get() == NULL || - cairoSurface_->GetWidth() != width || - cairoSurface_->GetHeight() != height) - { - cairoSurface_.reset(new CairoSurface(width, height, false /* no alpha */)); - - // TODO Big endian? - static const uint32_t rmask = 0x00ff0000; - static const uint32_t gmask = 0x0000ff00; - static const uint32_t bmask = 0x000000ff; - - if (sdlSurface_) - { - SDL_FreeSurface(sdlSurface_); - } - - sdlSurface_ = SDL_CreateRGBSurfaceFrom(cairoSurface_->GetBuffer(), width, height, 32, - cairoSurface_->GetPitch(), rmask, gmask, bmask, 0); - if (!sdlSurface_) - { - LOG(ERROR) << "Cannot create a SDL surface from a Cairo surface"; - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - } - } - - - void SdlCairoSurface::Render(Deprecated::IViewport& viewport) - { - if (cairoSurface_.get() == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - Orthanc::ImageAccessor target; - cairoSurface_->GetWriteableAccessor(target); - - if (viewport.Render(target)) - { - window_.Render(sdlSurface_); - } - } -} - -#endif
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Sdl/SdlCairoSurface.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#if ORTHANC_ENABLE_SDL == 1 - -#include "../../Framework/Viewport/SdlWindow.h" -#include "../../Framework/Wrappers/CairoSurface.h" -#include "../../Framework/Deprecated/Viewport/IViewport.h" - -#include <Core/Compatibility.h> - -#include <SDL_render.h> -#include <boost/thread/mutex.hpp> - -namespace OrthancStone -{ - class SdlCairoSurface : public boost::noncopyable - { - private: - std::unique_ptr<CairoSurface> cairoSurface_; - SdlWindow& window_; - SDL_Surface* sdlSurface_; - - public: - SdlCairoSurface(SdlWindow& window); - - ~SdlCairoSurface(); - - void SetSize(unsigned int width, - unsigned int height); - - void Render(Deprecated::IViewport& viewport); - }; -} - -#endif
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Sdl/SdlEngine.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,282 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "SdlEngine.h" - -#if ORTHANC_ENABLE_SDL == 1 - -#include <Core/Logging.h> - -#include <SDL.h> - -namespace OrthancStone -{ - void SdlEngine::SetSize(unsigned int width, - unsigned int height) - { - NativeStoneApplicationContext::GlobalMutexLocker locker(context_); - locker.GetCentralViewport().SetSize(width, height); - surface_.SetSize(width, height); - } - - - void SdlEngine::RenderFrame() - { - if (viewportChanged_) - { - NativeStoneApplicationContext::GlobalMutexLocker locker(context_); - surface_.Render(locker.GetCentralViewport()); - - viewportChanged_ = false; - } - } - - - KeyboardModifiers SdlEngine::GetKeyboardModifiers(const uint8_t* keyboardState, - const int scancodeCount) - { - int result = KeyboardModifiers_None; - - if (keyboardState != NULL) - { - if (SDL_SCANCODE_LSHIFT < scancodeCount && - keyboardState[SDL_SCANCODE_LSHIFT]) - { - result |= KeyboardModifiers_Shift; - } - - if (SDL_SCANCODE_RSHIFT < scancodeCount && - keyboardState[SDL_SCANCODE_RSHIFT]) - { - result |= KeyboardModifiers_Shift; - } - - if (SDL_SCANCODE_LCTRL < scancodeCount && - keyboardState[SDL_SCANCODE_LCTRL]) - { - result |= KeyboardModifiers_Control; - } - - if (SDL_SCANCODE_RCTRL < scancodeCount && - keyboardState[SDL_SCANCODE_RCTRL]) - { - result |= KeyboardModifiers_Control; - } - - if (SDL_SCANCODE_LALT < scancodeCount && - keyboardState[SDL_SCANCODE_LALT]) - { - result |= KeyboardModifiers_Alt; - } - - if (SDL_SCANCODE_RALT < scancodeCount && - keyboardState[SDL_SCANCODE_RALT]) - { - result |= KeyboardModifiers_Alt; - } - } - - return static_cast<KeyboardModifiers>(result); - } - - - SdlEngine::SdlEngine(SdlWindow& window, - NativeStoneApplicationContext& context) : - window_(window), - context_(context), - surface_(window), - viewportChanged_(true) - { - } - - - void SdlEngine::Run() - { - int scancodeCount = 0; - const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount); - - SetSize(window_.GetWidth(), window_.GetHeight()); - - { - NativeStoneApplicationContext::GlobalMutexLocker locker(context_); - locker.GetCentralViewport().FitContent(); - } - - bool stop = false; - while (!stop) - { - RenderFrame(); - - SDL_Event event; - - while (!stop && - SDL_PollEvent(&event)) - { - NativeStoneApplicationContext::GlobalMutexLocker locker(context_); - - if (event.type == SDL_QUIT) - { - stop = true; - break; - } - else if (event.type == SDL_MOUSEBUTTONDOWN) - { - KeyboardModifiers modifiers = GetKeyboardModifiers(keyboardState, scancodeCount); - - switch (event.button.button) - { - case SDL_BUTTON_LEFT: - locker.GetCentralViewport().MouseDown(MouseButton_Left, event.button.x, event.button.y, modifiers, std::vector<Deprecated::Touch>()); - break; - - case SDL_BUTTON_RIGHT: - locker.GetCentralViewport().MouseDown(MouseButton_Right, event.button.x, event.button.y, modifiers, std::vector<Deprecated::Touch>()); - break; - - case SDL_BUTTON_MIDDLE: - locker.GetCentralViewport().MouseDown(MouseButton_Middle, event.button.x, event.button.y, modifiers, std::vector<Deprecated::Touch>()); - break; - - default: - break; - } - } - else if (event.type == SDL_MOUSEMOTION) - { - locker.GetCentralViewport().MouseMove(event.button.x, event.button.y, std::vector<Deprecated::Touch>()); - } - else if (event.type == SDL_MOUSEBUTTONUP) - { - locker.GetCentralViewport().MouseUp(); - } - else if (event.type == SDL_WINDOWEVENT) - { - switch (event.window.event) - { - case SDL_WINDOWEVENT_LEAVE: - locker.GetCentralViewport().MouseLeave(); - break; - - case SDL_WINDOWEVENT_ENTER: - locker.GetCentralViewport().MouseEnter(); - break; - - case SDL_WINDOWEVENT_SIZE_CHANGED: - SetSize(event.window.data1, event.window.data2); - break; - - default: - break; - } - } - else if (event.type == SDL_MOUSEWHEEL) - { - KeyboardModifiers modifiers = GetKeyboardModifiers(keyboardState, scancodeCount); - - int x, y; - SDL_GetMouseState(&x, &y); - - if (event.wheel.y > 0) - { - locker.GetCentralViewport().MouseWheel(MouseWheelDirection_Up, x, y, modifiers); - } - else if (event.wheel.y < 0) - { - locker.GetCentralViewport().MouseWheel(MouseWheelDirection_Down, x, y, modifiers); - } - } - else if (event.type == SDL_KEYDOWN && - event.key.repeat == 0 /* Ignore key bounce */) - { - KeyboardModifiers modifiers = GetKeyboardModifiers(keyboardState, scancodeCount); - - switch (event.key.keysym.sym) - { - case SDLK_a: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'a', modifiers); break; - case SDLK_b: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'b', modifiers); break; - case SDLK_c: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'c', modifiers); break; - case SDLK_d: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'd', modifiers); break; - case SDLK_e: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'e', modifiers); break; - case SDLK_f: window_.ToggleMaximize(); break; - case SDLK_g: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'g', modifiers); break; - case SDLK_h: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'h', modifiers); break; - case SDLK_i: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'i', modifiers); break; - case SDLK_j: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'j', modifiers); break; - case SDLK_k: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'k', modifiers); break; - case SDLK_l: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'l', modifiers); break; - case SDLK_m: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'm', modifiers); break; - case SDLK_n: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'n', modifiers); break; - case SDLK_o: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'o', modifiers); break; - case SDLK_p: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'p', modifiers); break; - case SDLK_q: stop = true; break; - case SDLK_r: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'r', modifiers); break; - case SDLK_s: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 's', modifiers); break; - case SDLK_t: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 't', modifiers); break; - case SDLK_u: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'u', modifiers); break; - case SDLK_v: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'v', modifiers); break; - case SDLK_w: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'w', modifiers); break; - case SDLK_x: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'x', modifiers); break; - case SDLK_y: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'y', modifiers); break; - case SDLK_z: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, 'z', modifiers); break; - case SDLK_KP_0: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '0', modifiers); break; - case SDLK_KP_1: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '1', modifiers); break; - case SDLK_KP_2: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '2', modifiers); break; - case SDLK_KP_3: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '3', modifiers); break; - case SDLK_KP_4: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '4', modifiers); break; - case SDLK_KP_5: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '5', modifiers); break; - case SDLK_KP_6: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '6', modifiers); break; - case SDLK_KP_7: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '7', modifiers); break; - case SDLK_KP_8: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '8', modifiers); break; - case SDLK_KP_9: locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '9', modifiers); break; - - case SDLK_PLUS: - case SDLK_KP_PLUS: - locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '+', modifiers); break; - - case SDLK_MINUS: - case SDLK_KP_MINUS: - locker.GetCentralViewport().KeyPressed(KeyboardKeys_Generic, '-', modifiers); break; - - case SDLK_DELETE: - locker.GetCentralViewport().KeyPressed(KeyboardKeys_Delete, 0, modifiers); break; - case SDLK_BACKSPACE: - locker.GetCentralViewport().KeyPressed(KeyboardKeys_Backspace, 0, modifiers); break; - case SDLK_RIGHT: - locker.GetCentralViewport().KeyPressed(KeyboardKeys_Right, 0, modifiers); break; - case SDLK_LEFT: - locker.GetCentralViewport().KeyPressed(KeyboardKeys_Left, 0, modifiers); break; - case SDLK_UP: - locker.GetCentralViewport().KeyPressed(KeyboardKeys_Up, 0, modifiers); break; - case SDLK_DOWN: - locker.GetCentralViewport().KeyPressed(KeyboardKeys_Down, 0, modifiers); break; - default: - break; - } - } - } - - // Small delay to avoid using 100% of CPU - SDL_Delay(1); - } - } -} - -#endif
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Sdl/SdlEngine.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#if ORTHANC_ENABLE_SDL == 1 - -#include "../../Framework/Messages/ObserverBase.h" -#include "../Generic/NativeStoneApplicationContext.h" -#include "SdlCairoSurface.h" - -namespace OrthancStone -{ - class SdlEngine : public ObserverBase<SdlEngine> - { - private: - SdlWindow& window_; - NativeStoneApplicationContext& context_; - SdlCairoSurface surface_; - bool viewportChanged_; - - void SetSize(unsigned int width, - unsigned int height); - - void RenderFrame(); - - static KeyboardModifiers GetKeyboardModifiers(const uint8_t* keyboardState, - const int scancodeCount); - - public: - SdlEngine(SdlWindow& window, - NativeStoneApplicationContext& context); - - void OnViewportChanged(const Deprecated::IViewport::ViewportChangedMessage& message) - { - viewportChanged_ = true; - } - - void Run(); - }; -} - -#endif
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Sdl/SdlOrthancSurface.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "SdlOrthancSurface.h" - -#if ORTHANC_ENABLE_SDL == 1 - -#include <Core/Logging.h> -#include <Core/OrthancException.h> -#include <Core/Images/Image.h> - -#include <SDL_render.h> - -namespace OrthancStone -{ - SdlOrthancSurface::SdlOrthancSurface(SdlWindow& window) : - window_(window), - sdlSurface_(NULL) - { - } - - - SdlOrthancSurface::~SdlOrthancSurface() - { - if (sdlSurface_) - { - SDL_FreeSurface(sdlSurface_); - } - } - - - void SdlOrthancSurface::SetSize(unsigned int width, - unsigned int height) - { - if (image_.get() == NULL || - image_->GetWidth() != width || - image_->GetHeight() != height) - { - image_.reset(new Orthanc::Image(Orthanc::PixelFormat_BGRA32, width, height, true)); // (*) - - if (image_->GetPitch() != image_->GetWidth() * 4) - { - // This should have been ensured by setting "forceMinimalPitch" to "true" (*) - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - - // TODO Big endian? - static const uint32_t rmask = 0x00ff0000; - static const uint32_t gmask = 0x0000ff00; - static const uint32_t bmask = 0x000000ff; - - if (sdlSurface_) - { - SDL_FreeSurface(sdlSurface_); - } - - sdlSurface_ = SDL_CreateRGBSurfaceFrom(image_->GetBuffer(), width, height, 32, - image_->GetPitch(), rmask, gmask, bmask, 0); - if (!sdlSurface_) - { - LOG(ERROR) << "Cannot create a SDL surface from a Orthanc surface"; - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - } - } - - - Orthanc::ImageAccessor& SdlOrthancSurface::GetImage() - { - if (image_.get() == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - return *image_; - } - - - void SdlOrthancSurface::Render() - { - if (image_.get() == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - window_.Render(sdlSurface_); - } -} - -#endif
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Sdl/SdlOrthancSurface.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#if ORTHANC_ENABLE_SDL == 1 - -#include "../../Framework/Viewport/SdlWindow.h" - -#include <Core/Compatibility.h> -#include <Core/Images/ImageAccessor.h> - -#include <boost/thread/mutex.hpp> - -namespace OrthancStone -{ - class SdlOrthancSurface : public boost::noncopyable - { - private: - std::unique_ptr<Orthanc::ImageAccessor> image_; - SdlWindow& window_; - SDL_Surface* sdlSurface_; - - public: - SdlOrthancSurface(SdlWindow& window); - - ~SdlOrthancSurface(); - - void SetSize(unsigned int width, - unsigned int height); - - Orthanc::ImageAccessor& GetImage(); - - void Render(); - }; -} - -#endif
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Sdl/SdlStoneApplicationRunner.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,138 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#if ORTHANC_ENABLE_SDL != 1 -#error this file shall be included only with the ORTHANC_ENABLE_SDL set to 1 -#endif - -#include "SdlStoneApplicationRunner.h" - -#include "../../Platforms/Generic/OracleWebService.h" -#include "SdlEngine.h" - -#include <Core/Logging.h> -#include <Core/HttpClient.h> -#include <Core/Toolbox.h> -#include <Core/OrthancException.h> -#include <Plugins/Samples/Common/OrthancHttpConnection.h> - -#include <boost/program_options.hpp> - -namespace OrthancStone -{ - void SdlStoneApplicationRunner::Initialize() - { - SdlWindow::GlobalInitialize(); - } - - - void SdlStoneApplicationRunner::DeclareCommandLineOptions(boost::program_options::options_description& options) - { - boost::program_options::options_description sdl("SDL options"); - sdl.add_options() - ("width", boost::program_options::value<int>()->default_value(1024), "Initial width of the SDL window") - ("height", boost::program_options::value<int>()->default_value(768), "Initial height of the SDL window") - ("opengl", boost::program_options::value<bool>()->default_value(true), "Enable OpenGL in SDL") - ; - - options.add(sdl); - } - - - void SdlStoneApplicationRunner::ParseCommandLineOptions(const boost::program_options::variables_map& parameters) - { - if (!parameters.count("width") || - !parameters.count("height") || - !parameters.count("opengl")) - { - LOG(ERROR) << "Parameter \"width\", \"height\" or \"opengl\" is missing"; - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - int w = parameters["width"].as<int>(); - int h = parameters["height"].as<int>(); - if (w <= 0 || h <= 0) - { - LOG(ERROR) << "Parameters \"width\" and \"height\" must be positive"; - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - width_ = static_cast<unsigned int>(w); - height_ = static_cast<unsigned int>(h); - LOG(WARNING) << "Initial display size: " << width_ << "x" << height_; - - enableOpenGl_ = parameters["opengl"].as<bool>(); - if (enableOpenGl_) - { - LOG(WARNING) << "OpenGL is enabled, disable it with option \"--opengl=off\" if the application crashes"; - } - else - { - LOG(WARNING) << "OpenGL is disabled, enable it with option \"--opengl=on\" for best performance"; - } - } - - - void SdlStoneApplicationRunner::Run(NativeStoneApplicationContext& context, - const std::string& title, - int argc, - char* argv[]) - { - /************************************************************** - * Run the application inside a SDL window - **************************************************************/ - - LOG(WARNING) << "Starting the application"; - - SdlWindow window(title.c_str(), width_, height_, enableOpenGl_); - boost::shared_ptr<SdlEngine> sdl(new SdlEngine(window, context)); - - { - NativeStoneApplicationContext::GlobalMutexLocker locker(context); - - sdl->Register<Deprecated::IViewport::ViewportChangedMessage> - (locker.GetCentralViewport(), &SdlEngine::OnViewportChanged); - - //context.GetCentralViewport().Register(sdl); // (*) - } - - context.Start(); - sdl->Run(); - - LOG(WARNING) << "Stopping the application"; - - // Don't move the "Stop()" command below out of the block, - // otherwise the application might crash, because the - // "SdlEngine" is an observer of the viewport (*) and the - // update thread started by "context.Start()" would call a - // destructed object (the "SdlEngine" is deleted with the - // lexical scope). - - // TODO Is this still true with message broker? - context.Stop(); - } - - - void SdlStoneApplicationRunner::Finalize() - { - SdlWindow::GlobalFinalize(); - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Sdl/SdlStoneApplicationRunner.h Thu Sep 17 15:39:33 2020 +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-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../Generic/NativeStoneApplicationRunner.h" - -#if ORTHANC_ENABLE_SDL != 1 -#error this file shall be included only with the ORTHANC_ENABLE_SDL set to 1 -#endif - -#include <SDL.h> // Necessary to avoid undefined reference to `SDL_main' - -namespace OrthancStone -{ - class SdlStoneApplicationRunner : public NativeStoneApplicationRunner - { - private: - unsigned int width_; - unsigned int height_; - bool enableOpenGl_; - - public: - SdlStoneApplicationRunner(boost::shared_ptr<IStoneApplication> application) : - NativeStoneApplicationRunner(application) - { - } - - virtual void Initialize(); - - virtual void DeclareCommandLineOptions(boost::program_options::options_description& options); - - virtual void Run(NativeStoneApplicationContext& context, - const std::string& title, - int argc, - char* argv[]); - - virtual void ParseCommandLineOptions(const boost::program_options::variables_map& parameters); - - virtual void Finalize(); - }; -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/StoneApplicationContext.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "StoneApplicationContext.h" - -#include <Core/OrthancException.h> - -namespace OrthancStone -{ - void StoneApplicationContext::InitializeOrthanc() - { - if (webService_ == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - orthanc_.reset(new Deprecated::OrthancApiClient(*webService_, orthancBaseUrl_)); - } - - - boost::shared_ptr<Deprecated::IWebService> StoneApplicationContext::GetWebService() - { - if (webService_ == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - return webService_; - } - - - boost::shared_ptr<Deprecated::OrthancApiClient> StoneApplicationContext::GetOrthancApiClient() - { - if (orthanc_.get() == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - return orthanc_; - } - - - void StoneApplicationContext::SetWebService(boost::shared_ptr<Deprecated::IWebService> webService) - { - webService_ = webService; - InitializeOrthanc(); - } - - - void StoneApplicationContext::SetOrthancBaseUrl(const std::string& baseUrl) - { - // Make sure the base url ends with "/" - if (baseUrl.empty() || - baseUrl[baseUrl.size() - 1] != '/') - { - orthancBaseUrl_ = baseUrl + "/"; - } - else - { - orthancBaseUrl_ = baseUrl; - } - - if (webService_ != NULL) - { - InitializeOrthanc(); - } - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/StoneApplicationContext.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../Framework/Deprecated/Toolbox/IWebService.h" -#include "../Framework/Deprecated/Toolbox/IDelayedCallExecutor.h" -#include "../Framework/Deprecated/Toolbox/OrthancApiClient.h" -#include "../Framework/Deprecated/Viewport/WidgetViewport.h" - - -#ifdef _MSC_VER - #if _MSC_VER > 1910 - #define orthanc_override override - #else - #define orthanc_override - #endif -#elif defined __GNUC__ - #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) -/* Test for GCC > 3.2.0 */ - #if GCC_VERSION > 40900 - #define orthanc_override override - #else - #define orthanc_override - #endif -#else - #define orthanc_override -#endif - -#include <list> - -namespace OrthancStone -{ - // a StoneApplicationContext contains the services that a StoneApplication - // uses and that depends on the environment in which the Application executes. - // I.e, the StoneApplicationContext provides a WebService interface such that - // the StoneApplication can perform HTTP requests. In a WASM environment, - // the WebService is provided by the browser while, in a native environment, - // the WebService is provided by the OracleWebService (a C++ Http client) - - class StoneApplicationContext : public boost::noncopyable - { - private: - boost::shared_ptr<Deprecated::IWebService> webService_; - Deprecated::IDelayedCallExecutor* delayedCallExecutor_; // TODO => shared_ptr ?? - boost::shared_ptr<Deprecated::OrthancApiClient> orthanc_; - std::string orthancBaseUrl_; - - void InitializeOrthanc(); - - public: - StoneApplicationContext() : - delayedCallExecutor_(NULL) - { - } - - virtual ~StoneApplicationContext() - { - } - - boost::shared_ptr<Deprecated::IWebService> GetWebService(); - - boost::shared_ptr<Deprecated::OrthancApiClient> GetOrthancApiClient(); - - void SetWebService(boost::shared_ptr<Deprecated::IWebService> webService); - - void SetOrthancBaseUrl(const std::string& baseUrl); - - void SetDelayedCallExecutor(Deprecated::IDelayedCallExecutor& delayedCallExecutor) - { - delayedCallExecutor_ = &delayedCallExecutor; - } - - Deprecated::IDelayedCallExecutor& GetDelayedCallExecutor() - { - return *delayedCallExecutor_; - } - }; -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Wasm/StartupParametersBuilder.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "StartupParametersBuilder.h" -#include <iostream> -#include <cstdio> -#include "emscripten/html5.h" - -namespace OrthancStone -{ - void StartupParametersBuilder::Clear() - { - startupParameters_.clear(); - } - - void StartupParametersBuilder::SetStartupParameter( - const char* name, - const char* value) - { - startupParameters_.push_back(std::make_tuple(name, value)); - } - - void StartupParametersBuilder::GetStartupParameters( - boost::program_options::variables_map& parameters, - const boost::program_options::options_description& options) - { - std::vector<std::string> argvStrings(startupParameters_.size() + 1); - // argv mirrors pointers to the internal argvStrings buffers. - // ****************************************************** - // THIS IS HIGHLY DANGEROUS SO BEWARE!!!!!!!!!!!!!! - // ****************************************************** - std::vector<const char*> argv(startupParameters_.size() + 1); - - int argCounter = 0; - argvStrings[argCounter] = "dummy.exe"; - argv[argCounter] = argvStrings[argCounter].c_str(); - - argCounter++; - - std::string cmdLine = ""; - for ( StartupParameters::const_iterator it = startupParameters_.begin(); - it != startupParameters_.end(); - it++) - { - std::stringstream argSs; - - argSs << "--" << std::get<0>(*it); - if(std::get<1>(*it).length() > 0) - argSs << "=" << std::get<1>(*it); - - argvStrings[argCounter] = argSs.str(); - cmdLine = cmdLine + " " + argvStrings[argCounter]; - std::cout << cmdLine << std::endl; - argv[argCounter] = argvStrings[argCounter].c_str(); - argCounter++; - } - - - std::cout << "simulated cmdLine = \"" << cmdLine.c_str() << "\"\n"; - - try - { - boost::program_options::store( - boost::program_options::command_line_parser(argCounter, argv.data()). - options(options).allow_unregistered().run(), parameters); - boost::program_options::notify(parameters); - } - catch (boost::program_options::error& e) - { - std::cerr << "Error while parsing the command-line arguments: " << - e.what() << std::endl; - } - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Applications/Wasm/StartupParametersBuilder.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include <boost/program_options.hpp> -#include <tuple> - -#if ORTHANC_ENABLE_SDL == 1 -#error this file shall be included only with the ORTHANC_ENABLE_SDL set to 0 -#endif - -namespace OrthancStone -{ - // This class is used to generate boost program options from a dico. - // In a Wasm context, startup options are passed as URI arguments that - // are then passed to this class as a dico. - // This class regenerates a fake command-line and parses it to produce - // the same output as if the app was started at command-line. - class StartupParametersBuilder - { - typedef std::list<std::tuple<std::string, std::string>> StartupParameters; - StartupParameters startupParameters_; - - public: - - void Clear(); - // Please note that if a parameter is a flag-style one, the value that - // is passed should be an empty string - void SetStartupParameter(const char* name, const char* value); - void GetStartupParameters( - boost::program_options::variables_map& parameters_, - const boost::program_options::options_description& options); - }; - -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/DelayedCallCommand.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "DelayedCallCommand.h" -#include "boost/thread/thread.hpp" - -#include <iostream> - -namespace Deprecated -{ - DelayedCallCommand::DelayedCallCommand(MessageHandler<IDelayedCallExecutor::TimeoutMessage>* callback, // takes ownership - unsigned int timeoutInMs, - Orthanc::IDynamicObject* payload /* takes ownership */, - OrthancStone::NativeStoneApplicationContext& context - ) : - callback_(callback), - payload_(payload), - context_(context), - expirationTimePoint_(boost::posix_time::microsec_clock::local_time() + boost::posix_time::milliseconds(timeoutInMs)), - timeoutInMs_(timeoutInMs) - { - } - - - void DelayedCallCommand::Execute() - { - while (boost::posix_time::microsec_clock::local_time() < expirationTimePoint_) - { - boost::this_thread::sleep(boost::posix_time::milliseconds(1)); - } - } - - void DelayedCallCommand::Commit() - { - // We want to make sure that, i.e, the UpdateThread is not - // triggered while we are updating the "model" with the result of - // an OracleCommand - OrthancStone::NativeStoneApplicationContext::GlobalMutexLocker lock(context_); - - if (callback_.get() != NULL) - { - IDelayedCallExecutor::TimeoutMessage message; // TODO: add payload - callback_->Apply(message); - } - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/DelayedCallCommand.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "IOracleCommand.h" - -#include "../../Framework/Deprecated/Toolbox/IDelayedCallExecutor.h" -#include "../../Framework/Messages/IObservable.h" -#include "../../Framework/Messages/ICallable.h" -#include "../../Applications/Generic/NativeStoneApplicationContext.h" - -#include <boost/date_time/posix_time/posix_time.hpp> - -namespace Deprecated -{ - class DelayedCallCommand : public IOracleCommand, OrthancStone::IObservable - { - protected: - std::unique_ptr<MessageHandler<IDelayedCallExecutor::TimeoutMessage> > callback_; - std::unique_ptr<Orthanc::IDynamicObject> payload_; - OrthancStone::NativeStoneApplicationContext& context_; - boost::posix_time::ptime expirationTimePoint_; - unsigned int timeoutInMs_; - - public: - DelayedCallCommand(MessageHandler<IDelayedCallExecutor::TimeoutMessage>* callback, // takes ownership - unsigned int timeoutInMs, - Orthanc::IDynamicObject* payload /* takes ownership */, - OrthancStone::NativeStoneApplicationContext& context - ); - - virtual void Execute(); - - virtual void Commit(); - }; - -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/IOracleCommand.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include <Core/IDynamicObject.h> - -namespace Deprecated -{ - class IOracleCommand : public Orthanc::IDynamicObject - { - public: - virtual ~IOracleCommand() - { - } - - // This part of the command can be invoked simultaneously, and - // must not modify the Stone context - virtual void Execute() = 0; - - // This part of the command must be invoked in mutual exclusion - virtual void Commit() = 0; - }; -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/Oracle.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,212 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "Oracle.h" - -#include <Core/Logging.h> -#include <Core/MultiThreading/SharedMessageQueue.h> -#include <Core/OrthancException.h> - -#include <vector> -#include <stdio.h> -#include <boost/thread/mutex.hpp> - -namespace Deprecated -{ - class Oracle::PImpl - { - private: - enum State - { - State_Init, - State_Started, - State_Stopped - }; - - boost::mutex oracleMutex_; - State state_; - std::vector<boost::thread*> threads_; - Orthanc::SharedMessageQueue queue_; - - static void Worker(PImpl* that) - { - for (;;) - { - State state; - - { - boost::mutex::scoped_lock lock(that->oracleMutex_); - state = that->state_; - } - - if (state == State_Stopped) - { - break; - } - - std::unique_ptr<Orthanc::IDynamicObject> item(that->queue_.Dequeue(100)); - if (item.get() != NULL) - { - IOracleCommand& command = dynamic_cast<IOracleCommand&>(*item); - try - { - command.Execute(); - } - catch (Orthanc::OrthancException& /*ex*/) - { - // this is probably a curl error that has been triggered. We may just ignore it. - // The command.success_ will stay at false and this will be handled in the command.Commit - } - - // Random sleeping to test - //boost::this_thread::sleep(boost::posix_time::milliseconds(50 * (1 + rand() % 10))); - - command.Commit(); - } - } - } - - public: - PImpl(unsigned int threadCount) : - state_(State_Init), - threads_(threadCount) - { - } - - ~PImpl() - { - if (state_ == State_Started) - { - LOG(ERROR) << "You should have manually called Oracle::Stop()"; - Stop(); - } - } - - Orthanc::SharedMessageQueue& GetQueue() - { - return queue_; - } - - void Submit(IOracleCommand* command) - { - std::unique_ptr<IOracleCommand> protection(command); - - if (command == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); - } - - boost::mutex::scoped_lock lock(oracleMutex_); - - switch (state_) - { - case State_Init: - case State_Started: - queue_.Enqueue(protection.release()); - break; - - case State_Stopped: - LOG(ERROR) << "Cannot schedule a request to the Oracle after having " - << "called Oracle::Stop()"; - break; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - - } - - void Start() - { - boost::mutex::scoped_lock lock(oracleMutex_); - - if (state_ != State_Init) - { - LOG(ERROR) << "Oracle::PImpl::Start: (state_ != State_Init)"; - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - for (size_t i = 0; i < threads_.size(); i++) - { - threads_[i] = new boost::thread(Worker, this); - } - - state_ = State_Started; - } - - void Stop() - { - { - boost::mutex::scoped_lock lock(oracleMutex_); - - if (state_ != State_Started) - { - LOG(ERROR) << "Oracle::PImpl::Stop(): (state_ != State_Started)"; - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - state_ = State_Stopped; - } - - for (size_t i = 0; i < threads_.size(); i++) - { - if (threads_[i] != NULL) - { - if (threads_[i]->joinable()) - { - threads_[i]->join(); - } - - delete threads_[i]; - } - } - } - }; - - - Oracle::Oracle(unsigned int threadCount) : - pimpl_(new PImpl(threadCount)) - { - } - - void Oracle::Start() - { - pimpl_->Start(); - } - - - void Oracle::Submit(IOracleCommand* command) - { - pimpl_->Submit(command); - } - - - void Oracle::Stop() - { - pimpl_->Stop(); - } - - - void Oracle::WaitEmpty() - { - pimpl_->GetQueue().WaitEmpty(50); - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/Oracle.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "IOracleCommand.h" - -#include <boost/shared_ptr.hpp> - -namespace Deprecated -{ - class Oracle : public boost::noncopyable - { - private: - class PImpl; - - boost::shared_ptr<PImpl> pimpl_; - - public: - Oracle(unsigned int threadCount); - - void Start(); - - void Submit(IOracleCommand* command); - - void WaitEmpty(); // For unit tests - - void Stop(); - }; -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/OracleDelayedCallExecutor.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../Framework/Deprecated/Toolbox/IDelayedCallExecutor.h" -#include "Oracle.h" -#include "../../Applications/Generic/NativeStoneApplicationContext.h" -#include "DelayedCallCommand.h" - -namespace Deprecated -{ - // The OracleTimeout executes callbacks after a delay. - class OracleDelayedCallExecutor : public IDelayedCallExecutor - { - private: - Oracle& oracle_; - OrthancStone::NativeStoneApplicationContext& context_; - - public: - OracleDelayedCallExecutor(Oracle& oracle, - OrthancStone::NativeStoneApplicationContext& context) : - oracle_(oracle), - context_(context) - { - } - - virtual void Schedule(MessageHandler<IDelayedCallExecutor::TimeoutMessage>* callback, - unsigned int timeoutInMs = 1000) - { - oracle_.Submit(new DelayedCallCommand(callback, timeoutInMs, NULL, context_)); - } - }; -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/OracleWebService.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "OracleWebService.h" -#include "../../Framework/Deprecated/Toolbox/IWebService.h" - -namespace Deprecated -{ - - - class OracleWebService::WebServiceCachedGetCommand : public IOracleCommand, OrthancStone::IObservable - { - protected: - std::unique_ptr<MessageHandler<IWebService::HttpRequestSuccessMessage> > successCallback_; - std::unique_ptr<Orthanc::IDynamicObject> payload_; - boost::shared_ptr<BaseWebService::CachedHttpRequestSuccessMessage> cachedMessage_; - OrthancStone::NativeStoneApplicationContext& context_; - - public: - WebServiceCachedGetCommand(MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership - boost::shared_ptr<BaseWebService::CachedHttpRequestSuccessMessage> cachedMessage, - Orthanc::IDynamicObject* payload /* takes ownership */, - OrthancStone::NativeStoneApplicationContext& context - ) : - successCallback_(successCallback), - payload_(payload), - cachedMessage_(cachedMessage), - context_(context) - { - } - - virtual void Execute() - { - // nothing to do, everything is in the commit - } - - virtual void Commit() - { - // We want to make sure that, i.e, the UpdateThread is not - // triggered while we are updating the "model" with the result of - // a WebServiceCommand - OrthancStone::NativeStoneApplicationContext::GlobalMutexLocker lock(context_); - - IWebService::HttpRequestSuccessMessage successMessage(cachedMessage_->GetUri(), - cachedMessage_->GetAnswer(), - cachedMessage_->GetAnswerSize(), - cachedMessage_->GetAnswerHttpHeaders(), - payload_.get()); - - successCallback_->Apply(successMessage); - } - }; - - void OracleWebService::NotifyHttpSuccessLater(boost::shared_ptr<BaseWebService::CachedHttpRequestSuccessMessage> cachedMessage, - Orthanc::IDynamicObject* payload, // takes ownership - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback) - { - oracle_.Submit(new WebServiceCachedGetCommand(successCallback, cachedMessage, payload, context_)); - } - - -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/OracleWebService.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../Framework/Deprecated/Toolbox/BaseWebService.h" -#include "Oracle.h" -#include "WebServiceGetCommand.h" -#include "WebServicePostCommand.h" -#include "WebServiceDeleteCommand.h" -#include "../../Applications/Generic/NativeStoneApplicationContext.h" - -namespace Deprecated -{ - // The OracleWebService performs HTTP requests in a native environment. - // It uses a thread pool to handle multiple HTTP requests in a same time. - // It works asynchronously to mimick the behaviour of the WebService running in a WASM environment. - class OracleWebService : public BaseWebService - { - private: - Oracle& oracle_; - OrthancStone::NativeStoneApplicationContext& context_; - Orthanc::WebServiceParameters parameters_; - - class WebServiceCachedGetCommand; - - public: - OracleWebService(Oracle& oracle, - const Orthanc::WebServiceParameters& parameters, - OrthancStone::NativeStoneApplicationContext& context) : - oracle_(oracle), - context_(context), - parameters_(parameters) - { - } - - virtual void PostAsync(const std::string& uri, - const HttpHeaders& headers, - const std::string& body, - Orthanc::IDynamicObject* payload, // takes ownership - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, // takes ownership - unsigned int timeoutInSeconds = 60) - { - oracle_.Submit(new WebServicePostCommand(successCallback, failureCallback, parameters_, uri, headers, timeoutInSeconds, body, payload, context_)); - } - - virtual void DeleteAsync(const std::string& uri, - const HttpHeaders& headers, - Orthanc::IDynamicObject* payload, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, - unsigned int timeoutInSeconds = 60) - { - oracle_.Submit(new WebServiceDeleteCommand(successCallback, failureCallback, parameters_, uri, headers, timeoutInSeconds, payload, context_)); - } - - protected: - virtual void GetAsyncInternal(const std::string& uri, - const HttpHeaders& headers, - Orthanc::IDynamicObject* payload, // takes ownership - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL,// takes ownership - unsigned int timeoutInSeconds = 60) - { - oracle_.Submit(new WebServiceGetCommand(successCallback, failureCallback, parameters_, uri, headers, timeoutInSeconds, payload, context_)); - } - - virtual void NotifyHttpSuccessLater(boost::shared_ptr<BaseWebService::CachedHttpRequestSuccessMessage> cachedHttpMessage, - Orthanc::IDynamicObject* payload, // takes ownership - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback); - - }; -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/WebServiceCommandBase.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "WebServiceCommandBase.h" - -#include <Core/HttpClient.h> - -namespace Deprecated -{ - WebServiceCommandBase::WebServiceCommandBase(MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, - const Orthanc::WebServiceParameters& parameters, - const std::string& url, - const IWebService::HttpHeaders& headers, - unsigned int timeoutInSeconds, - Orthanc::IDynamicObject* payload /* takes ownership */, - OrthancStone::NativeStoneApplicationContext& context) : - successCallback_(successCallback), - failureCallback_(failureCallback), - parameters_(parameters), - url_(url), - headers_(headers), - payload_(payload), - success_(false), - httpStatus_(Orthanc::HttpStatus_None), - context_(context), - timeoutInSeconds_(timeoutInSeconds) - { - } - - - void WebServiceCommandBase::Commit() - { - // We want to make sure that, i.e, the UpdateThread is not - // triggered while we are updating the "model" with the result of - // a WebServiceCommand - OrthancStone::NativeStoneApplicationContext::GlobalMutexLocker lock(context_); - - if (success_ && successCallback_.get() != NULL) - { - IWebService::HttpRequestSuccessMessage message - (url_, answer_.c_str(), answer_.size(), answerHeaders_, payload_.get()); - successCallback_->Apply(message); - } - else if (!success_ && failureCallback_.get() != NULL) - { - IWebService::HttpRequestErrorMessage message(url_, httpStatus_, payload_.get()); - failureCallback_->Apply(message); - } - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/WebServiceCommandBase.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "IOracleCommand.h" - -#include "../../Framework/Deprecated/Toolbox/IWebService.h" -#include "../../Framework/Messages/IObservable.h" -#include "../../Framework/Messages/ICallable.h" -#include "../../Applications/Generic/NativeStoneApplicationContext.h" - -#include <Core/WebServiceParameters.h> - -#include <memory> - -namespace Deprecated -{ - class WebServiceCommandBase : public IOracleCommand, OrthancStone::IObservable - { - protected: - std::unique_ptr<MessageHandler<IWebService::HttpRequestSuccessMessage> > successCallback_; - std::unique_ptr<MessageHandler<IWebService::HttpRequestErrorMessage> > failureCallback_; - Orthanc::WebServiceParameters parameters_; - std::string url_; - IWebService::HttpHeaders headers_; - std::unique_ptr<Orthanc::IDynamicObject> payload_; - bool success_; - Orthanc::HttpStatus httpStatus_; - std::string answer_; - IWebService::HttpHeaders answerHeaders_; - OrthancStone::NativeStoneApplicationContext& context_; - unsigned int timeoutInSeconds_; - - public: - WebServiceCommandBase(MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, // takes ownership - const Orthanc::WebServiceParameters& parameters, - const std::string& url, - const IWebService::HttpHeaders& headers, - unsigned int timeoutInSeconds, - Orthanc::IDynamicObject* payload /* takes ownership */, - OrthancStone::NativeStoneApplicationContext& context - ); - - virtual void Execute() = 0; - - virtual void Commit(); - }; - -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/WebServiceDeleteCommand.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "WebServiceDeleteCommand.h" - -#include <Core/HttpClient.h> - -namespace Deprecated -{ - WebServiceDeleteCommand::WebServiceDeleteCommand(MessageHandler<Deprecated::IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership - MessageHandler<Deprecated::IWebService::HttpRequestErrorMessage>* failureCallback, // takes ownership - const Orthanc::WebServiceParameters& parameters, - const std::string& url, - const Deprecated::IWebService::HttpHeaders& headers, - unsigned int timeoutInSeconds, - Orthanc::IDynamicObject* payload /* takes ownership */, - OrthancStone::NativeStoneApplicationContext& context) : - WebServiceCommandBase(successCallback, failureCallback, parameters, url, headers, timeoutInSeconds, payload, context) - { - } - - void WebServiceDeleteCommand::Execute() - { - Orthanc::HttpClient client(parameters_, "/"); - client.SetUrl(url_); - client.SetTimeout(timeoutInSeconds_); - client.SetMethod(Orthanc::HttpMethod_Delete); - - for (Deprecated::IWebService::HttpHeaders::const_iterator it = headers_.begin(); it != headers_.end(); it++ ) - { - client.AddHeader(it->first, it->second); - } - - success_ = client.Apply(answer_, answerHeaders_); - httpStatus_ = client.GetLastStatus(); - } - -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/WebServiceDeleteCommand.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "WebServiceCommandBase.h" - -namespace Deprecated -{ - class WebServiceDeleteCommand : public WebServiceCommandBase - { - public: - WebServiceDeleteCommand(MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, // takes ownership - const Orthanc::WebServiceParameters& parameters, - const std::string& url, - const IWebService::HttpHeaders& headers, - unsigned int timeoutInSeconds, - Orthanc::IDynamicObject* payload /* takes ownership */, - OrthancStone::NativeStoneApplicationContext& context); - - virtual void Execute(); - }; -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/WebServiceGetCommand.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "WebServiceGetCommand.h" - -#include <Core/HttpClient.h> - -namespace Deprecated -{ - WebServiceGetCommand::WebServiceGetCommand(MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, // takes ownership - const Orthanc::WebServiceParameters& parameters, - const std::string& url, - const IWebService::HttpHeaders& headers, - unsigned int timeoutInSeconds, - Orthanc::IDynamicObject* payload /* takes ownership */, - OrthancStone::NativeStoneApplicationContext& context) : - WebServiceCommandBase(successCallback, failureCallback, parameters, url, headers, timeoutInSeconds, payload, context) - { - } - - - void WebServiceGetCommand::Execute() - { - Orthanc::HttpClient client(parameters_, "/"); - client.SetUrl(url_); - client.SetTimeout(timeoutInSeconds_); - client.SetMethod(Orthanc::HttpMethod_Get); - - for (IWebService::HttpHeaders::const_iterator it = headers_.begin(); it != headers_.end(); it++ ) - { - client.AddHeader(it->first, it->second); - } - - success_ = client.Apply(answer_, answerHeaders_); - httpStatus_ = client.GetLastStatus(); - } - -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/WebServiceGetCommand.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "WebServiceCommandBase.h" - -namespace Deprecated -{ - class WebServiceGetCommand : public WebServiceCommandBase - { - public: - WebServiceGetCommand(MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, // takes ownership - const Orthanc::WebServiceParameters& parameters, - const std::string& url, - const IWebService::HttpHeaders& headers, - unsigned int timeoutInSeconds, - Orthanc::IDynamicObject* payload /* takes ownership */, - OrthancStone::NativeStoneApplicationContext& context); - - virtual void Execute(); - }; - -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/WebServicePostCommand.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "WebServicePostCommand.h" - -#include <Core/HttpClient.h> - -namespace Deprecated -{ - WebServicePostCommand::WebServicePostCommand(MessageHandler<Deprecated::IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership - MessageHandler<Deprecated::IWebService::HttpRequestErrorMessage>* failureCallback, // takes ownership - const Orthanc::WebServiceParameters& parameters, - const std::string& url, - const Deprecated::IWebService::HttpHeaders& headers, - unsigned int timeoutInSeconds, - const std::string& body, - Orthanc::IDynamicObject* payload /* takes ownership */, - OrthancStone::NativeStoneApplicationContext& context) : - WebServiceCommandBase(successCallback, failureCallback, parameters, url, headers, timeoutInSeconds, payload, context), - body_(body) - { - } - - void WebServicePostCommand::Execute() - { - Orthanc::HttpClient client(parameters_, "/"); - client.SetUrl(url_); - client.SetTimeout(timeoutInSeconds_); - client.SetMethod(Orthanc::HttpMethod_Post); - client.GetBody().swap(body_); - - for (Deprecated::IWebService::HttpHeaders::const_iterator it = headers_.begin(); it != headers_.end(); it++ ) - { - client.AddHeader(it->first, it->second); - } - - success_ = client.Apply(answer_, answerHeaders_); - httpStatus_ = client.GetLastStatus(); - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Generic/WebServicePostCommand.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "WebServiceCommandBase.h" - -namespace Deprecated -{ - class WebServicePostCommand : public WebServiceCommandBase - { - protected: - std::string body_; - - public: - WebServicePostCommand(MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, // takes ownership - const Orthanc::WebServiceParameters& parameters, - const std::string& url, - const IWebService::HttpHeaders& headers, - unsigned int timeoutInSeconds, - const std::string& body, - Orthanc::IDynamicObject* payload /* takes ownership */, - OrthancStone::NativeStoneApplicationContext& context); - - virtual void Execute(); - }; -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/Defaults.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,437 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "Defaults.h" - -#include "WasmWebService.h" -#include "WasmDelayedCallExecutor.h" -#include "../../../Framework/Deprecated/Widgets/TestCairoWidget.h" -#include "../../../Framework/Deprecated/Viewport/WidgetViewport.h" -#include <Applications/Wasm/StartupParametersBuilder.h> -#include <Platforms/Wasm/WasmPlatformApplicationAdapter.h> -#include <Framework/StoneInitialization.h> -#include <Core/Logging.h> -#include <sstream> - -#include <algorithm> - - -static unsigned int width_ = 0; -static unsigned int height_ = 0; - -/**********************************/ - -static std::unique_ptr<OrthancStone::IStoneApplication> application; -static std::unique_ptr<OrthancStone::WasmPlatformApplicationAdapter> applicationWasmAdapter = NULL; -static std::unique_ptr<OrthancStone::StoneApplicationContext> context; -static OrthancStone::StartupParametersBuilder startupParametersBuilder; -static OrthancStone::MessageBroker broker; - -static OrthancStone::ViewportContentChangedObserver viewportContentChangedObserver_(broker); -static OrthancStone::StatusBar statusBar_; - -static std::list<std::shared_ptr<Deprecated::WidgetViewport>> viewports_; - -std::shared_ptr<Deprecated::WidgetViewport> FindViewportSharedPtr(ViewportHandle viewport) { - for (const auto& v : viewports_) { - if (v.get() == viewport) { - return v; - } - } - assert(false); - return std::shared_ptr<Deprecated::WidgetViewport>(); -} - -#ifdef __cplusplus -extern "C" { -#endif - -#if 0 - // rewrite malloc/free in order to monitor allocations. We actually only monitor large allocations (like images ...) - - size_t bigChunksTotalSize = 0; - std::map<void*, size_t> allocatedBigChunks; - - extern void* emscripten_builtin_malloc(size_t bytes); - extern void emscripten_builtin_free(void* mem); - - void * __attribute__((noinline)) malloc(size_t size) - { - void *ptr = emscripten_builtin_malloc(size); - if (size > 100000) - { - bigChunksTotalSize += size; - printf("++ Allocated %zu bytes, got %p. (%zu MB consumed by big chunks)\n", size, ptr, bigChunksTotalSize/(1024*1024)); - allocatedBigChunks[ptr] = size; - } - return ptr; - } - - void __attribute__((noinline)) free(void *ptr) - { - emscripten_builtin_free(ptr); - - std::map<void*, size_t>::iterator it = allocatedBigChunks.find(ptr); - if (it != allocatedBigChunks.end()) - { - bigChunksTotalSize -= it->second; - printf("-- Freed %zu bytes at %p. (%zu MB consumed by big chunks)\n", it->second, ptr, bigChunksTotalSize/(1024*1024)); - allocatedBigChunks.erase(it); - } - } -#endif // 0 - - using namespace OrthancStone; - - // when WASM needs a C++ viewport - ViewportHandle EMSCRIPTEN_KEEPALIVE CreateCppViewport() { - - std::shared_ptr<Deprecated::WidgetViewport> viewport(new Deprecated::WidgetViewport(broker)); - printf("viewport %x\n", (int)viewport.get()); - - viewports_.push_back(viewport); - - printf("There are now %lu viewports in C++\n", viewports_.size()); - - viewport->SetStatusBar(statusBar_); - - viewport->RegisterObserverCallback( - new Callable<ViewportContentChangedObserver, Deprecated::IViewport::ViewportChangedMessage> - (viewportContentChangedObserver_, &ViewportContentChangedObserver::OnViewportChanged)); - - return viewport.get(); - } - - // when WASM does not need a viewport anymore, it should release it - void EMSCRIPTEN_KEEPALIVE ReleaseCppViewport(ViewportHandle viewport) { - viewports_.remove_if([viewport](const std::shared_ptr<Deprecated::WidgetViewport>& v) { return v.get() == viewport;}); - - printf("There are now %lu viewports in C++\n", viewports_.size()); - } - - void EMSCRIPTEN_KEEPALIVE CreateWasmApplication(ViewportHandle viewport) { - printf("Initializing Stone\n"); - OrthancStone::StoneInitialize(); - printf("CreateWasmApplication\n"); - - application.reset(CreateUserApplication(broker)); - applicationWasmAdapter.reset(CreateWasmApplicationAdapter(broker, application.get())); - Deprecated::WasmWebService::SetBroker(broker); - Deprecated::WasmDelayedCallExecutor::SetBroker(broker); - - startupParametersBuilder.Clear(); - } - - void EMSCRIPTEN_KEEPALIVE SetStartupParameter(const char* keyc, - const char* value) { - startupParametersBuilder.SetStartupParameter(keyc, value); - } - - void EMSCRIPTEN_KEEPALIVE StartWasmApplication(const char* baseUri) { - - printf("StartWasmApplication\n"); - - Orthanc::Logging::SetErrorWarnInfoTraceLoggingFunctions( - stone_console_error, stone_console_warning, - stone_console_info, stone_console_trace); - - // recreate a command line from uri arguments and parse it - boost::program_options::variables_map parameters; - boost::program_options::options_description options; - application->DeclareStartupOptions(options); - startupParametersBuilder.GetStartupParameters(parameters, options); - - context.reset(new OrthancStone::StoneApplicationContext(broker)); - context->SetOrthancBaseUrl(baseUri); - printf("Base URL to Orthanc API: [%s]\n", baseUri); - context->SetWebService(Deprecated::WasmWebService::GetInstance()); - context->SetDelayedCallExecutor(Deprecated::WasmDelayedCallExecutor::GetInstance()); - application->Initialize(context.get(), statusBar_, parameters); - application->InitializeWasm(); - -// viewport->SetSize(width_, height_); - printf("StartWasmApplication - completed\n"); - } - - bool EMSCRIPTEN_KEEPALIVE WasmIsTraceLevelEnabled() - { - return Orthanc::Logging::IsTraceLevelEnabled(); - } - - bool EMSCRIPTEN_KEEPALIVE WasmIsInfoLevelEnabled() - { - return Orthanc::Logging::IsInfoLevelEnabled(); - } - - void EMSCRIPTEN_KEEPALIVE WasmDoAnimation() - { - for (auto viewport : viewports_) { - // TODO Only launch the JavaScript timer if "HasAnimation()" - if (viewport->HasAnimation()) - { - viewport->DoAnimation(); - } - - } - - } - - - void EMSCRIPTEN_KEEPALIVE ViewportSetSize(ViewportHandle viewport, unsigned int width, unsigned int height) - { - width_ = width; - height_ = height; - - viewport->SetSize(width, height); - } - - int EMSCRIPTEN_KEEPALIVE ViewportRender(ViewportHandle viewport, - unsigned int width, - unsigned int height, - uint8_t* data) - { - viewportContentChangedObserver_.Reset(); - - //printf("ViewportRender called %dx%d\n", width, height); - if (width == 0 || - height == 0) - { - return 1; - } - - Orthanc::ImageAccessor surface; - surface.AssignWritable(Orthanc::PixelFormat_BGRA32, width, height, 4 * width, data); - - viewport->Render(surface); - - // Convert from BGRA32 memory layout (only color mode supported by - // Cairo, which corresponds to CAIRO_FORMAT_ARGB32) to RGBA32 (as - // expected by HTML5 canvas). This simply amounts to swapping the - // B and R channels. - uint8_t* p = data; - for (unsigned int y = 0; y < height; y++) { - for (unsigned int x = 0; x < width; x++) { - uint8_t tmp = p[0]; - p[0] = p[2]; - p[2] = tmp; - - p += 4; - } - } - - return 1; - } - - - void EMSCRIPTEN_KEEPALIVE ViewportMouseDown(ViewportHandle viewport, - unsigned int rawButton, - int x, - int y, - unsigned int rawModifiers) - { - OrthancStone::MouseButton button; - switch (rawButton) - { - case 0: - button = OrthancStone::MouseButton_Left; - break; - - case 1: - button = OrthancStone::MouseButton_Middle; - break; - - case 2: - button = OrthancStone::MouseButton_Right; - break; - - default: - return; // Unknown button - } - - viewport->MouseDown(button, x, y, OrthancStone::KeyboardModifiers_None, std::vector<Deprecated::Touch>()); - } - - - void EMSCRIPTEN_KEEPALIVE ViewportMouseWheel(ViewportHandle viewport, - int deltaY, - int x, - int y, - int isControl) - { - if (deltaY != 0) - { - OrthancStone::MouseWheelDirection direction = (deltaY < 0 ? - OrthancStone::MouseWheelDirection_Up : - OrthancStone::MouseWheelDirection_Down); - OrthancStone::KeyboardModifiers modifiers = OrthancStone::KeyboardModifiers_None; - - if (isControl != 0) - { - modifiers = OrthancStone::KeyboardModifiers_Control; - } - - viewport->MouseWheel(direction, x, y, modifiers); - } - } - - - void EMSCRIPTEN_KEEPALIVE ViewportMouseMove(ViewportHandle viewport, - int x, - int y) - { - viewport->MouseMove(x, y, std::vector<Deprecated::Touch>()); - } - - void GetTouchVector(std::vector<Deprecated::Touch>& output, - int touchCount, - float x0, - float y0, - float x1, - float y1, - float x2, - float y2) - { - // TODO: it might be nice to try to pass all the x0,y0 coordinates as arrays but that's not so easy to pass array between JS and C++ - if (touchCount > 0) - { - output.push_back(Deprecated::Touch(x0, y0)); - } - if (touchCount > 1) - { - output.push_back(Deprecated::Touch(x1, y1)); - } - if (touchCount > 2) - { - output.push_back(Deprecated::Touch(x2, y2)); - } - - } - - void EMSCRIPTEN_KEEPALIVE ViewportTouchStart(ViewportHandle viewport, - int touchCount, - float x0, - float y0, - float x1, - float y1, - float x2, - float y2) - { - // printf("touch start with %d touches\n", touchCount); - - std::vector<Deprecated::Touch> touches; - GetTouchVector(touches, touchCount, x0, y0, x1, y1, x2, y2); - viewport->TouchStart(touches); - } - - void EMSCRIPTEN_KEEPALIVE ViewportTouchMove(ViewportHandle viewport, - int touchCount, - float x0, - float y0, - float x1, - float y1, - float x2, - float y2) - { - // printf("touch move with %d touches\n", touchCount); - - std::vector<Deprecated::Touch> touches; - GetTouchVector(touches, touchCount, x0, y0, x1, y1, x2, y2); - viewport->TouchMove(touches); - } - - void EMSCRIPTEN_KEEPALIVE ViewportTouchEnd(ViewportHandle viewport, - int touchCount, - float x0, - float y0, - float x1, - float y1, - float x2, - float y2) - { - // printf("touch end with %d touches remaining\n", touchCount); - - std::vector<Deprecated::Touch> touches; - GetTouchVector(touches, touchCount, x0, y0, x1, y1, x2, y2); - viewport->TouchEnd(touches); - } - - void EMSCRIPTEN_KEEPALIVE ViewportKeyPressed(ViewportHandle viewport, - int key, - const char* keyChar, - bool isShiftPressed, - bool isControlPressed, - bool isAltPressed) - - { - OrthancStone::KeyboardModifiers modifiers = OrthancStone::KeyboardModifiers_None; - if (isShiftPressed) { - modifiers = static_cast<OrthancStone::KeyboardModifiers>(modifiers + OrthancStone::KeyboardModifiers_Shift); - } - if (isControlPressed) { - modifiers = static_cast<OrthancStone::KeyboardModifiers>(modifiers + OrthancStone::KeyboardModifiers_Control); - } - if (isAltPressed) { - modifiers = static_cast<OrthancStone::KeyboardModifiers>(modifiers + OrthancStone::KeyboardModifiers_Alt); - } - - char c = 0; - if (keyChar != NULL && key == OrthancStone::KeyboardKeys_Generic) { - c = keyChar[0]; - } - viewport->KeyPressed(static_cast<OrthancStone::KeyboardKeys>(key), c, modifiers); - } - - - void EMSCRIPTEN_KEEPALIVE ViewportMouseUp(ViewportHandle viewport) - { - viewport->MouseUp(); - } - - - void EMSCRIPTEN_KEEPALIVE ViewportMouseEnter(ViewportHandle viewport) - { - viewport->MouseEnter(); - } - - - void EMSCRIPTEN_KEEPALIVE ViewportMouseLeave(ViewportHandle viewport) - { - viewport->MouseLeave(); - } - - const char* EMSCRIPTEN_KEEPALIVE SendSerializedMessageToStoneApplication(const char* message) - { - static std::string output; // we don't want the string to be deallocated when we return to JS code so we always use the same string (this is fine since JS is single-thread) - - //printf("SendSerializedMessageToStoneApplication\n"); - //printf("%s", message); - - if (applicationWasmAdapter.get() != NULL) { - applicationWasmAdapter->HandleSerializedMessageFromWeb(output, std::string(message)); - return output.c_str(); - } - printf("This Stone application does not have a Web Adapter, unable to send messages"); - return NULL; - } - -#ifdef __cplusplus -} -#endif
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/Defaults.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include <emscripten/emscripten.h> - -#include "../../Framework/Deprecated/Viewport/WidgetViewport.h" -#include "../../Framework/Deprecated/Widgets/LayoutWidget.h" -#include <Applications/IStoneApplication.h> -#include <Platforms/Wasm/WasmPlatformApplicationAdapter.h> - -typedef Deprecated::WidgetViewport* ViewportHandle; // the objects exchanged between JS and C++ - -#ifdef __cplusplus -extern "C" { -#endif - - // JS methods accessible from C++ - extern void ScheduleWebViewportRedrawFromCpp(ViewportHandle cppViewportHandle); - extern void UpdateStoneApplicationStatusFromCppWithString(const char* statusUpdateMessage); - extern void UpdateStoneApplicationStatusFromCppWithSerializedMessage(const char* statusUpdateMessage); - extern void stone_console_error(const char*); - extern void stone_console_warning(const char*); - extern void stone_console_info(const char*); - extern void stone_console_trace(const char*); - - // C++ methods accessible from JS - extern void EMSCRIPTEN_KEEPALIVE CreateWasmApplication(ViewportHandle cppViewportHandle); - extern void EMSCRIPTEN_KEEPALIVE SetStartupParameter(const char* keyc, const char* value); - - -#ifdef __cplusplus -} -#endif - -// these methods must be implemented in the custom app "mainWasm.cpp" -extern OrthancStone::IStoneApplication* CreateUserApplication(OrthancStone::MessageBroker& broker); -extern OrthancStone::WasmPlatformApplicationAdapter* CreateWasmApplicationAdapter(OrthancStone::MessageBroker& broker, OrthancStone::IStoneApplication* application); - -namespace OrthancStone { - - // default Observer to trigger Viewport redraw when something changes in the Viewport - class ViewportContentChangedObserver : public IObserver - { - private: - // Flag to avoid flooding JavaScript with redundant Redraw requests - bool isScheduled_; - - public: - ViewportContentChangedObserver(MessageBroker& broker) : - IObserver(broker), - isScheduled_(false) - { - } - - void Reset() - { - isScheduled_ = false; - } - - void OnViewportChanged(const Deprecated::IViewport::ViewportChangedMessage& message) - { - if (!isScheduled_) - { - ScheduleWebViewportRedrawFromCpp((ViewportHandle)&message.GetOrigin()); // loosing constness when transmitted to Web - isScheduled_ = true; - } - } - }; - - // default status bar to log messages on the console/stdout - class StatusBar : public Deprecated::IStatusBar - { - public: - virtual void ClearMessage() - { - } - - virtual void SetMessage(const std::string& message) - { - printf("%s\n", message.c_str()); - } - }; -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/WasmDelayedCallExecutor.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "WasmDelayedCallExecutor.h" -#include "json/value.h" -#include "json/writer.h" -#include <emscripten/emscripten.h> - -#ifdef __cplusplus -extern "C" { -#endif - - extern void WasmDelayedCallExecutor_Schedule(void* callable, - unsigned int timeoutInMs - /*void* payload*/); - - void EMSCRIPTEN_KEEPALIVE WasmDelayedCallExecutor_ExecuteCallback(void* callable - //void* payload - ) - { - if (callable == NULL) - { - throw; - } - else - { - reinterpret_cast<OrthancStone::MessageHandler<Deprecated::IDelayedCallExecutor::TimeoutMessage>*>(callable)-> - Apply(Deprecated::IDelayedCallExecutor::TimeoutMessage()); // uri, reinterpret_cast<Orthanc::IDynamicObject*>(payload))); - } - } - - -#ifdef __cplusplus -} -#endif - - - -namespace Deprecated -{ - OrthancStone::MessageBroker* WasmDelayedCallExecutor::broker_ = NULL; - - - void WasmDelayedCallExecutor::Schedule(OrthancStone::MessageHandler<IDelayedCallExecutor::TimeoutMessage>* callback, - unsigned int timeoutInMs) - { - WasmDelayedCallExecutor_Schedule(callback, timeoutInMs); - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/WasmDelayedCallExecutor.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../Framework/Deprecated/Toolbox/IDelayedCallExecutor.h" -#include <Core/OrthancException.h> - -namespace Deprecated -{ - class WasmDelayedCallExecutor : public IDelayedCallExecutor - { - private: - static OrthancStone::MessageBroker* broker_; - - // Private constructor => Singleton design pattern - WasmDelayedCallExecutor(OrthancStone::MessageBroker& broker) : - IDelayedCallExecutor(broker) - { - } - - public: - static WasmDelayedCallExecutor& GetInstance() - { - if (broker_ == NULL) - { - printf("WasmDelayedCallExecutor::GetInstance(): broker not initialized\n"); - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - static WasmDelayedCallExecutor instance(*broker_); - return instance; - } - - static void SetBroker(OrthancStone::MessageBroker& broker) - { - broker_ = &broker; - } - - virtual void Schedule(OrthancStone::MessageHandler<IDelayedCallExecutor::TimeoutMessage>* callback, - unsigned int timeoutInMs = 1000); - - }; -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/WasmDelayedCallExecutor.js Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -mergeInto(LibraryManager.library, { - WasmDelayedCallExecutor_Schedule: function(callable, timeoutInMs/*, payload*/) { - setTimeout(function() { - window.WasmDelayedCallExecutor_ExecuteCallback(callable/*, payload*/); - }, timeoutInMs); - } -});
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/WasmPlatformApplicationAdapter.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "WasmPlatformApplicationAdapter.h" - -#include "Framework/StoneException.h" -#include <stdio.h> -#include "Platforms/Wasm/Defaults.h" - -namespace OrthancStone -{ - WasmPlatformApplicationAdapter::WasmPlatformApplicationAdapter(MessageBroker& broker, IStoneApplication& application) - : IObserver(broker), - application_(application) - { - } - - void WasmPlatformApplicationAdapter::HandleSerializedMessageFromWeb(std::string& output, const std::string& input) - { - try - { - application_.HandleSerializedMessage(input.c_str()); - } - catch (StoneException& exc) - { - printf("Error while handling message from web (error code = %d):\n", exc.GetErrorCode()); - printf("While interpreting input: '%s'\n", input.c_str()); - output = std::string("ERROR : "); - } - catch (std::exception& exc) - { - printf("Error while handling message from web (error text = %s):\n", exc.what()); - printf("While interpreting input: '%s'\n", input.c_str()); - output = std::string("ERROR : "); - } - } - - void WasmPlatformApplicationAdapter::NotifyStatusUpdateFromCppToWebWithString(const std::string& statusUpdateMessage) - { - try - { - UpdateStoneApplicationStatusFromCppWithString(statusUpdateMessage.c_str()); - } - catch (...) - { - printf("Error while handling string message to web\n"); - } - } - - void WasmPlatformApplicationAdapter::NotifyStatusUpdateFromCppToWebWithSerializedMessage(const std::string& statusUpdateMessage) - { - try - { - UpdateStoneApplicationStatusFromCppWithSerializedMessage(statusUpdateMessage.c_str()); - } - catch (...) - { - printf("Error while handling serialized message to web\n"); - } - } - -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/WasmPlatformApplicationAdapter.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include <string> -#include "../../../Framework/Messages/IObserver.h" -#include <Applications/IStoneApplication.h> - -namespace OrthancStone -{ - class WasmPlatformApplicationAdapter : public IObserver - { - IStoneApplication& application_; - public: - WasmPlatformApplicationAdapter(MessageBroker& broker, IStoneApplication& application); - - virtual void HandleSerializedMessageFromWeb(std::string& output, const std::string& input); - virtual void NotifyStatusUpdateFromCppToWebWithString(const std::string& statusUpdateMessage); - virtual void NotifyStatusUpdateFromCppToWebWithSerializedMessage(const std::string& statusUpdateMessage); - }; -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/WasmViewport.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "WasmViewport.h" - -#include <vector> -#include <memory> - -std::vector<std::shared_ptr<Deprecated::WidgetViewport>> wasmViewports; - -void AttachWidgetToWasmViewport(const char* htmlCanvasId, Deprecated::IWidget* centralWidget) { - std::shared_ptr<Deprecated::WidgetViewport> viewport(CreateWasmViewportFromCpp(htmlCanvasId)); - viewport->SetCentralWidget(centralWidget); - - wasmViewports.push_back(viewport); -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/WasmViewport.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../Framework/Deprecated/Viewport/WidgetViewport.h" - -#include <emscripten/emscripten.h> - -#ifdef __cplusplus -extern "C" { -#endif - - // JS methods accessible from C++ - extern Deprecated::WidgetViewport* CreateWasmViewportFromCpp(const char* htmlCanvasId); - -#ifdef __cplusplus -} -#endif - -extern void AttachWidgetToWasmViewport(const char* htmlCanvasId, Deprecated::IWidget* centralWidget);
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/WasmWebService.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,189 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "WasmWebService.h" -#include "json/value.h" -#include "json/writer.h" -#include <emscripten/emscripten.h> -#include <boost/shared_ptr.hpp> - -struct CachedSuccessNotification -{ - boost::shared_ptr<Deprecated::BaseWebService::CachedHttpRequestSuccessMessage> cachedMessage; - std::unique_ptr<Orthanc::IDynamicObject> payload; - OrthancStone::MessageHandler<Deprecated::IWebService::HttpRequestSuccessMessage>* successCallback; -}; - - -#ifdef __cplusplus -extern "C" { -#endif - - extern void WasmWebService_GetAsync(void* callableSuccess, - void* callableFailure, - const char* uri, - const char* headersInJsonString, - void* payload, - unsigned int timeoutInSeconds); - - extern void WasmWebService_ScheduleLaterCachedSuccessNotification(void* brol); - - extern void WasmWebService_PostAsync(void* callableSuccess, - void* callableFailure, - const char* uri, - const char* headersInJsonString, - const void* body, - size_t bodySize, - void* payload, - unsigned int timeoutInSeconds); - - extern void WasmWebService_DeleteAsync(void* callableSuccess, - void* callableFailure, - const char* uri, - const char* headersInJsonString, - void* payload, - unsigned int timeoutInSeconds); - - void EMSCRIPTEN_KEEPALIVE WasmWebService_NotifyError(void* failureCallable, - const char* uri, - unsigned int httpStatus, - void* payload) - { - if (failureCallable != NULL) - { - reinterpret_cast<OrthancStone::MessageHandler<Deprecated::IWebService::HttpRequestErrorMessage>*>(failureCallable)-> - Apply(Deprecated::IWebService::HttpRequestErrorMessage(uri, static_cast<Orthanc::HttpStatus>(httpStatus), reinterpret_cast<Orthanc::IDynamicObject*>(payload))); - } - } - - void EMSCRIPTEN_KEEPALIVE WasmWebService_NotifyCachedSuccess(void* notification_) - { - // notification has been allocated in C++ and passed to JS. It must be deleted by this method - std::unique_ptr<CachedSuccessNotification> notification(reinterpret_cast<CachedSuccessNotification*>(notification_)); - - notification->successCallback->Apply(Deprecated::IWebService::HttpRequestSuccessMessage( - notification->cachedMessage->GetUri(), - notification->cachedMessage->GetAnswer(), - notification->cachedMessage->GetAnswerSize(), - notification->cachedMessage->GetAnswerHttpHeaders(), - notification->payload.get() - )); - } - - void EMSCRIPTEN_KEEPALIVE WasmWebService_NotifySuccess(void* successCallable, - const char* uri, - const void* body, - size_t bodySize, - const char* answerHeaders, - void* payload) - { - if (successCallable != NULL) - { - Deprecated::IWebService::HttpHeaders headers; - - // TODO - Parse "answerHeaders" - //printf("TODO: parse headers [%s]\n", answerHeaders); - - reinterpret_cast<OrthancStone::MessageHandler<Deprecated::IWebService::HttpRequestSuccessMessage>*>(successCallable)-> - Apply(Deprecated::IWebService::HttpRequestSuccessMessage(uri, body, bodySize, headers, - reinterpret_cast<Orthanc::IDynamicObject*>(payload))); - } - } - -#ifdef __cplusplus -} -#endif - - - -namespace Deprecated -{ - OrthancStone::MessageBroker* WasmWebService::broker_ = NULL; - - void ToJsonString(std::string& output, const IWebService::HttpHeaders& headers) - { - Json::Value jsonHeaders; - for (IWebService::HttpHeaders::const_iterator it = headers.begin(); it != headers.end(); it++ ) - { - jsonHeaders[it->first] = it->second; - } - - Json::StreamWriterBuilder builder; - std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter()); - std::ostringstream outputStr; - - writer->write(jsonHeaders, &outputStr); - output = outputStr.str(); - } - - void WasmWebService::PostAsync(const std::string& relativeUri, - const HttpHeaders& headers, - const std::string& body, - Orthanc::IDynamicObject* payload, - OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallable, - OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallable, - unsigned int timeoutInSeconds) - { - std::string headersInJsonString; - ToJsonString(headersInJsonString, headers); - WasmWebService_PostAsync(successCallable, failureCallable, relativeUri.c_str(), headersInJsonString.c_str(), - body.c_str(), body.size(), payload, timeoutInSeconds); - } - - void WasmWebService::DeleteAsync(const std::string& relativeUri, - const HttpHeaders& headers, - Orthanc::IDynamicObject* payload, - OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallable, - OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallable, - unsigned int timeoutInSeconds) - { - std::string headersInJsonString; - ToJsonString(headersInJsonString, headers); - WasmWebService_DeleteAsync(successCallable, failureCallable, relativeUri.c_str(), headersInJsonString.c_str(), - payload, timeoutInSeconds); - } - - void WasmWebService::GetAsyncInternal(const std::string &relativeUri, - const HttpHeaders &headers, - Orthanc::IDynamicObject *payload, - OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage> *successCallable, - OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage> *failureCallable, - unsigned int timeoutInSeconds) - { - std::string headersInJsonString; - ToJsonString(headersInJsonString, headers); - WasmWebService_GetAsync(successCallable, failureCallable, relativeUri.c_str(), - headersInJsonString.c_str(), payload, timeoutInSeconds); - } - - void WasmWebService::NotifyHttpSuccessLater(boost::shared_ptr<BaseWebService::CachedHttpRequestSuccessMessage> cachedMessage, - Orthanc::IDynamicObject* payload, // takes ownership - OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback) - { - CachedSuccessNotification* notification = new CachedSuccessNotification(); // allocated on the heap, it will be passed to JS and deleted when coming back to C++ - notification->cachedMessage = cachedMessage; - notification->payload.reset(payload); - notification->successCallback = successCallback; - - WasmWebService_ScheduleLaterCachedSuccessNotification(notification); - } - -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/WasmWebService.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../Framework/Deprecated/Toolbox/BaseWebService.h" -#include <Core/OrthancException.h> - -namespace Deprecated -{ -class WasmWebService : public BaseWebService -{ -private: - static OrthancStone::MessageBroker *broker_; - - // Private constructor => Singleton design pattern - WasmWebService(OrthancStone::MessageBroker &broker) : BaseWebService(broker) - { - } - -public: - static WasmWebService &GetInstance() - { - if (broker_ == NULL) - { - printf("WasmWebService::GetInstance(): broker not initialized\n"); - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - static WasmWebService instance(*broker_); - return instance; - } - - static void SetBroker(OrthancStone::MessageBroker &broker) - { - broker_ = &broker; - } - - virtual void PostAsync(const std::string &uri, - const HttpHeaders &headers, - const std::string &body, - Orthanc::IDynamicObject *payload, - OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage> *successCallable, - OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage> *failureCallable = NULL, - unsigned int timeoutInSeconds = 60); - - virtual void DeleteAsync(const std::string &uri, - const HttpHeaders &headers, - Orthanc::IDynamicObject *payload, - OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage> *successCallable, - OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage> *failureCallable = NULL, - unsigned int timeoutInSeconds = 60); - -protected: - virtual void GetAsyncInternal(const std::string &uri, - const HttpHeaders &headers, - Orthanc::IDynamicObject *payload, - OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage> *successCallable, - OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage> *failureCallable = NULL, - unsigned int timeoutInSeconds = 60); - - virtual void NotifyHttpSuccessLater(boost::shared_ptr<BaseWebService::CachedHttpRequestSuccessMessage> cachedHttpMessage, - Orthanc::IDynamicObject *payload, // takes ownership - OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage> *successCallback); -}; -} // namespace Deprecated
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/WasmWebService.js Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -mergeInto(LibraryManager.library, { - WasmWebService_GetAsync: function(callableSuccess, callableFailure, url, headersInJsonString, payload, timeoutInSeconds) { - // Directly use XMLHttpRequest (no jQuery) to retrieve the raw binary data - // http://www.henryalgus.com/reading-binary-files-using-jquery-ajax/ - var xhr = new XMLHttpRequest(); - var url_ = UTF8ToString(url); - var headersInJsonString_ = UTF8ToString(headersInJsonString); - - xhr.open('GET', url_, true); - xhr.responseType = 'arraybuffer'; - xhr.timeout = timeoutInSeconds * 1000; - var headers = JSON.parse(headersInJsonString_); - for (var key in headers) { - xhr.setRequestHeader(key, headers[key]); - } - //console.log(xhr); - xhr.onreadystatechange = function() { - if (this.readyState == XMLHttpRequest.DONE) { - if (xhr.status === 200) { - var s = xhr.getAllResponseHeaders(); - var headers = _malloc(s.length + 1); - stringToUTF8(s, headers, s.length + 1); - - // TODO - Is "new Uint8Array()" necessary? This copies the - // answer to the WebAssembly stack, hence necessitating - // increasing the TOTAL_STACK parameter of Emscripten - window.WasmWebService_NotifySuccess(callableSuccess, url_, new Uint8Array(this.response), - this.response.byteLength, headers, payload); - } else { - window.WasmWebService_NotifyError(callableFailure, url_, xhr.status, payload); - } - } - } - - xhr.send(); - }, - - WasmWebService_ScheduleLaterCachedSuccessNotification: function (brol) { - setTimeout(function() { - window.WasmWebService_NotifyCachedSuccess(brol); - }, 0); - }, - - WasmWebService_PostAsync: function(callableSuccess, callableFailure, url, headersInJsonString, body, bodySize, payload, timeoutInSeconds) { - var xhr = new XMLHttpRequest(); - var url_ = UTF8ToString(url); - var headersInJsonString_ = UTF8ToString(headersInJsonString); - xhr.open('POST', url_, true); - xhr.timeout = timeoutInSeconds * 1000; - xhr.responseType = 'arraybuffer'; - xhr.setRequestHeader('Content-type', 'application/octet-stream'); - - var headers = JSON.parse(headersInJsonString_); - for (var key in headers) { - xhr.setRequestHeader(key, headers[key]); - } - - xhr.onreadystatechange = function() { - if (this.readyState == XMLHttpRequest.DONE) { - if (xhr.status === 200) { - var s = xhr.getAllResponseHeaders(); - var headers = _malloc(s.length + 1); - stringToUTF8(s, headers, s.length + 1); - - window.WasmWebService_NotifySuccess(callableSuccess, url_, new Uint8Array(this.response), - this.response.byteLength, headers, payload); - } else { - window.WasmWebService_NotifyError(callableFailure, url_, xhr.status, payload); - } - } - } - - xhr.send(new Uint8ClampedArray(HEAPU8.buffer, body, bodySize)); - }, - - WasmWebService_DeleteAsync: function(callableSuccess, callableFailure, url, headersInJsonString, payload, timeoutInSeconds) { - var xhr = new XMLHttpRequest(); - var url_ = UTF8ToString(url); - var headersInJsonString_ = UTF8ToString(headersInJsonString); - xhr.open('DELETE', url_, true); - xhr.timeout = timeoutInSeconds * 1000; - xhr.responseType = 'arraybuffer'; - xhr.setRequestHeader('Content-type', 'application/octet-stream'); - - var headers = JSON.parse(headersInJsonString_); - for (var key in headers) { - xhr.setRequestHeader(key, headers[key]); - } - - xhr.onreadystatechange = function() { - if (this.readyState == XMLHttpRequest.DONE) { - if (xhr.status === 200) { - var s = xhr.getAllResponseHeaders(); - var headers = _malloc(s.length + 1); - stringToUTF8(s, headers, s.length + 1); - - window.WasmWebService_NotifySuccess(callableSuccess, url_, new Uint8Array(this.response), - this.response.byteLength, headers, payload); - } else { - window.WasmWebService_NotifyError(callableFailure, url_, xhr.status, payload); - } - } - } - - xhr.send(); - } - -});
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/default-library.js Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -// this file contains the JS method you want to expose to C++ code - -mergeInto(LibraryManager.library, { - - ScheduleWebViewportRedrawFromCpp: function(cppViewportHandle) { - window.ScheduleWebViewportRedraw(cppViewportHandle); - }, - - CreateWasmViewportFromCpp: function(htmlCanvasId) { - return window.CreateWasmViewport(htmlCanvasId); - }, - - // each time the StoneApplication updates its status, it may signal it - // through this method. i.e, to change the status of a button in the web interface - UpdateStoneApplicationStatusFromCppWithString: function(statusUpdateMessage) { - var statusUpdateMessage_ = UTF8ToString(statusUpdateMessage); - window.UpdateWebApplicationWithString(statusUpdateMessage_); - }, - - // same, but with a serialized message - UpdateStoneApplicationStatusFromCppWithSerializedMessage: function(statusUpdateMessage) { - var statusUpdateMessage_ = UTF8ToString(statusUpdateMessage); - window.UpdateWebApplicationWithSerializedMessage(statusUpdateMessage_); - }, - - // These functions are called from C++ (through an extern declaration) - // and call the standard logger that, here, routes to the console. - - stone_console_error : function(message) { - var text = UTF8ToString(message); - window.errorFromCpp(text); - }, - - stone_console_warning : function(message) { - var text = UTF8ToString(message); - window.warningFromCpp(text); - }, - - stone_console_info: function(message) { - var text = UTF8ToString(message); - window.infoFromCpp(text); - }, - - stone_console_trace : function(message) { - var text = UTF8ToString(message); - window.debugFromCpp(text); - } - -});
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/logger.ts Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -export enum LogSource { - Cpp, - Typescript -} - -export class StandardConsoleLogger { - public showSource: boolean = true; - - public debug(...args: any[]): void { - this._debug(LogSource.Typescript, ...args); - } - - public debugFromCpp(...args: any[]): void { - this._debug(LogSource.Cpp, ...args); - } - - public info(...args: any[]): void { - this._info(LogSource.Typescript, ...args); - } - - public infoFromCpp(message: string): void { - this._info(LogSource.Cpp, message); - } - - public warning(...args: any[]): void { - this._warning(LogSource.Typescript, ...args); - } - - public warningFromCpp(message: string): void { - this._warning(LogSource.Cpp, message); - } - - public error(...args: any[]): void { - this._error(LogSource.Typescript, ...args); - } - - public errorFromCpp(message: string): void { - this._error(LogSource.Cpp, message); - } - - public _debug(source: LogSource, ...args: any[]): void { - if ((<any> window).IsTraceLevelEnabled) - { - if ((<any> window).IsTraceLevelEnabled()) - { - var output = this.getOutput(source, args); - console.debug(...output); - } - } - } - - private _info(source: LogSource, ...args: any[]): void { - if ((<any> window).IsInfoLevelEnabled) - { - if ((<any> window).IsInfoLevelEnabled()) - { - var output = this.getOutput(source, args); - console.info(...output); - } - } - } - - public _warning(source: LogSource, ...args: any[]): void { - var output = this.getOutput(source, args); - console.warn(...output); - } - - public _error(source: LogSource, ...args: any[]): void { - var output = this.getOutput(source, args); - console.error(...output); - } - - - private getOutput(source: LogSource, args: any[]): any[] { - var prefix = this.getPrefix(); - var prefixAndSource = Array<string>(); - - if (prefix != null) { - prefixAndSource = [prefix]; - } - - if (this.showSource) { - if (source == LogSource.Typescript) { - prefixAndSource = [...prefixAndSource, "TS "]; - } else if (source == LogSource.Cpp) { - prefixAndSource = [...prefixAndSource, "C++"]; - } - } - - if (prefixAndSource.length > 0) { - prefixAndSource = [...prefixAndSource, "|"]; - } - - return [...prefixAndSource, ...args]; - } - - protected getPrefix(): string | null { - return null; - } -} - -export class TimeConsoleLogger extends StandardConsoleLogger { - protected getPrefix(): string { - let now = new Date(); - let timeString = now.getHours().toString().padStart(2, "0") + ":" + now.getMinutes().toString().padStart(2, "0") + ":" + now.getSeconds().toString().padStart(2, "0") + "." + now.getMilliseconds().toString().padStart(3, "0"); - return timeString; - } -} - -export var defaultLogger: StandardConsoleLogger = new TimeConsoleLogger(); -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/stone-framework-loader.ts Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -/** - * This file contains primitives to interface with WebAssembly and - * with the Stone framework. - **/ -import * as Logger from './logger' - -export declare type InitializationCallback = () => void; - -//export declare var StoneFrameworkModule : any; -export var StoneFrameworkModule : any; - -//const ASSETS_FOLDER : string = "assets/lib"; -//const WASM_FILENAME : string = "orthanc-framework"; - -export class Framework -{ - private static singleton_ : Framework = null; - private static wasmModuleName_ : string = null; - - public static Configure(wasmModuleName: string) { - this.wasmModuleName_ = wasmModuleName; - } - - private constructor(verbose : boolean) - { - //this.ccall('Initialize', null, [ 'number' ], [ verbose ]); - } - - - public ccall( name: string, - returnType: string, - argTypes: Array<string>, - argValues: Array<any>) : any - { - return (<any> window).StoneFrameworkModule.ccall(name, returnType, argTypes, argValues); - } - - - public cwrap( name: string, - returnType: string, - argTypes: Array<string>) : any - { - return (<any> window).StoneFrameworkModule.cwrap(name, returnType, argTypes); - } - - - public static GetInstance() : Framework - { - if (Framework.singleton_ == null) { - throw new Error('The WebAssembly module is not loaded yet'); - } else { - return Framework.singleton_; - } - } - - - public static Initialize( verbose: boolean, - callback: InitializationCallback) - { - Logger.defaultLogger.debug('Initializing WebAssembly Module'); - - (<any> window).errorFromCpp = function(text:any) { Logger.defaultLogger.errorFromCpp(text); }; - (<any> window).warningFromCpp = function(text:any) { Logger.defaultLogger.warningFromCpp(text); }; - (<any> window).infoFromCpp = function(text:any) { Logger.defaultLogger.infoFromCpp(text); }; - (<any> window).debugFromCpp = function(text:any) { Logger.defaultLogger.debugFromCpp(text); }; - - // (<any> window). - (<any> window).StoneFrameworkModule = { - preRun: [ - function() { - Logger.defaultLogger.debug('Loading the Stone Framework using WebAssembly'); - } - ], - postRun: [ - function() { - // This function is called by ".js" wrapper once the ".wasm" - // WebAssembly module has been loaded and compiled by the - // browser - Logger.defaultLogger.debug('WebAssembly is ready'); - Framework.singleton_ = new Framework(verbose); - callback(); - } - ], - totalDependencies: 0 - }; - - // Dynamic loading of the JavaScript wrapper around WebAssembly - var script = document.createElement('script'); - script.type = 'application/javascript'; - //script.src = "orthanc-stone.js"; // ASSETS_FOLDER + '/' + WASM_FILENAME + '.js'; - script.src = this.wasmModuleName_ + ".js";// "OrthancStoneSimpleViewer.js"; // ASSETS_FOLDER + '/' + WASM_FILENAME + '.js'; - script.async = true; - document.head.appendChild(script); - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/tsconfig-stone.json Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -{ - "include" : [ - "stone-framework-loader.ts", - "logger.ts", - "wasm-application-runner.ts", - "wasm-viewport.ts" - ] -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/wasm-application-runner.ts Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,141 +0,0 @@ -import * as Stone from './stone-framework-loader' -import * as StoneViewport from './wasm-viewport' -import * as Logger from './logger' - -if (!('WebAssembly' in window)) { - alert('Sorry, your browser does not support WebAssembly :('); -} - -//var StoneFrameworkModule : Stone.Framework = (<any>window).StoneFrameworkModule; -//export declare var StoneFrameworkModule : Stone.Framework; - -// global functions -var WasmWebService_NotifyError: Function = null; -var WasmWebService_NotifySuccess: Function = null; -var WasmWebService_NotifyCachedSuccess: Function = null; -var WasmDelayedCallExecutor_ExecuteCallback: Function = null; -var WasmDoAnimation: Function = null; -var SetStartupParameter: Function = null; -var CreateWasmApplication: Function = null; -export var CreateCppViewport: Function = null; -var ReleaseCppViewport: Function = null; -var StartWasmApplication: Function = null; -export var SendSerializedMessageToStoneApplication: Function = null; - -var auxiliaryParameters : Map<string,string> = null; - -export function SetApplicationParameters(params : Map<string,string>) { - if (auxiliaryParameters != null) { - console.warn("wasm-application-runner.SetApplicationParameters: about to overwrite the existing application parameters!") - } - auxiliaryParameters = params; -} - -function DoAnimationThread() { - if (WasmDoAnimation != null) { - WasmDoAnimation(); - } - - // Update the viewport content every 100ms if need be - setTimeout(DoAnimationThread, 100); -} - - -function GetUriParameters(): Map<string, string> { - var parameters = window.location.search.substr(1); - - if (parameters != null && - parameters != '') { - var result = new Map<string, string>(); - var tokens = parameters.split('&'); - - for (var i = 0; i < tokens.length; i++) { - var tmp = tokens[i].split('='); - if (tmp.length == 2) { - result[tmp[0]] = decodeURIComponent(tmp[1]); - } else if(tmp.length == 1) { - // if there is no '=', we treat ot afterwards as a flag-style param - result[tmp[0]] = ""; - } - } - return result; - } - else { - return new Map<string, string>(); - } -} - -// function UpdateWebApplication(statusUpdateMessage: string) { -// console.log(statusUpdateMessage); -// } - -function _InitializeWasmApplication(orthancBaseUrl: string): void { - - CreateWasmApplication(); - - // transmit the API-specified parameters to the app before initializing it - for (let key in auxiliaryParameters) { - if (auxiliaryParameters.hasOwnProperty(key)) { - Logger.defaultLogger.debug( - `About to call SetStartupParameter("${key}","${auxiliaryParameters[key]}")`); - SetStartupParameter(key, auxiliaryParameters[key]); - } - } - - // parse uri and transmit the URI parameters to the app before initializing it - let parameters = GetUriParameters(); - - for (let key in parameters) { - if (parameters.hasOwnProperty(key)) { - Logger.defaultLogger.debug( - `About to call SetStartupParameter("${key}","${parameters[key]}")`); - SetStartupParameter(key, parameters[key]); - } - } - - StartWasmApplication(orthancBaseUrl); - - // trigger a first resize of the canvas that has just been initialized - StoneViewport.WasmViewport.ResizeAll(); - - DoAnimationThread(); -} - -export function InitializeWasmApplication(wasmModuleName: string, orthancBaseUrl: string) { - - Stone.Framework.Configure(wasmModuleName); - - // Wait for the Orthanc Framework to be initialized (this initializes - // the WebAssembly environment) and then, create and initialize the Wasm application - Stone.Framework.Initialize(true, function () { - - Logger.defaultLogger.debug("Connecting C++ methods to JS methods"); - - SetStartupParameter = (<any> window).StoneFrameworkModule.cwrap('SetStartupParameter', null, ['string', 'string']); - CreateWasmApplication = (<any> window).StoneFrameworkModule.cwrap('CreateWasmApplication', null, ['number']); - CreateCppViewport = (<any> window).StoneFrameworkModule.cwrap('CreateCppViewport', 'number', []); - ReleaseCppViewport = (<any> window).StoneFrameworkModule.cwrap('ReleaseCppViewport', null, ['number']); - StartWasmApplication = (<any> window).StoneFrameworkModule.cwrap('StartWasmApplication', null, ['string']); - (<any> window).IsTraceLevelEnabled = (<any> window).StoneFrameworkModule.cwrap('WasmIsTraceLevelEnabled', 'boolean', null); - (<any> window).IsInfoLevelEnabled = (<any> window).StoneFrameworkModule.cwrap('WasmIsInfoLevelEnabled', 'boolean', null); - - (<any> window).WasmWebService_NotifyCachedSuccess = (<any> window).StoneFrameworkModule.cwrap('WasmWebService_NotifyCachedSuccess', null, ['number']); - (<any> window).WasmWebService_NotifySuccess = (<any> window).StoneFrameworkModule.cwrap('WasmWebService_NotifySuccess', null, ['number', 'string', 'array', 'number', 'number']); - (<any> window).WasmWebService_NotifyError = (<any> window).StoneFrameworkModule.cwrap('WasmWebService_NotifyError', null, ['number', 'string', 'number', 'number']); - (<any> window).WasmDelayedCallExecutor_ExecuteCallback = (<any> window).StoneFrameworkModule.cwrap('WasmDelayedCallExecutor_ExecuteCallback', null, ['number']); - // no need to put this into the globals for it's only used in this very module - WasmDoAnimation = (<any> window).StoneFrameworkModule.cwrap('WasmDoAnimation', null, []); - - SendSerializedMessageToStoneApplication = (<any> window).StoneFrameworkModule.cwrap('SendSerializedMessageToStoneApplication', 'string', ['string']); - - Logger.defaultLogger.debug("Connecting C++ methods to JS methods - done"); - - _InitializeWasmApplication(orthancBaseUrl); - }); -} - - -// exports.InitializeWasmApplication = InitializeWasmApplication; - - -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Platforms/Wasm/wasm-viewport.ts Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,359 +0,0 @@ -import * as wasmApplicationRunner from './wasm-application-runner' -import * as Logger from './logger' - -var isPendingRedraw = false; - -function ScheduleWebViewportRedraw(cppViewportHandle: any) : void -{ - if (!isPendingRedraw) { - isPendingRedraw = true; - Logger.defaultLogger.debug('Scheduling a refresh of the viewport, as its content changed'); - window.requestAnimationFrame(function() { - isPendingRedraw = false; - let viewport = WasmViewport.GetFromCppViewport(cppViewportHandle); - if (viewport) { - viewport.Redraw(); - } - }); - } -} - -(<any>window).ScheduleWebViewportRedraw = ScheduleWebViewportRedraw; - -declare function UTF8ToString(v: any): string; - -function CreateWasmViewport(htmlCanvasId: string) : any { - var cppViewportHandle = wasmApplicationRunner.CreateCppViewport(); - var canvasId = UTF8ToString(htmlCanvasId); - var webViewport = new WasmViewport((<any> window).StoneFrameworkModule, canvasId, cppViewportHandle); // viewports are stored in a static map in WasmViewport -> won't be deleted - webViewport.Initialize(); - - return cppViewportHandle; -} - -(<any>window).CreateWasmViewport = CreateWasmViewport; - -export class WasmViewport { - - private static viewportsMapByCppHandle_ : Map<number, WasmViewport> = new Map<number, WasmViewport>(); // key = the C++ handle - private static viewportsMapByCanvasId_ : Map<string, WasmViewport> = new Map<string, WasmViewport>(); // key = the canvasId - - private module_ : any; - private canvasId_ : string; - private htmlCanvas_ : HTMLCanvasElement; - private context_ : CanvasRenderingContext2D | null; - private imageData_ : any = null; - private renderingBuffer_ : any = null; - - private touchGestureInProgress_: boolean = false; - private touchCount_: number = 0; - private touchGestureLastCoordinates_: [number, number][] = []; // last x,y coordinates of each touch - - private touchZoom_ : any = false; - private touchTranslation_ : any = false; - - private ViewportSetSize : Function; - private ViewportRender : Function; - private ViewportMouseDown : Function; - private ViewportMouseMove : Function; - private ViewportMouseUp : Function; - private ViewportMouseEnter : Function; - private ViewportMouseLeave : Function; - private ViewportMouseWheel : Function; - private ViewportKeyPressed : Function; - private ViewportTouchStart : Function; - private ViewportTouchMove : Function; - private ViewportTouchEnd : Function; - - private pimpl_ : any; // Private pointer to the underlying WebAssembly C++ object - - public constructor(module: any, canvasId: string, cppViewport: any) { - - this.pimpl_ = cppViewport; - WasmViewport.viewportsMapByCppHandle_[this.pimpl_] = this; - WasmViewport.viewportsMapByCanvasId_[canvasId] = this; - - this.module_ = module; - this.canvasId_ = canvasId; - this.htmlCanvas_ = document.getElementById(this.canvasId_) as HTMLCanvasElement; - if (this.htmlCanvas_ == null) { - Logger.defaultLogger.error("Can not create WasmViewport, did not find the canvas whose id is '", this.canvasId_, "'"); - } - this.context_ = this.htmlCanvas_.getContext('2d'); - - this.ViewportSetSize = this.module_.cwrap('ViewportSetSize', null, [ 'number', 'number', 'number' ]); - this.ViewportRender = this.module_.cwrap('ViewportRender', null, [ 'number', 'number', 'number', 'number' ]); - this.ViewportMouseDown = this.module_.cwrap('ViewportMouseDown', null, [ 'number', 'number', 'number', 'number', 'number' ]); - this.ViewportMouseMove = this.module_.cwrap('ViewportMouseMove', null, [ 'number', 'number', 'number' ]); - this.ViewportMouseUp = this.module_.cwrap('ViewportMouseUp', null, [ 'number' ]); - this.ViewportMouseEnter = this.module_.cwrap('ViewportMouseEnter', null, [ 'number' ]); - this.ViewportMouseLeave = this.module_.cwrap('ViewportMouseLeave', null, [ 'number' ]); - this.ViewportMouseWheel = this.module_.cwrap('ViewportMouseWheel', null, [ 'number', 'number', 'number', 'number', 'number' ]); - this.ViewportKeyPressed = this.module_.cwrap('ViewportKeyPressed', null, [ 'number', 'number', 'string', 'number', 'number' ]); - this.ViewportTouchStart = this.module_.cwrap('ViewportTouchStart', null, [ 'number', 'number', 'number', 'number', 'number', 'number', 'number' ]); - this.ViewportTouchMove = this.module_.cwrap('ViewportTouchMove', null, [ 'number', 'number', 'number', 'number', 'number', 'number', 'number' ]); - this.ViewportTouchEnd = this.module_.cwrap('ViewportTouchEnd', null, [ 'number', 'number', 'number', 'number', 'number', 'number', 'number' ]); - } - - public GetCppViewport() : number { - return this.pimpl_; - } - - public static GetFromCppViewport(cppViewportHandle: number) : WasmViewport | null { - if (WasmViewport.viewportsMapByCppHandle_[cppViewportHandle] !== undefined) { - return WasmViewport.viewportsMapByCppHandle_[cppViewportHandle]; - } - Logger.defaultLogger.error("WasmViewport not found !"); - return null; - } - - public static GetFromCanvasId(canvasId: string) : WasmViewport | null { - if (WasmViewport.viewportsMapByCanvasId_[canvasId] !== undefined) { - return WasmViewport.viewportsMapByCanvasId_[canvasId]; - } - Logger.defaultLogger.error("WasmViewport not found !"); - return null; - } - - public static ResizeAll() { - for (let canvasId in WasmViewport.viewportsMapByCanvasId_) { - WasmViewport.viewportsMapByCanvasId_[canvasId].Resize(); - } - } - - public Redraw() { - if (this.imageData_ === null || - this.renderingBuffer_ === null || - this.ViewportRender(this.pimpl_, - this.imageData_.width, - this.imageData_.height, - this.renderingBuffer_) == 0) { - Logger.defaultLogger.error('The rendering has failed'); - } else { - // Create an accessor to the rendering buffer (i.e. create a - // "window" above the heap of the WASM module), then copy it to - // the ImageData object - this.imageData_.data.set(new Uint8ClampedArray( - this.module_.HEAPU8.buffer, - this.renderingBuffer_, - this.imageData_.width * this.imageData_.height * 4)); - - if (this.context_) { - this.context_.putImageData(this.imageData_, 0, 0); - } - } - } - - public Resize() { - if (this.imageData_ != null && - (this.imageData_.width != window.innerWidth || - this.imageData_.height != window.innerHeight)) { - this.imageData_ = null; - } - - // width/height is defined by the parent width/height - if (this.htmlCanvas_.parentElement) { - this.htmlCanvas_.width = this.htmlCanvas_.parentElement.offsetWidth; - this.htmlCanvas_.height = this.htmlCanvas_.parentElement.offsetHeight; - - Logger.defaultLogger.debug("resizing WasmViewport: ", this.htmlCanvas_.width, "x", this.htmlCanvas_.height); - - if (this.imageData_ === null && this.context_) { - this.imageData_ = this.context_.getImageData(0, 0, this.htmlCanvas_.width, this.htmlCanvas_.height); - this.ViewportSetSize(this.pimpl_, this.htmlCanvas_.width, this.htmlCanvas_.height); - - if (this.renderingBuffer_ != null) { - this.module_._free(this.renderingBuffer_); - } - - this.renderingBuffer_ = this.module_._malloc(this.imageData_.width * this.imageData_.height * 4); - } else { - this.ViewportSetSize(this.pimpl_, this.htmlCanvas_.width, this.htmlCanvas_.height); - } - - this.Redraw(); - } - } - - public Initialize() { - - // Force the rendering of the viewport for the first time - this.Resize(); - - var that : WasmViewport = this; - // Register an event listener to call the Resize() function - // each time the window is resized. - window.addEventListener('resize', function(event) { - that.Resize(); - }, false); - - this.htmlCanvas_.addEventListener('contextmenu', function(event) { - // Prevent right click on the canvas - event.preventDefault(); - }, false); - - this.htmlCanvas_.addEventListener('mouseleave', function(event) { - that.ViewportMouseLeave(that.pimpl_); - }); - - this.htmlCanvas_.addEventListener('mouseenter', function(event) { - that.ViewportMouseEnter(that.pimpl_); - }); - - this.htmlCanvas_.addEventListener('mousedown', function(event) { - var x = event.pageX - this.offsetLeft; - var y = event.pageY - this.offsetTop; - - that.ViewportMouseDown(that.pimpl_, event.button, x, y, 0 /* TODO detect modifier keys*/); - }); - - this.htmlCanvas_.addEventListener('mousemove', function(event) { - var x = event.pageX - this.offsetLeft; - var y = event.pageY - this.offsetTop; - that.ViewportMouseMove(that.pimpl_, x, y); - }); - - this.htmlCanvas_.addEventListener('mouseup', function(event) { - that.ViewportMouseUp(that.pimpl_); - }); - - window.addEventListener('keydown', function(event) { - var keyChar: string | null = event.key; - var keyCode = event.keyCode - if (keyChar.length == 1) { - keyCode = 0; // maps to OrthancStone::KeyboardKeys_Generic - } else { - keyChar = null; - } -// console.log("key: ", keyCode, keyChar); - that.ViewportKeyPressed(that.pimpl_, keyCode, keyChar, event.shiftKey, event.ctrlKey, event.altKey); - }); - - this.htmlCanvas_.addEventListener('wheel', function(event) { - var x = event.pageX - this.offsetLeft; - var y = event.pageY - this.offsetTop; - that.ViewportMouseWheel(that.pimpl_, event.deltaY, x, y, event.ctrlKey); - event.preventDefault(); - }, {passive: false}); // must not be passive if calling event.preventDefault, ie to cancel scroll or zoom of the whole interface - - this.htmlCanvas_.addEventListener('touchstart', function(event: TouchEvent) { - // don't propagate events to the whole body (this could zoom the entire page instead of zooming the viewport) - event.preventDefault(); - event.stopPropagation(); - - // TODO: find a way to pass the coordinates as an array between JS and C++ - var x0 = 0; - var y0 = 0; - var x1 = 0; - var y1 = 0; - var x2 = 0; - var y2 = 0; - if (event.targetTouches.length > 0) { - x0 = event.targetTouches[0].pageX; - y0 = event.targetTouches[0].pageY; - } - if (event.targetTouches.length > 1) { - x1 = event.targetTouches[1].pageX; - y1 = event.targetTouches[1].pageY; - } - if (event.targetTouches.length > 2) { - x2 = event.targetTouches[2].pageX; - y2 = event.targetTouches[2].pageY; - } - - that.ViewportTouchStart(that.pimpl_, event.targetTouches.length, x0, y0, x1, y1, x2, y2); - }, {passive: false}); // must not be passive if calling event.preventDefault, ie to cancel scroll or zoom of the whole interface - - this.htmlCanvas_.addEventListener('touchend', function(event) { - // don't propagate events to the whole body (this could zoom the entire page instead of zooming the viewport) - event.preventDefault(); - event.stopPropagation(); - - // TODO: find a way to pass the coordinates as an array between JS and C++ - var x0 = 0; - var y0 = 0; - var x1 = 0; - var y1 = 0; - var x2 = 0; - var y2 = 0; - if (event.targetTouches.length > 0) { - x0 = event.targetTouches[0].pageX; - y0 = event.targetTouches[0].pageY; - } - if (event.targetTouches.length > 1) { - x1 = event.targetTouches[1].pageX; - y1 = event.targetTouches[1].pageY; - } - if (event.targetTouches.length > 2) { - x2 = event.targetTouches[2].pageX; - y2 = event.targetTouches[2].pageY; - } - - that.ViewportTouchEnd(that.pimpl_, event.targetTouches.length, x0, y0, x1, y1, x2, y2); - }); - - this.htmlCanvas_.addEventListener('touchmove', function(event: TouchEvent) { - - // don't propagate events to the whole body (this could zoom the entire page instead of zooming the viewport) - event.preventDefault(); - event.stopPropagation(); - - - // TODO: find a way to pass the coordinates as an array between JS and C++ - var x0 = 0; - var y0 = 0; - var x1 = 0; - var y1 = 0; - var x2 = 0; - var y2 = 0; - if (event.targetTouches.length > 0) { - x0 = event.targetTouches[0].pageX; - y0 = event.targetTouches[0].pageY; - } - if (event.targetTouches.length > 1) { - x1 = event.targetTouches[1].pageX; - y1 = event.targetTouches[1].pageY; - } - if (event.targetTouches.length > 2) { - x2 = event.targetTouches[2].pageX; - y2 = event.targetTouches[2].pageY; - } - - that.ViewportTouchMove(that.pimpl_, event.targetTouches.length, x0, y0, x1, y1, x2, y2); - return; - - }, {passive: false}); // must not be passive if calling event.preventDefault, ie to cancel scroll or zoom of the whole interface - } - - public ResetTouch() { - if (this.touchTranslation_ || - this.touchZoom_) { - this.ViewportMouseUp(this.pimpl_); - } - - this.touchTranslation_ = false; - this.touchZoom_ = false; - } - - public GetTouchTranslation(event: any) { - var touch = event.targetTouches[0]; - return [ - touch.pageX, - touch.pageY - ]; - } - - public GetTouchZoom(event: any) { - var touch1 = event.targetTouches[0]; - var touch2 = event.targetTouches[1]; - var dx = (touch1.pageX - touch2.pageX); - var dy = (touch1.pageY - touch2.pageY); - var d = Math.sqrt(dx * dx + dy * dy); - return [ - (touch1.pageX + touch2.pageX) / 2.0, - (touch1.pageY + touch2.pageY) / 2.0, - d - ]; - } - -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/Graveyard/playground.ts Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,259 +0,0 @@ -/* - 1 2 3 4 5 6 7 -12345678901234567890123456789012345678901234567890123456789012345678901234567890 -*/ - -namespace VsolStuff -{ - enum EnumMonth0 - { - January, - February, - March - }; - - // interface Serializer - // { - // Serialize(value: number): string; - // Serialize(value: string): string; - // Serialize(value: EnumMonth0): string; - // }; - function printf(value: any):void - { - console.log(value) - } - - // function StoneSerialize(value: string) : string; - // function StoneSerialize(value: number) : string; - // function StoneSerialize(value: EnumMonth0) : string; - function StoneSerialize<T>(value: T[]) : string; - - function StoneSerialize<T>(value: T[] | EnumMonth0) : string - { - let valueType = typeof value; - printf(`About to serialize value. Type is ${valueType}`) - printf(`About to serialize value. Type is ${typeof value}`) - return "Choucroute"; - } - - function main():number - { - enum Color {Red = 1, Green = 2, Blue = 4} - let color: Color = Color.Green; - printf("---------------------------"); - printf(`typeof color: ${typeof color}`); - printf("---------------------------"); - let colors: Color[] = [] - colors.push(Color.Green); - colors.push(Color.Red); - printf(`typeof colors: ${typeof colors}`); - printf(`Array.isArray(colors): ${Array.isArray(colors)}`); - printf("---------------------------"); - - - let toto:EnumMonth0[] = []; - - toto.push(EnumMonth0.February); - toto.push(EnumMonth0.March); - - printf(JSON.stringify(toto)); - - return 0; - - } - - main() - -// string StoneSerialize_number(int32_t value) -// { - -// Json::Value result(value); -// return result; -// } - -// Json::Value StoneSerialize(double value) -// { -// Json::Value result(value); -// return result; -// } - -// Json::Value StoneSerialize(bool value) -// { -// Json::Value result(value); -// return result; -// } - -// Json::Value StoneSerialize(const std::string& value) -// { -// // the following is better than -// Json::Value result(value.data(),value.data()+value.size()); -// return result; -// } - -// template<typename T> -// Json::Value StoneSerialize(const std::map<std::string,T>& value) -// { -// Json::Value result(Json::objectValue); - -// for (std::map<std::string, T>::const_iterator it = value.cbegin(); -// it != value.cend(); ++it) -// { -// // it->first it->second -// result[it->first] = StoneSerialize(it->second); -// } -// return result; -// } - -// template<typename T> -// Json::Value StoneSerialize(const std::vector<T>& value) -// { -// Json::Value result(Json::arrayValue); -// for (size_t i = 0; i < value.size(); ++i) -// { -// result.append(StoneSerialize(value[i])); -// } -// return result; -// } - -// enum EnumMonth0 -// { -// January, -// February, -// March -// }; - -// std::string ToString(EnumMonth0 value) -// { -// switch(value) -// { -// case January: -// return "January"; -// case February: -// return "February"; -// case March: -// return "March"; -// default: -// { -// std::stringstream ss; -// ss << "Unrecognized EnumMonth0 value (" << static_cast<int64_t>(value) << ")"; -// throw std::runtime_error(ss.str()); -// } -// } -// } - -// void FromString(EnumMonth0& value, std::string strValue) -// { -// if (strValue == "January" || strValue == "EnumMonth0_January") -// { -// return January; -// } -// else if (strValue == "February" || strValue == "EnumMonth0_February") -// { -// return February; -// } -// #error Not implemented yet -// } - -// Json::Value StoneSerialize(const EnumMonth0& value) -// { -// return StoneSerialize(ToString(value)); -// } -// struct Message1 -// { -// int32_t a; -// std::string b; -// EnumMonth0 c; -// bool d; -// }; - -// struct Message2 -// { -// std::string toto; -// std::vector<Message1> tata; -// std::vector<std::string> tutu; -// std::map<std::string, std::string> titi; -// std::map<std::string, Message1> lulu; -// }; - -// Json::Value StoneSerialize(const Message1& value) -// { -// Json::Value result(Json::objectValue); -// result["a"] = StoneSerialize(value.a); -// result["b"] = StoneSerialize(value.b); -// result["c"] = StoneSerialize(value.c); -// result["d"] = StoneSerialize(value.d); -// return result; -// } - -// Json::Value StoneSerialize(const Message2& value) -// { -// Json::Value result(Json::objectValue); -// result["toto"] = StoneSerialize(value.toto); -// result["tata"] = StoneSerialize(value.tata); -// result["tutu"] = StoneSerialize(value.tutu); -// result["titi"] = StoneSerialize(value.titi); -// result["lulu"] = StoneSerialize(value.lulu); -// return result; -// } -// } - -// int main() -// { -// VsolStuff::Message1 msg1_0; -// msg1_0.a = 42; -// msg1_0.b = "Benjamin"; -// msg1_0.c = VsolStuff::January; -// msg1_0.d = true; - -// VsolStuff::Message1 msg1_1; -// msg1_1.a = 43; -// msg1_1.b = "Sandrine"; -// msg1_1.c = VsolStuff::March; -// msg1_0.d = false; - -// // std::string toto; -// // std::vector<Message1> tata; -// // std::vector<std::string> tutu; -// // std::map<int32_t, std::string> titi; -// // std::map<int32_t, Message1> lulu; - -// VsolStuff::Message2 msg2_0; -// msg2_0.toto = "Prout zizi"; -// msg2_0.tata.push_back(msg1_0); -// msg2_0.tata.push_back(msg1_1); -// msg2_0.tutu.push_back("Mercadet"); -// msg2_0.tutu.push_back("Poisson"); -// msg2_0.titi["44"] = "key 44"; -// msg2_0.titi["45"] = "key 45"; -// msg2_0.lulu["54"] = msg1_1; -// msg2_0.lulu["55"] = msg1_0; -// auto result = VsolStuff::StoneSerialize(msg2_0); -// auto resultStr = result.toStyledString(); - -// Json::Value readValue; - -// Json::CharReaderBuilder builder; -// Json::CharReader* reader = builder.newCharReader(); -// std::string errors; - -// bool ok = reader->parse( -// resultStr.c_str(), -// resultStr.c_str() + resultStr.size(), -// &readValue, -// &errors -// ); -// delete reader; - -// if (!ok) -// { -// std::stringstream ss; -// ss << "Json parsing error: " << errors; -// throw std::runtime_error(ss.str()); -// } -// std::cout << readValue.get("toto", "Default Value").asString() << std::endl; -// return 0; -// } - - -} -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/Graveyard/playground2.ts Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -class Greeter { - greeting: string; - constructor(message: string) { - this.greeting = message; - } - greet() { - return "Hello, " + this.greeting; - } -} -enum Color { - Red, - Green, - Blue, -}; - -function ColorToString(value: Color) -{ - switch (value) - { - case Color.Red: - return "Red"; - case Color.Green: - return "Green"; - case Color.Blue: - return "Blue"; - default: - throw new Error(`Unrecognized Color value(${value})`); - } -} - -let color: Color = Color.Red; - -document.body.textContent = "<p>---------------------</p>" -document.body.textContent += "<p>********************************</p>" - -class TestMessage { - s1: string; - s2: Array<string>; - s3: Array<Array<string>>; - s4: Map<string, number>; - s5: Map<number, Array<string>>; - s6: Color; - s7: boolean; -} - -let tm = new TestMessage(); -tm.s2 = new Array<string>() -tm.s2.push("toto"); -tm.s2.push("toto2"); -tm.s2.push("toto3"); -tm.s4 = new Map<string, number>(); -tm.s4["toto"] = 42; -tm.s4["toto"] = 1999; -tm.s4["tatata"] = 1999; -tm.s6 = Color.Red; -tm.s7 = true - -let txt = JSON.stringify(tm) -let txtElem = document.createElement('textarea'); -txtElem.value = txt; - -document.body.appendChild(txtElem); - -let greeter = new Greeter("world"); - -let button = document.createElement('button'); -button.textContent = "Say Hello"; -button.onclick = function() { - alert(greeter.greet()); -} - -document.body.appendChild(button);
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/Graveyard/playground3.ts Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,275 +0,0 @@ -/* - 1 2 3 4 5 6 7 -12345678901234567890123456789012345678901234567890123456789012345678901234567890 -*/ - -namespace VsolStuff222 { - export enum EnumMonth0 { - January, - February, - March - }; - - export class Message1 { - a: number; - b: string; - c: EnumMonth0; - d: boolean; - public StoneSerialize(): string { - let container: object = {}; - container['type'] = 'VsolStuff.Message1'; - container['value'] = this; - return JSON.stringify(container); - } - }; - - export class Message2 { - toto: string; - tata: Message1[]; - tutu: string[]; - titi: Map<string, string>; - lulu: Map<string, Message1>; - - public StoneSerialize(): string { - let container: object = {}; - container['type'] = 'VsolStuff.Message2'; - container['value'] = this; - return JSON.stringify(container); - } - }; -} - -function printf(value: any): void { - console.log(value) -} - -function main(): number { - - let msg1_0 = new VsolStuff.Message1(); - msg1_0.a = 42; - msg1_0.b = "Benjamin"; - msg1_0.c = VsolStuff.EnumMonth0.January; - msg1_0.d = true; - - let msg1_1 = new VsolStuff.Message1(); - msg1_1.a = 43; - msg1_1.b = "Sandrine"; - msg1_1.c = VsolStuff.EnumMonth0.March; - msg1_0.d = false; - - // std::string toto; - // std::vector<Message1> tata; - // std::vector<std::string> tutu; - // std::map<int32_t, std::string> titi; - // std::map<int32_t, Message1> lulu; - - let msg2_0 = new VsolStuff.Message2(); - msg2_0.toto = "Prout zizi"; - msg2_0.tata = new Array<VsolStuff.Message1>(); - msg2_0.tata.push(msg1_0); - msg2_0.tata.push(msg1_1); - msg2_0.tutu.push("Mercadet"); - msg2_0.tutu.push("Poisson");ing - msg2_0.titi["44"] = "key 44"; - msg2_0.titi["45"] = "key 45"; - msg2_0.lulu["54"] = msg1_1; - msg2_0.lulu["55"] = msg1_0; - let result:string = VsolStuff.StoneSerialize(msg2_0); - return 0; -} - -main() - -// string StoneSerialize_number(int32_t value) -// { - -// Json::Value result(value); -// return result; -// } - -// Json::Value StoneSerialize(double value) -// { -// Json::Value result(value); -// return result; -// } - -// Json::Value StoneSerialize(bool value) -// { -// Json::Value result(value); -// return result; -// } - -// Json::Value StoneSerialize(const std::string& value) -// { -// // the following is better than -// Json::Value result(value.data(),value.data()+value.size()); -// return result; -// } - -// template<typename T> -// Json::Value StoneSerialize(const std::map<std::string,T>& value) -// { -// Json::Value result(Json::objectValue); - -// for (std::map<std::string, T>::const_iterator it = value.cbegin(); -// it != value.cend(); ++it) -// { -// // it->first it->second -// result[it->first] = StoneSerialize(it->second); -// } -// return result; -// } - -// template<typename T> -// Json::Value StoneSerialize(const std::vector<T>& value) -// { -// Json::Value result(Json::arrayValue); -// for (size_t i = 0; i < value.size(); ++i) -// { -// result.append(StoneSerialize(value[i])); -// } -// return result; -// } - -// enum EnumMonth0 -// { -// January, -// February, -// March -// }; - -// std::string ToString(EnumMonth0 value) -// { -// switch(value) -// { -// case January: -// return "January"; -// case February: -// return "February"; -// case March: -// return "March"; -// default: -// { -// std::stringstream ss; -// ss << "Unrecognized EnumMonth0 value (" << static_cast<int64_t>(value) << ")"; -// throw std::runtime_error(ss.str()); -// } -// } -// } - -// void FromString(EnumMonth0& value, std::string strValue) -// { -// if (strValue == "January" || strValue == "EnumMonth0_January") -// { -// return January; -// } -// else if (strValue == "February" || strValue == "EnumMonth0_February") -// { -// return February; -// } -// #error Not implemented yet -// } - -// Json::Value StoneSerialize(const EnumMonth0& value) -// { -// return StoneSerialize(ToString(value)); -// } -// struct Message1 -// { -// int32_t a; -// std::string b; -// EnumMonth0 c; -// bool d; -// }; - -// struct Message2 -// { -// std::string toto; -// std::vector<Message1> tata; -// std::vector<std::string> tutu; -// std::map<std::string, std::string> titi; -// std::map<std::string, Message1> lulu; -// }; - -// Json::Value StoneSerialize(const Message1& value) -// { -// Json::Value result(Json::objectValue); -// result["a"] = StoneSerialize(value.a); -// result["b"] = StoneSerialize(value.b); -// result["c"] = StoneSerialize(value.c); -// result["d"] = StoneSerialize(value.d); -// return result; -// } - -// Json::Value StoneSerialize(const Message2& value) -// { -// Json::Value result(Json::objectValue); -// result["toto"] = StoneSerialize(value.toto); -// result["tata"] = StoneSerialize(value.tata); -// result["tutu"] = StoneSerialize(value.tutu); -// result["titi"] = StoneSerialize(value.titi); -// result["lulu"] = StoneSerialize(value.lulu); -// return result; -// } -// } - -// int main() -// { -// VsolStuff::Message1 msg1_0; -// msg1_0.a = 42; -// msg1_0.b = "Benjamin"; -// msg1_0.c = VsolStuff::January; -// msg1_0.d = true; - -// VsolStuff::Message1 msg1_1; -// msg1_1.a = 43; -// msg1_1.b = "Sandrine"; -// msg1_1.c = VsolStuff::March; -// msg1_0.d = false; - -// // std::string toto; -// // std::vector<Message1> tata; -// // std::vector<std::string> tutu; -// // std::map<int32_t, std::string> titi; -// // std::map<int32_t, Message1> lulu; - -// VsolStuff::Message2 msg2_0; -// msg2_0.toto = "Prout zizi"; -// msg2_0.tata.push_back(msg1_0); -// msg2_0.tata.push_back(msg1_1); -// msg2_0.tutu.push_back("Mercadet"); -// msg2_0.tutu.push_back("Poisson"); -// msg2_0.titi["44"] = "key 44"; -// msg2_0.titi["45"] = "key 45"; -// msg2_0.lulu["54"] = msg1_1; -// msg2_0.lulu["55"] = msg1_0; -// auto result = VsolStuff::StoneSerialize(msg2_0); -// auto resultStr = result.toStyledString(); - -// Json::Value readValue; - -// Json::CharReaderBuilder builder; -// Json::CharReader* reader = builder.newCharReader(); -// std::string errors; - -// bool ok = reader->parse( -// resultStr.c_str(), -// resultStr.c_str() + resultStr.size(), -// &readValue, -// &errors -// ); -// delete reader; - -// if (!ok) -// { -// std::stringstream ss; -// ss << "Json parsing error: " << errors; -// throw std::runtime_error(ss.str()); -// } -// std::cout << readValue.get("toto", "Default Value").asString() << std::endl; -// return 0; -// } - - -} -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/Graveyard/playground4.py Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -testYaml = """ -enum SomeEnum: - - january - - feb - -struct Message0: - a: string - -struct Message1: - a: string - b: int32 - c: vector<Message0> - d: SomeEnum = january - e: SomeEnum= january - f: SomeEnum=january - g: SomeEnum =january - - -# github.com/AlDanial/cloc -header2 : - cloc_version : 1.67 - elapsed_seconds : int32_t - -header : - cloc_version : 1.67 - elapsed_seconds : int32_t - cloc_url : vector<map<string,int32>> - n_files : 1 - n_lines : 3 - files_per_second : 221.393718659277 - lines_per_second : 664.181155977831 - report_file : IDL.idl.yaml -IDL : - nFiles: 1 - blank: 0 - comment: 2 - code: 1 -EnumSUM: - - aaa - - bbb - -SUM: - blank: 0 - comment: 2 - code: 1 - nFiles: 1 -""" - -import yaml - -b = yaml.load(testYaml) -print(b) - -c = { - 'enum SomeEnum': ['january', 'feb'], - 'struct Message0': {'a': 'string'}, - 'struct Message1': { - 'a': 'string', - 'b': 'int32', - 'c': 'vector<Message0>', - 'd': 'vector<map<string,int32>>', - 'e': 'SomeEnum= january', - 'f': 'SomeEnum=january', - 'g': 'SomeEnum =january' - }, -} - -print(c) \ No newline at end of file
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/Graveyard/runts.ps1 Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -# echo "+----------------------+" -# echo "| playground.ts |" -# echo "+----------------------+" - -# tsc -t ES2015 .\playground.ts; node .\playground.js - -# echo "+----------------------+" -# echo "| playground3.ts |" -# echo "+----------------------+" - -# tsc -t ES2015 .\playground3.ts; node .\playground3.js - -echo "+----------------------+" -echo "| stonegen |" -echo "+----------------------+" - -if(-not (test-Path "build")) { - mkdir "build" -} - -echo "Generate the TS and CPP wrapper... (to build/)" -python stonegentool.py -o "." test_data/test1.yaml -if($LASTEXITCODE -ne 0) { - Write-Error ("Code generation failed!") - exit $LASTEXITCODE -} - -echo "Compile the TS wrapper to JS... (in build/)" -tsc --module commonjs --sourceMap -t ES2015 --outDir "build/" VsolMessages_generated.ts -if($LASTEXITCODE -ne 0) { - Write-Error ("Code compilation failed!") - exit $LASTEXITCODE -} - -echo "Compile the test app..." -tsc --module commonjs --sourceMap -t ES2015 --outDir "build/" test_stonegen.ts -if($LASTEXITCODE -ne 0) { - Write-Error ("Code compilation failed!") - exit $LASTEXITCODE -} - -browserify "build/test_stonegen.js" "build/VsolMessages_generated.js" -o "build_browser/test_stonegen_fused.js" - -cp .\test_stonegen.html .\build_browser\ - -echo "Run the test app..." -Push-Location -cd build_browser -node .\test_stonegen_fused.js -Pop-Location -if($LASTEXITCODE -ne 0) { - Write-Error ("Code execution failed!") - exit $LASTEXITCODE -} - - -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/Graveyard/test_stonegen.html Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -<script type="text/javascript" src="test_stonegen_fused.js"></script>
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/Graveyard/test_stonegen.ts Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,206 +0,0 @@ -import * as VsolMessages from "./VsolMessages_generated"; - -function TEST_StoneGen_SerializeComplex() { - let msg1_0 = new VsolMessages.Message1(); - msg1_0.a = 42; - msg1_0.b = "Benjamin"; - msg1_0.c = VsolMessages.EnumMonth0.January; - msg1_0.d = true; - let msg1_1 = new VsolMessages.Message1(); - msg1_1.a = 43; - msg1_1.b = "Sandrine"; - msg1_1.c = VsolMessages.EnumMonth0.March; - msg1_0.d = false; - let result1_0 = msg1_0.StoneSerialize(); - let resultStr1_0 = JSON.stringify(result1_0); - let result1_1 = msg1_1.StoneSerialize(); - let resultStr1_1 = JSON.stringify(result1_1); - // std::string toto; - // std::vector<Message1> tata; - // std::vector<std::string> tutu; - // std::map<int32_t, std::string> titi; - // std::map<int32_t, Message1> lulu; - let msg2_0 = new VsolMessages.Message2(); - msg2_0.toto = "Prout zizi"; - msg2_0.tata.push(msg1_0); - msg2_0.tata.push(msg1_1); - msg2_0.tutu.push("Mercadet"); - msg2_0.tutu.push("Poisson"); - msg2_0.titi["44"] = "key 44"; - msg2_0.titi["45"] = "key 45"; - msg2_0.lulu["54"] = msg1_1; - msg2_0.lulu["55"] = msg1_0; - let result2 = msg2_0.StoneSerialize(); - let resultStr2 = JSON.stringify(result2); - let refResult2 = `{ -"type" : "VsolMessages.Message2", -"value" : -{ - "lulu" : - { - "54" : - { - "a" : 43, - "b" : "Sandrine", - "c" : 2, - "d" : true - }, - "55" : - { - "a" : 42, - "b" : "Benjamin", - "c" : 0, - "d" : false - } - }, - "tata" : - [ - { - "a" : 42, - "b" : "Benjamin", - "c" : 0, - "d" : false - }, - { - "a" : 43, - "b" : "Sandrine", - "c" : 2, - "d" : true - } - ], - "titi" : - { - "44" : "key 44", - "45" : "key 45" - }, - "toto" : "Prout zizi", - "tutu" : - [ - "Mercadet", - "Poisson" - ] -} -} -`; - let refResult2Obj = JSON.parse(refResult2); - let resultStr2Obj = JSON.parse(resultStr2); - if (false) { - if (refResult2Obj !== resultStr2Obj) { - console.log("Results are different!"); - console.log(`refResult2Obj['value']['lulu']['54'] = ${refResult2Obj['value']['lulu']['54']}`); - console.log(`refResult2Obj['value']['lulu']['54']['a'] = ${refResult2Obj['value']['lulu']['54']['a']}`); - console.log("************************************************************"); - console.log("** REFERENCE OBJ **"); - console.log("************************************************************"); - console.log(refResult2Obj); - console.log("************************************************************"); - console.log("** ACTUAL OBJ **"); - console.log("************************************************************"); - console.log(resultStr2Obj); - console.log("************************************************************"); - console.log("** REFERENCE **"); - console.log("************************************************************"); - console.log(refResult2); - console.log("************************************************************"); - console.log("** ACTUAL **"); - console.log("************************************************************"); - console.log(resultStr2); - throw new Error("Wrong serialization"); - } - } - let refResultValue = JSON.parse(resultStr2); - console.log(refResultValue); -} -class MyDispatcher { - message1: VsolMessages.Message1; - message2: VsolMessages.Message2; - - HandleMessage1(value: VsolMessages.Message1) { - this.message1 = value; - return true; - } - HandleMessage2(value: VsolMessages.Message2) { - this.message2 = value; - return true; - } - HandleA(value) { - return true; - } - HandleB(value) { - return true; - } - HandleC(value) { - return true; - } -} -; -function TEST_StoneGen_DeserializeOkAndNok() { - let serializedMessage = `{ -"type" : "VsolMessages.Message2", -"value" : -{ - "lulu" : - { - "54" : - { - "a" : 43, - "b" : "Sandrine", - "c" : 2, - "d" : true - }, - "55" : - { - "a" : 42, - "b" : "Benjamin", - "c" : 0, - "d" : false - } - }, - "tata" : - [ - { - "a" : 42, - "b" : "Benjamin", - "c" : 0, - "d" : false - }, - { - "a" : 43, - "b" : "Sandrine", - "c" : 2, - "d" : true - } - ], - "titi" : - { - "44" : "key 44", - "45" : "key 45" - }, - "toto" : "Prout zizi", - "tutu" : - [ - "Mercadet", - "Poisson" - ] -} -}`; - let myDispatcher = new MyDispatcher(); - let ok = VsolMessages.StoneDispatchToHandler(serializedMessage, myDispatcher); - if (!ok) { - throw Error("Error when dispatching message!"); - } - if (myDispatcher.message1 != undefined) { - throw Error("(myDispatcher.Message1 != undefined)"); - } - if (myDispatcher.message2 == undefined) { - throw Error("(myDispatcher.Message2 == undefined)"); - } - console.log("TEST_StoneGen_DeserializeOkAndNok: OK!"); -} -function main() { - console.log("Entering main()"); - TEST_StoneGen_SerializeComplex(); - TEST_StoneGen_DeserializeOkAndNok(); - return 0; -} -console.log(`Exit code is: ${main()}`); \ No newline at end of file
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/Graveyard/tsconfig.json Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -{ - // "extends": "../../../../../orthanc-stone/Platforms/Wasm/tsconfig-stone", - "compilerOptions": { - // "outFile": "../../../WebApplication-build/to-embed/app.js", - // "module": "system", - // "sourceMap": false, - "lib": [ - "es2017", - "es2017", - "dom", - "dom.iterable" - ] - }, - "include": [ - // "commands/*.ts", - // "logger.ts", - // "app.ts", - // "main.ts", - // "ui.ts", - // "popup.ts" - ] -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/README.md Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -Requirements ----------------- - -Install Node and npm. - -Then: -- `npm install browserify` -- `npm install typescript` -- `npm install tsify` - -`testCppHandler` contains a C++ project that produces an executable -slurping a set of text files representing messages defined against -the `test_data/testTestStoneCodeGen.yaml' schema and dumping them to `cout`. - -'testWasmIntegrated` contains a small Web app demonstrating the -interaction between TypeScript and C++ in WASM. -source ~/apps/emsdk/emsdk_env.sh - - -Install Python and the following packages `pip install pyyaml yamlloader jinja2`
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/stonegentool.py Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,605 +0,0 @@ -import json -import yaml -import re -import os -import sys -from jinja2 import Template -from io import StringIO -import time -import datetime -import yamlloader - -""" - 1 2 3 4 5 6 7 -12345678901234567890123456789012345678901234567890123456789012345678901234567890 -""" - -# see https://stackoverflow.com/a/2504457/2927708 -def trim(docstring): - if not docstring: - return '' - # Convert tabs to spaces (following the normal Python rules) - # and split into a list of lines: - lines = docstring.expandtabs().splitlines() - # Determine minimum indentation (first line doesn't count): - indent = sys.maxsize - for line in lines[1:]: - stripped = line.lstrip() - if stripped: - indent = min(indent, len(line) - len(stripped)) - # Remove indentation (first line is special): - trimmed = [lines[0].strip()] - if indent < sys.maxsize: - for line in lines[1:]: - trimmed.append(line[indent:].rstrip()) - # Strip off trailing and leading blank lines: - while trimmed and not trimmed[-1]: - trimmed.pop() - while trimmed and not trimmed[0]: - trimmed.pop(0) - # Return a single string: - return '\n'.join(trimmed) - -class JsonHelpers: - """A set of utilities to perform JSON operations""" - - @staticmethod - def removeCommentsFromJsonContent(string): - """ - Remove comments from a JSON file - - Comments are not allowed in JSON but, i.e., Orthanc configuration files - contains C++ like comments that we need to remove before python can - parse the file - """ - # remove all occurrence streamed comments (/*COMMENT */) from string - string = re.sub(re.compile("/\*.*?\*/", re.DOTALL), "", string) - - # remove all occurrence singleline comments (//COMMENT\n ) from string - string = re.sub(re.compile("//.*?\n"), "", string) - - return string - - @staticmethod - def loadJsonWithComments(path): - """ - Reads a JSON file that may contain C++ like comments - """ - with open(path, "r") as fp: - fileContent = fp.read() - fileContent = JsonHelpers.removeCommentsFromJsonContent(fileContent) - return json.loads(fileContent) - -class FieldDefinition: - - def __init__(self, name: str, type: str, defaultValue: str): - self.name = name - self.type = type - self.defaultValue = defaultValue - - @staticmethod - def fromKeyValue(key: str, value: str): - - if "=" in value: - splitValue = value.split(sep="=") - type = splitValue[0].strip(" ") - defaultValue = splitValue[1].strip(" ") - else: - type = value - defaultValue = None - - return FieldDefinition(name = key, type = type, defaultValue = defaultValue) - - -def LoadSchemaFromJson(filePath): - return JsonHelpers.loadJsonWithComments(filePath) - -def CanonToCpp(canonicalTypename): - # C++: prefix map vector and string with std::map, std::vector and - # std::string - # replace int32... by int32_t... - # replace float32 by float - # replace float64 by double - retVal = canonicalTypename - retVal = retVal.replace("map", "std::map") - retVal = retVal.replace("vector", "std::vector") - retVal = retVal.replace("set", "std::set") - retVal = retVal.replace("string", "std::string") - #uint32 and uint64 are handled by int32 and uint32 (because search and replace are done as partial words) - retVal = retVal.replace("int32", "int32_t") - retVal = retVal.replace("int64", "int64_t") - retVal = retVal.replace("float32", "float") - retVal = retVal.replace("float64", "double") - retVal = retVal.replace("json", "Json::Value") - return retVal - -def CanonToTs(canonicalTypename): - # TS: replace vector with Array and map with Map - # string remains string - # replace int32... by number - # replace float32... by number - retVal = canonicalTypename - retVal = retVal.replace("map", "Map") - retVal = retVal.replace("vector", "Array") - retVal = retVal.replace("set", "Set") - retVal = retVal.replace("uint32", "number") - retVal = retVal.replace("uint64", "number") - retVal = retVal.replace("int32", "number") - retVal = retVal.replace("int64", "number") - retVal = retVal.replace("float32", "number") - retVal = retVal.replace("float64", "number") - retVal = retVal.replace("bool", "boolean") - retVal = retVal.replace("json", "Object") - return retVal - -def NeedsTsConstruction(enums, tsType): - if tsType == 'boolean': - return False - elif tsType == 'number': - return False - elif tsType == 'string': - return False - else: - enumNames = [] - for enum in enums: - enumNames.append(enum['name']) - if tsType in enumNames: - return False - return True - -def NeedsCppConstruction(canonTypename): - return False - -def DefaultValueToTs(enums, field:FieldDefinition): - tsType = CanonToTs(field.type) - - enumNames = [] - for enum in enums: - enumNames.append(enum['name']) - - if tsType in enumNames: - return tsType + "." + field.defaultValue - else: - return field.defaultValue - -def DefaultValueToCpp(root, enums, field:FieldDefinition): - cppType = CanonToCpp(field.type) - - enumNames = [] - for enum in enums: - enumNames.append(enum['name']) - - if cppType in enumNames: - return root + "::" + cppType + "_" + field.defaultValue - else: - return field.defaultValue - -def RegisterTemplateFunction(template,func): - """Makes a function callable by a jinja2 template""" - template.globals[func.__name__] = func - return func - -def MakeTemplate(templateStr): - template = Template(templateStr) - RegisterTemplateFunction(template,CanonToCpp) - RegisterTemplateFunction(template,CanonToTs) - RegisterTemplateFunction(template,NeedsTsConstruction) - RegisterTemplateFunction(template,NeedsCppConstruction) - RegisterTemplateFunction(template, DefaultValueToTs) - RegisterTemplateFunction(template, DefaultValueToCpp) - return template - -def MakeTemplateFromFile(templateFileName): - - with open(templateFileName, "r") as templateFile: - templateFileContents = templateFile.read() - return MakeTemplate(templateFileContents) - - -def EatToken(sentence): - """splits "A,B,C" into "A" and "B,C" where A, B and C are type names - (including templates) like "int32", "TotoTutu", or - "map<map<int32,vector<string>>,map<string,int32>>" """ - - if sentence.count("<") != sentence.count(">"): - raise Exception( - "Error in the partial template type list " + str(sentence) + "." - + " The number of < and > do not match!" - ) - - # the template level we're currently in - templateLevel = 0 - for i in range(len(sentence)): - if (sentence[i] == ",") and (templateLevel == 0): - return (sentence[0:i], sentence[i + 1 :]) - elif sentence[i] == "<": - templateLevel += 1 - elif sentence[i] == ">": - templateLevel -= 1 - return (sentence, "") - - -def SplitListOfTypes(typename): - """Splits something like - vector<string>,int32,map<string,map<string,int32>> - in: - - vector<string> - - int32 - map<string,map<string,int32>> - - This is not possible with a regex so - """ - stillStuffToEat = True - tokenList = [] - restOfString = typename - while stillStuffToEat: - firstToken, restOfString = EatToken(restOfString) - tokenList.append(firstToken) - if restOfString == "": - stillStuffToEat = False - return tokenList - - -templateRegex = \ - re.compile(r"([a-zA-Z0-9_]*[a-zA-Z0-9_]*)<([a-zA-Z0-9_,:<>]+)>") - - -def ParseTemplateType(typename): - """ If the type is a template like "SOMETHING<SOME<THING,EL<SE>>>", - then it returns (true,"SOMETHING","SOME<THING,EL<SE>>") - otherwise it returns (false,"","")""" - - # let's remove all whitespace from the type - # split without argument uses any whitespace string as separator - # (space, tab, newline, return or formfeed) - typename = "".join(typename.split()) - matches = templateRegex.match(typename) - if matches == None: - return (False, "", []) - else: - m = matches - assert len(m.groups()) == 2 - # we need to split with the commas that are outside of the - # defined types. Simply splitting at commas won't work - listOfDependentTypes = SplitListOfTypes(m.group(2)) - return (True, m.group(1), listOfDependentTypes) - -def GetStructFields(struct): - """This filters out the special metadata key from the struct fields""" - return [k for k in struct.keys() if k != '__handler'] - -def ComputeOrderFromTypeTree( - ancestors, - genOrder, - shortTypename, schema): - - if shortTypename in ancestors: - raise Exception( - "Cyclic dependency chain found: the last of " + str(ancestors) + - + " depends on " + str(shortTypename) + " that is already in the list." - ) - - if not (shortTypename in genOrder): - (isTemplate, _, dependentTypenames) = ParseTemplateType(shortTypename) - if isTemplate: - # if it is a template, it HAS dependent types... They can be - # anything (primitive, collection, enum, structs..). - # Let's process them! - for dependentTypename in dependentTypenames: - # childAncestors = ancestors.copy() NO TEMPLATE ANCESTOR!!! - # childAncestors.append(typename) - ComputeOrderFromTypeTree( - ancestors, genOrder, dependentTypename, schema - ) - else: - # If it is not template, we are only interested if it is a - # dependency that we must take into account in the dep graph, - # i.e., a struct. - if IsShortStructType(shortTypename, schema): - struct = schema[GetLongTypename(shortTypename, schema)] - # The keys in the struct dict are the member names - # The values in the struct dict are the member types - if struct: - # we reach this if struct is not None AND not empty - for field in GetStructFields(struct): - # we fill the chain of dependent types (starting here) - ancestors.append(shortTypename) - ComputeOrderFromTypeTree( - ancestors, genOrder, struct[field], schema) - # don't forget to restore it! - ancestors.pop() - - # now we're pretty sure our dependencies have been processed, - # we can start marking our code for generation (it might - # already have been done if someone referenced us earlier) - if not shortTypename in genOrder: - genOrder.append(shortTypename) - -# +-----------------------+ -# | Utility functions | -# +-----------------------+ - -def IsShortStructType(typename, schema): - fullStructName = "struct " + typename - return (fullStructName in schema) - -def GetLongTypename(shortTypename, schema): - if shortTypename.startswith("enum "): - raise RuntimeError('shortTypename.startswith("enum "):') - enumName = "enum " + shortTypename - isEnum = enumName in schema - - if shortTypename.startswith("struct "): - raise RuntimeError('shortTypename.startswith("struct "):') - structName = "struct " + shortTypename - isStruct = ("struct " + shortTypename) in schema - - if isEnum and isStruct: - raise RuntimeError('Enums and structs cannot have the same name') - - if isEnum: - return enumName - if isStruct: - return structName - -def IsTypename(fullName): - return (fullName.startswith("enum ") or fullName.startswith("struct ")) - -def IsEnumType(fullName): - return fullName.startswith("enum ") - -def IsStructType(fullName): - return fullName.startswith("struct ") - -def GetShortTypename(fullTypename): - if fullTypename.startswith("struct "): - return fullTypename[7:] - elif fullTypename.startswith("enum"): - return fullTypename[5:] - else: - raise RuntimeError \ - ('fullTypename should start with either "struct " or "enum "') - -def CheckSchemaSchema(schema): - if not "rootName" in schema: - raise Exception("schema lacks the 'rootName' key") - for name in schema.keys(): - if (not IsEnumType(name)) and (not IsStructType(name)) and \ - (name != 'rootName'): - raise RuntimeError \ - ('Type "' + str(name) + '" should start with "enum " or "struct "') - - # TODO: check enum fields are unique (in whole namespace) - # TODO: check struct fields are unique (in each struct) - # TODO: check that in the source schema, there are spaces after each colon - -nonTypeKeys = ['rootName'] -def GetTypesInSchema(schema): - """Returns the top schema keys that are actual type names""" - typeList = [k for k in schema if k not in nonTypeKeys] - return typeList - -# +-----------------------+ -# | Main processing logic | -# +-----------------------+ - -def ComputeRequiredDeclarationOrder(schema): - # sanity check - CheckSchemaSchema(schema) - - # we traverse the type dependency graph and we fill a queue with - # the required struct types, in a bottom-up fashion, to compute - # the declaration order - # The genOrder list contains the struct full names in the order - # where they must be defined. - # We do not care about the enums here... They do not depend upon - # anything and we'll handle them, in their original declaration - # order, at the start - genOrder = [] - for fullName in GetTypesInSchema(schema): - if IsStructType(fullName): - realName = GetShortTypename(fullName) - ancestors = [] - ComputeOrderFromTypeTree(ancestors, genOrder, realName, schema) - return genOrder - -def GetStructFields(fieldDict): - """Returns the regular (non __handler) struct fields""" - # the following happens for empty structs - if fieldDict == None: - return fieldDict - ret = {} - for k,v in fieldDict.items(): - if k != "__handler": - ret[k] = FieldDefinition.fromKeyValue(k, v) - if k.startswith("__") and k != "__handler": - raise RuntimeError("Fields starting with __ (double underscore) are reserved names!") - return ret - -def GetStructMetadata(fieldDict): - """Returns the __handler struct fields (there are default values that - can be overridden by entries in the schema - Not tested because it's a fail-safe: if something is broken in this, - dependent projects will not build.""" - metadataDict = {} - metadataDict['handleInCpp'] = False - metadataDict['handleInTypescript'] = False - - if fieldDict != None: - for k,v in fieldDict.items(): - if k.startswith("__") and k != "__handler": - raise RuntimeError("Fields starting with __ (double underscore) are reserved names") - if k == "__handler": - if type(v) == list: - for i in v: - if i == "cpp": - metadataDict['handleInCpp'] = True - elif i == "ts": - metadataDict['handleInTypescript'] = True - else: - raise RuntimeError("Error in schema. Allowed values for __handler are \"cpp\" or \"ts\"") - elif type(v) == str: - if v == "cpp": - metadataDict['handleInCpp'] = True - elif v == "ts": - metadataDict['handleInTypescript'] = True - else: - raise RuntimeError("Error in schema. Allowed values for __handler are \"cpp\" or \"ts\" (or a list of both)") - else: - raise RuntimeError("Error in schema. Allowed values for __handler are \"cpp\" or \"ts\" (or a list of both)") - return metadataDict - -def ProcessSchema(schema, genOrder): - # sanity check - CheckSchemaSchema(schema) - - # let's doctor the schema to clean it up a bit - # order DOES NOT matter for enums, even though it's a list - enums = [] - for fullName in schema.keys(): - if IsEnumType(fullName): - # convert "enum Toto" to "Toto" - typename = GetShortTypename(fullName) - enum = {} - enum['name'] = typename - assert(type(schema[fullName]) == list) - enum['fields'] = schema[fullName] # must be a list - enums.append(enum) - - # now that the order has been established, we actually store\ - # the structs in the correct order - # the structs are like: - # example = [ - # { - # "name": "Message1", - # "fields": { - # "someMember":"int32", - # "someOtherMember":"vector<string>" - # } - # }, - # { - # "name": "Message2", - # "fields": { - # "someMember":"int32", - # "someOtherMember22":"vector<Message1>" - # } - # } - # ] - - structs = [] - for i in range(len(genOrder)): - # this is already the short name - typename = genOrder[i] - fieldDict = schema["struct " + typename] - struct = {} - struct['name'] = typename - struct['fields'] = GetStructFields(fieldDict) - struct['__meta__'] = GetStructMetadata(fieldDict) - structs.append(struct) - - templatingDict = {} - templatingDict['enums'] = enums - templatingDict['structs'] = structs - templatingDict['rootName'] = schema['rootName'] - - return templatingDict - -# +-----------------------+ -# | Write to files | -# +-----------------------+ - -# def WriteStreamsToFiles(rootName: str, genc: Dict[str, StringIO]) \ -# -> None: -# pass - -def LoadSchema(fn): - # latin-1 is a trick, when we do NOT care about NON-ascii chars but - # we wish to avoid using a decoding error handler - # (see http://python-notes.curiousefficiency.org/en/latest/python3/text_file_processing.html#files-in-an-ascii-compatible-encoding-best-effort-is-acceptable) - # TL;DR: all 256 values are mapped to characters in latin-1 so the file - # contents never cause an error. - with open(fn, 'r', encoding='latin-1') as f: - schemaText = f.read() - assert(type(schemaText) == str) - return LoadSchemaFromString(schemaText = schemaText) - -def LoadSchemaFromString(schemaText:str): - # ensure there is a space after each colon. Otherwise, dicts could be - # erroneously recognized as an array of strings containing ':' - for i in range(len(schemaText)-1): - ch = schemaText[i] - nextCh = schemaText[i+1] - if ch == ':': - if not (nextCh == ' ' or nextCh == '\n'): - lineNumber = schemaText.count("\n",0,i) + 1 - raise RuntimeError("Error at line " + str(lineNumber) + " in the schema: colons must be followed by a space or a newline!") - schema = yaml.load(schemaText, Loader = yamlloader.ordereddict.SafeLoader) - return schema - -def GetTemplatingDictFromSchemaFilename(fn): - return GetTemplatingDictFromSchema(LoadSchema(fn)) - -def GetTemplatingDictFromSchema(schema): - genOrder = ComputeRequiredDeclarationOrder(schema) - templatingDict = ProcessSchema(schema, genOrder) - currentDT = datetime.datetime.now() - templatingDict['currentDatetime'] = str(currentDT) - return templatingDict - -# +-----------------------+ -# | ENTRY POINT | -# +-----------------------+ -def Process(schemaFile, outDir): - tdico = GetTemplatingDictFromSchemaFilename(schemaFile) - - tsTemplateFile = \ - os.path.join(os.path.dirname(__file__), 'template.in.ts.j2') - template = MakeTemplateFromFile(tsTemplateFile) - renderedTsCode = template.render(**tdico) - outputTsFile = os.path.join( \ - outDir,str(tdico['rootName']) + "_generated.ts") - with open(outputTsFile,"wt",encoding='utf8') as outFile: - outFile.write(renderedTsCode) - - cppTemplateFile = \ - os.path.join(os.path.dirname(__file__), 'template.in.h.j2') - template = MakeTemplateFromFile(cppTemplateFile) - renderedCppCode = template.render(**tdico) - outputCppFile = os.path.join( \ - outDir, str(tdico['rootName']) + "_generated.hpp") - with open(outputCppFile,"wt",encoding='utf8') as outFile: - outFile.write(renderedCppCode) - -if __name__ == "__main__": - import argparse - - parser = argparse.ArgumentParser( - usage="""stonegentool.py [-h] [-o OUT_DIR] [-v] input_schema - EXAMPLE: python stonegentool.py -o "generated_files/" """ - + """ "mainSchema.yaml,App Specific Commands.json" """ - ) - parser.add_argument("input_schema", type=str, \ - help="path to the schema file") - parser.add_argument( - "-o", - "--out_dir", - type=str, - default=".", - help="""path of the directory where the files - will be generated. Default is current - working folder""", - ) - parser.add_argument( - "-v", - "--verbosity", - action="count", - default=0, - help="""increase output verbosity (0 == errors - only, 1 == some verbosity, 2 == nerd - mode""", - ) - - args = parser.parse_args() - schemaFile = args.input_schema - outDir = args.out_dir - Process(schemaFile, outDir)
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/stonegentool_test.py Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,438 +0,0 @@ -# -# 1 2 3 4 5 6 7 8 -# 345678901234567890123456789012345678901234567890123456789012345678901234567890 -# - -from stonegentool import \ -EatToken,SplitListOfTypes,ParseTemplateType,ProcessSchema, \ -CheckSchemaSchema,LoadSchema,trim,ComputeRequiredDeclarationOrder, \ -GetTemplatingDictFromSchemaFilename,MakeTemplate,MakeTemplateFromFile,LoadSchemaFromString,GetTemplatingDictFromSchema -import unittest -import os -import re -import pprint -from jinja2 import Template - -def RemoveDateTimeLine(s : str): - # regex are non-multiline by default, and $ does NOT match the end of the line - s2 = re.sub(r"^// autogenerated by stonegentool on .*\n","",s) - return s2 - -class TestStonegentool(unittest.TestCase): - def test_EatToken_empty(self): - c = r"" - a,b = EatToken(c) - self.assertEqual(a,r"") - self.assertEqual(b,r"") - - def test_EatToken_simpleNonTemplate(self): - c = r"int32" - a,b = EatToken(c) - self.assertEqual(a,r"int32") - self.assertEqual(b,r"") - - def test_EatToken_simpleTemplate(self): - c = r"vector<string>" - a,b = EatToken(c) - self.assertEqual(a,r"vector<string>") - self.assertEqual(b,r"") - - def test_EatToken_complexTemplate(self): - c = r"vector<map<int64,string>>,vector<map<int32,string>>" - a,b = EatToken(c) - self.assertEqual(a,r"vector<map<int64,string>>") - self.assertEqual(b,r"vector<map<int32,string>>") - - def test_EatToken_complexTemplates(self): - c = r"vector<map<vector<string>,map<int32,string>>>,map<int32,string>,map<map<int32,string>,string>" - a,b = EatToken(c) - self.assertEqual(a,r"vector<map<vector<string>,map<int32,string>>>") - self.assertEqual(b,r"map<int32,string>,map<map<int32,string>,string>") - a,b = EatToken(b) - self.assertEqual(a,r"map<int32,string>") - self.assertEqual(b,r"map<map<int32,string>,string>") - - def test_SplitListOfTypes(self): - c = r"vector<map<vector<string>,map<int32,string>>>,map<int32,string>,map<map<int32,string>,string>" - lot = SplitListOfTypes(c) - self.assertEqual(3,len(lot)) - self.assertEqual("vector<map<vector<string>,map<int32,string>>>",lot[0]) - self.assertEqual("map<int32,string>",lot[1]) - self.assertEqual("map<map<int32,string>,string>",lot[2]) - - def test_SplitListOfTypes_bogus(self): - c = r"vector<map<vector<string>,map<int32,string>>,map<int32,string>,map<map<int32,string>,string" - self.assertRaises(Exception,SplitListOfTypes,c) # the argument c must be passed to assertRaises, not as a normal call of SplitListOfTypes - - def test_ParseTemplateType_true(self): - c = "map<vector<map<int,vector<string>>>,map<vector<int>,vector<string>>>" - (ok,a,b) = ParseTemplateType(c) - self.assertEqual(ok,True) - self.assertEqual(a,"map") - self.assertEqual(b,["vector<map<int,vector<string>>>","map<vector<int>,vector<string>>"]) - - (ok2,a2,b2) = ParseTemplateType(b[0]) - self.assertEqual(ok2,True) - self.assertEqual(a2,"vector") - self.assertEqual(b2,["map<int,vector<string>>"]) - - (ok3,a3,b3) = ParseTemplateType(b[1]) - self.assertEqual(ok3,True) - self.assertEqual(a3,"map") - self.assertEqual(b3,["vector<int>","vector<string>"]) - - (ok4,a4,b4) = ParseTemplateType(b2[0]) - self.assertEqual(ok4,True) - self.assertEqual(a4,"map") - self.assertEqual(b4,["int","vector<string>"]) - - def test_ParseSchema(self): - fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') - obj = LoadSchema(fn) - # we're happy if it does not crash :) - CheckSchemaSchema(obj) - - def test_ComputeRequiredDeclarationOrder(self): - fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') - obj = LoadSchema(fn) - genOrder: str = ComputeRequiredDeclarationOrder(obj) - self.assertEqual(5,len(genOrder)) - self.assertEqual("A",genOrder[0]) - self.assertEqual("B",genOrder[1]) - self.assertEqual("C",genOrder[2]) - self.assertEqual("Message1",genOrder[3]) - self.assertEqual("Message2",genOrder[4]) - - # def test_GeneratePreambleEnumerationAndStructs(self): - # fn = os.path.join(os.path.dirname(__file__), 'test', 'test1.jsonc') - # obj = LoadSchema(fn) - # (_,genc,_) = ProcessSchema(obj) - - def test_genEnums(self): - self.maxDiff = None - fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') - obj = LoadSchema(fn) - genOrder: str = ComputeRequiredDeclarationOrder(obj) - processedSchema = ProcessSchema(obj, genOrder) - self.assertTrue('rootName' in processedSchema) - - structs = {} - for v in processedSchema['structs']: - structs[v['name']] = v - enums = {} - for v in processedSchema['enums']: - enums[v['name']] = v - - self.assertTrue('C' in structs) - self.assertTrue('someBs' in structs['C']['fields']) - self.assertTrue('CrispType' in enums) - self.assertTrue('Message1' in structs) - self.assertEqual('int32', structs['Message1']['fields']['memberInt32'].type) - self.assertEqual('string', structs['Message1']['fields']['memberString'].type) - self.assertEqual('EnumMonth0', structs['Message1']['fields']['memberEnumMonth'].type) - self.assertEqual('bool', structs['Message1']['fields']['memberBool'].type) - self.assertEqual('float32', structs['Message1']['fields']['memberFloat32'].type) - self.assertEqual('float64', structs['Message1']['fields']['memberFloat64'].type) - - def test_GenerateTypeScriptEnums(self): - fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') - tdico = GetTemplatingDictFromSchemaFilename(fn) - template = Template(""" // end of generic methods -{% for enum in enums%} export enum {{enum['name']}} { -{% for key in enum['fields']%} {{key}}, -{%endfor%} }; - -{%endfor%}""") - renderedCode = template.render(**tdico) - renderedCodeRef = """ // end of generic methods - export enum MovieType { - RomCom, - Horror, - ScienceFiction, - Vegetables, - }; - - export enum CrispType { - SaltAndPepper, - CreamAndChives, - Paprika, - Barbecue, - }; - - export enum EnumMonth0 { - January, - February, - March, - }; - -""" - self.assertEqual(renderedCodeRef,renderedCode) - - def test_GenerateCplusplusEnums(self): - fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') - tdico = GetTemplatingDictFromSchemaFilename(fn) - template = Template(""" // end of generic methods -{% for enum in enums%} enum {{enum['name']}} { -{% for key in enum['fields']%} {{key}}, -{%endfor%} }; - -{%endfor%}""") - renderedCode = template.render(**tdico) - renderedCodeRef = """ // end of generic methods - enum MovieType { - RomCom, - Horror, - ScienceFiction, - Vegetables, - }; - - enum CrispType { - SaltAndPepper, - CreamAndChives, - Paprika, - Barbecue, - }; - - enum EnumMonth0 { - January, - February, - March, - }; - -""" - self.assertEqual(renderedCodeRef,renderedCode) - - def test_generateTsStructType(self): - fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') - tdico = GetTemplatingDictFromSchemaFilename(fn) - -# template = MakeTemplate(""" // end of generic methods -# {% for struct in struct%} export class {{struct['name']}} { -# {% for key in struct['fields']%} {{key}}:{{struct['fields'][key]}}, -# {% endfor %} -# constructor() { -# {% for key in struct['fields']%} -# {% if NeedsConstruction(struct['fields']['key'])} -# {{key}} = new {{CanonToTs(struct['fields']['key'])}}; -# {% end if %} -# {% endfor %} -# } -# {% endfor %} -# public StoneSerialize(): string { -# let container: object = {}; -# container['type'] = '{{rootName}}.{{struct['name']}}'; -# container['value'] = this; -# return JSON.stringify(container); -# } };""") - template = MakeTemplate(""" // end of generic methods -{% for struct in structs%} export class {{struct['name']}} { -{% for key in struct['fields']%} {{key}}:{{CanonToTs(struct['fields'][key]['type'])}}; -{% endfor %} - constructor() { -{% for key in struct['fields']%} this.{{key}} = new {{CanonToTs(struct['fields'][key]['type'])}}(); -{% endfor %} } - - public StoneSerialize(): string { - let container: object = {}; - container['type'] = '{{rootName}}.{{struct['name']}}'; - container['value'] = this; - return JSON.stringify(container); - } - }; - -{% endfor %}""") - renderedCode = template.render(**tdico) - renderedCodeRef = """ // end of generic methods - export class A { - someStrings:Array<string>; - someInts2:Array<number>; - movies:Array<MovieType>; - - constructor() { - this.someStrings = new Array<string>(); - this.someInts2 = new Array<number>(); - this.movies = new Array<MovieType>(); - } - - public StoneSerialize(): string { - let container: object = {}; - container['type'] = 'TestStoneCodeGen.A'; - container['value'] = this; - return JSON.stringify(container); - } - }; - - export class B { - someAs:Array<A>; - someInts:Array<number>; - - constructor() { - this.someAs = new Array<A>(); - this.someInts = new Array<number>(); - } - - public StoneSerialize(): string { - let container: object = {}; - container['type'] = 'TestStoneCodeGen.B'; - container['value'] = this; - return JSON.stringify(container); - } - }; - - export class C { - someBs:Array<B>; - ddd:Array<string>; - - constructor() { - this.someBs = new Array<B>(); - this.ddd = new Array<string>(); - } - - public StoneSerialize(): string { - let container: object = {}; - container['type'] = 'TestStoneCodeGen.C'; - container['value'] = this; - return JSON.stringify(container); - } - }; - - export class Message1 { - memberInt32:number; - memberString:string; - memberEnumMonth:EnumMonth0; - memberBool:boolean; - memberFloat32:number; - memberFloat64:number; - - constructor() { - this.memberInt32 = new number(); - this.memberString = new string(); - this.memberEnumMonth = new EnumMonth0(); - this.memberBool = new boolean(); - this.memberFloat32 = new number(); - this.memberFloat64 = new number(); - } - - public StoneSerialize(): string { - let container: object = {}; - container['type'] = 'TestStoneCodeGen.Message1'; - container['value'] = this; - return JSON.stringify(container); - } - }; - - export class Message2 { - memberString:string; - memberStringWithDefault:string; - memberVectorOfMessage1:Array<Message1>; - memberVectorOfString:Array<string>; - memberMapStringString:Map<string, string>; - memberMapStringStruct:Map<string, Message1>; - memberMapEnumFloat:Map<CrispType, number>; - memberEnumMovieType:MovieType; - memberJson:Object; - - constructor() { - this.memberString = new string(); - this.memberStringWithDefault = new string(); - this.memberVectorOfMessage1 = new Array<Message1>(); - this.memberVectorOfString = new Array<string>(); - this.memberMapStringString = new Map<string, string>(); - this.memberMapStringStruct = new Map<string, Message1>(); - this.memberMapEnumFloat = new Map<CrispType, number>(); - this.memberEnumMovieType = new MovieType(); - this.memberJson = new Object(); - } - - public StoneSerialize(): string { - let container: object = {}; - container['type'] = 'TestStoneCodeGen.Message2'; - container['value'] = this; - return JSON.stringify(container); - } - }; - -""" - # print(renderedCode) - self.maxDiff = None - self.assertEqual(renderedCodeRef, renderedCode) - - def test_generateWholeTsFile(self): - schemaFile = \ - os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') - tdico = GetTemplatingDictFromSchemaFilename(schemaFile) - tsTemplateFile = \ - os.path.join(os.path.dirname(__file__), 'template.in.ts.j2') - template = MakeTemplateFromFile(tsTemplateFile) - renderedCode = template.render(**tdico) - print(renderedCode) - - def test_GenerateTypeScriptHandlerInterface(self): - pass - - def test_GenerateCppHandlerInterface(self): - pass - - def test_GenerateTypeScriptDispatcher(self): - pass - - def test_GenerateCppDispatcher(self): - pass - - def test_StringDefaultValueInTs(self): - schema = LoadSchemaFromString(""" - rootName: MyTest - struct Toto: - withoutDefault: string - withDefault: string = \"tutu\" - """) - tdico = GetTemplatingDictFromSchema(schema) - - tsTemplateFile = os.path.join(os.path.dirname(__file__), 'template.in.ts.j2') - template = MakeTemplateFromFile(tsTemplateFile) - renderedCode = template.render(**tdico) - self.assertIn("withDefault = \"tutu\"", renderedCode) - # print(renderedCode) - - cppTemplateFile = os.path.join(os.path.dirname(__file__), 'template.in.h.j2') - template = MakeTemplateFromFile(cppTemplateFile) - renderedCode = template.render(**tdico) - print(renderedCode) - self.assertIn("withDefault = \"tutu\"", renderedCode) - - - def test_EnumDefaultValue(self): - schema = LoadSchemaFromString(""" - rootName: MyTest - enum MyEnum: - - Toto - - Tutu - struct Toto: - withoutDefault: MyEnum - withDefault: MyEnum = Toto - """) - tdico = GetTemplatingDictFromSchema(schema) - - tsTemplateFile = os.path.join(os.path.dirname(__file__), 'template.in.ts.j2') - template = MakeTemplateFromFile(tsTemplateFile) - renderedCode = template.render(**tdico) - # print(renderedCode) - self.assertIn("withDefault = MyEnum.Toto", renderedCode) - - tsTemplateFile = os.path.join(os.path.dirname(__file__), 'template.in.h.j2') - template = MakeTemplateFromFile(tsTemplateFile) - renderedCode = template.render(**tdico) - self.assertIn("withDefault = MyTest::MyEnum_Toto", renderedCode) - # print(renderedCode) - - -# def test(self): -# s = 'hello world' -# self.assertEqual(s.split(), ['hello', 'world']) -# # check that s.split fails when the separator is not a string -# with self.assertRaises(TypeError): -# s.split(2) - -if __name__ == '__main__': - unittest.main() -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/template.in.h.j2 Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,551 +0,0 @@ -/* - 1 2 3 4 5 6 7 -12345678901234567890123456789012345678901234567890123456789012345678901234567890 - -Generated on {{currentDatetime}} by stonegentool - -*/ -#pragma once - -#include <exception> -#include <iostream> -#include <string> -#include <sstream> -#include <assert.h> -#include <memory> -#include <set> -#include <json/json.h> - -//#define STONEGEN_NO_CPP11 1 - -#ifdef STONEGEN_NO_CPP11 -#define StoneSmartPtr std::unique_ptr -#else -#define StoneSmartPtr std::unique_ptr -#endif - -namespace {{rootName}} -{ - /** Throws in case of problem */ - inline void _StoneDeserializeValue(int32_t& destValue, const Json::Value& jsonValue) - { - if (!jsonValue.isNull()) - { - destValue = jsonValue.asInt(); - } - } - - inline Json::Value _StoneSerializeValue(int32_t value) - { - Json::Value result(value); - return result; - } - - inline void _StoneDeserializeValue(int64_t& destValue, const Json::Value& jsonValue) - { - if (!jsonValue.isNull()) - { - destValue = jsonValue.asInt64(); - } - } - - inline Json::Value _StoneSerializeValue(int64_t value) - { - Json::Value result(static_cast<Json::Value::Int64>(value)); - return result; - } - - inline void _StoneDeserializeValue(uint32_t& destValue, const Json::Value& jsonValue) - { - if (!jsonValue.isNull()) - { - destValue = jsonValue.asUInt(); - } - } - - inline Json::Value _StoneSerializeValue(uint32_t value) - { - Json::Value result(value); - return result; - } - - inline void _StoneDeserializeValue(uint64_t& destValue, const Json::Value& jsonValue) - { - if (!jsonValue.isNull()) - { - destValue = jsonValue.asUInt64(); - } - } - - inline Json::Value _StoneSerializeValue(uint64_t value) - { - Json::Value result(static_cast<Json::Value::UInt64>(value)); - return result; - } - - inline void _StoneDeserializeValue(Json::Value& destValue, const Json::Value& jsonValue) - { - destValue = jsonValue; - } - - inline Json::Value _StoneSerializeValue(Json::Value value) - { - return value; - } - - /** Throws in case of problem */ - inline void _StoneDeserializeValue(double& destValue, const Json::Value& jsonValue) - { - if (!jsonValue.isNull()) - { - destValue = jsonValue.asDouble(); - } - } - - inline Json::Value _StoneSerializeValue(double value) - { - Json::Value result(value); - return result; - } - - /** Throws in case of problem */ - inline void _StoneDeserializeValue(float& destValue, const Json::Value& jsonValue) - { - if (!jsonValue.isNull()) - { - destValue = jsonValue.asFloat(); - } - } - - inline Json::Value _StoneSerializeValue(float value) - { - Json::Value result(value); - return result; - } - - /** Throws in case of problem */ - inline void _StoneDeserializeValue(bool& destValue, const Json::Value& jsonValue) - { - if (!jsonValue.isNull()) - { - destValue = jsonValue.asBool(); - } - } - - inline Json::Value _StoneSerializeValue(bool value) - { - Json::Value result(value); - return result; - } - - /** Throws in case of problem */ - inline void _StoneDeserializeValue( - std::string& destValue - , const Json::Value& jsonValue) - { - if (!jsonValue.isNull()) - { - destValue = jsonValue.asString(); - } - } - - inline Json::Value _StoneSerializeValue(const std::string& value) - { - // the following is better than - Json::Value result(value.data(),value.data()+value.size()); - return result; - } - - inline std::string MakeIndent(size_t indent) - { - char* txt = reinterpret_cast<char*>(malloc(indent+1)); // NO EXCEPTION BELOW!!!!!!!!!!!! - for(size_t i = 0; i < indent; ++i) - txt[i] = ' '; - txt[indent] = 0; - std::string retVal(txt); - free(txt); // NO EXCEPTION ABOVE !!!!!!!!!! - return retVal; - } - - // generic dumper - template<typename T> - std::ostream& StoneDumpValue(std::ostream& out, const T& value, size_t indent) - { - out << MakeIndent(indent) << value; - return out; - } - - // string dumper - inline std::ostream& StoneDumpValue(std::ostream& out, const std::string& value, size_t indent) - { - out << MakeIndent(indent) << "\"" << value << "\""; - return out; - } - - inline std::string ToString(const std::string& str) - { - return str; - } - - inline void FromString(std::string& value, std::string strValue) - { - value = strValue; - } - - - /** Throws in case of problem */ - template<typename TK, typename TV> - void _StoneDeserializeValue( - std::map<TK, TV>& destValue, const Json::Value& jsonValue) - { - if (!jsonValue.isNull()) - { - destValue.clear(); - for ( - Json::Value::const_iterator itr = jsonValue.begin(); - itr != jsonValue.end(); - itr++) - { - std::string strKey; - _StoneDeserializeValue(strKey, itr.key()); - TK key; - FromString(key, strKey); // if you have a compile error here, it means that your type is not suitable to be the key of a map (or you should overwrite the FromString/ToString in template.in.h.j2) - - TV innerDestValue; - _StoneDeserializeValue(innerDestValue, *itr); - - destValue[key] = innerDestValue; - } - } - } - - template<typename TK, typename TV> - Json::Value _StoneSerializeValue(const std::map<TK, TV>& value) - { - Json::Value result(Json::objectValue); - - for (typename std::map<TK, TV>::const_iterator it = value.cbegin(); - it != value.cend(); ++it) - { - // it->first it->second - result[ToString(it->first)] = _StoneSerializeValue(it->second); - } - return result; - } - - template<typename TK, typename TV> - std::ostream& StoneDumpValue(std::ostream& out, const std::map<TK, TV>& value, size_t indent) - { - out << MakeIndent(indent) << "{\n"; - for (typename std::map<TK, TV>::const_iterator it = value.cbegin(); - it != value.cend(); ++it) - { - out << MakeIndent(indent+2) << "\"" << it->first << "\" : "; - StoneDumpValue(out, it->second, indent+2); - out << ", \n"; - } - out << MakeIndent(indent) << "}\n"; - return out; - } - - /** Throws in case of problem */ - template<typename T> - void _StoneDeserializeValue( - std::vector<T>& destValue, const Json::Value& jsonValue) - { - if (!jsonValue.isNull() && jsonValue.isArray()) - { - destValue.clear(); - destValue.reserve(jsonValue.size()); - for (Json::Value::ArrayIndex i = 0; i != jsonValue.size(); i++) - { - T innerDestValue; - _StoneDeserializeValue(innerDestValue, jsonValue[i]); - destValue.push_back(innerDestValue); - } - } - } - - template<typename T> - Json::Value _StoneSerializeValue(const std::vector<T>& value) - { - Json::Value result(Json::arrayValue); - for (size_t i = 0; i < value.size(); ++i) - { - result.append(_StoneSerializeValue(value[i])); - } - return result; - } - - template<typename T> - std::ostream& StoneDumpValue(std::ostream& out, const std::vector<T>& value, size_t indent) - { - out << MakeIndent(indent) << "[\n"; - for (size_t i = 0; i < value.size(); ++i) - { - StoneDumpValue(out, value[i], indent+2); - out << ", \n"; - } - out << MakeIndent(indent) << "]\n"; - return out; - } - - /** Throws in case of problem */ - template<typename T> - void _StoneDeserializeValue( - std::set<T>& destValue, const Json::Value& jsonValue) - { - if (!jsonValue.isNull() && jsonValue.isArray()) - { - destValue.clear(); - for (Json::Value::ArrayIndex i = 0; i != jsonValue.size(); i++) - { - T innerDestValue; - _StoneDeserializeValue(innerDestValue, jsonValue[i]); - destValue.insert(innerDestValue); - } - } - } - - template<typename T> - Json::Value _StoneSerializeValue(const std::set<T>& value) - { - Json::Value result(Json::arrayValue); - for (typename std::set<T>::const_iterator it = value.begin(); it != value.end(); ++it) - { - result.append(_StoneSerializeValue(*it)); - } - return result; - } - - template<typename T> - std::ostream& StoneDumpValue(std::ostream& out, const std::set<T>& value, size_t indent) - { - out << MakeIndent(indent) << "[\n"; - for (typename std::set<T>::const_iterator it = value.begin(); it != value.end(); ++it) - { - StoneDumpValue(out, *it, indent+2); - out << ", \n"; - } - out << MakeIndent(indent) << "]\n"; - return out; - } - - inline void StoneCheckSerializedValueTypeGeneric(const Json::Value& value) - { - if ((!value.isMember("type")) || (!value["type"].isString())) - { - std::stringstream ss; - ss << "Cannot deserialize value ('type' key invalid)"; - throw std::runtime_error(ss.str()); - } - } - - inline void StoneCheckSerializedValueType( - const Json::Value& value, std::string typeStr) - { - StoneCheckSerializedValueTypeGeneric(value); - - std::string actTypeStr = value["type"].asString(); - if (actTypeStr != typeStr) - { - std::stringstream ss; - ss << "Cannot deserialize type" << actTypeStr - << "into " << typeStr; - throw std::runtime_error(ss.str()); - } - } - - // end of generic methods - -// end of generic methods -{% for enum in enums%} - enum {{enum['name']}} { -{% for key in enum['fields']%} {{enum['name']}}_{{key}}, -{%endfor%} }; - - inline std::string ToString(const {{enum['name']}}& value) - { -{% for key in enum['fields']%} if( value == {{enum['name']}}_{{key}}) - { - return std::string("{{key}}"); - } -{%endfor%} std::stringstream ss; - ss << "Value \"" << value << "\" cannot be converted to {{enum['name']}}. Possible values are: " -{% for key in enum['fields']%} << " {{key}} = " << static_cast<int64_t>({{enum['name']}}_{{key}}) << ", " -{% endfor %} << std::endl; - std::string msg = ss.str(); - throw std::runtime_error(msg); - } - - inline void FromString({{enum['name']}}& value, std::string strValue) - { -{% for key in enum['fields']%} if( strValue == std::string("{{key}}") ) - { - value = {{enum['name']}}_{{key}}; - return; - } -{%endfor%} - std::stringstream ss; - ss << "String \"" << strValue << "\" cannot be converted to {{enum['name']}}. Possible values are: {% for key in enum['fields']%}{{key}} {% endfor %}"; - std::string msg = ss.str(); - throw std::runtime_error(msg); - } - - - inline void _StoneDeserializeValue( - {{enum['name']}}& destValue, const Json::Value& jsonValue) - { - if (!jsonValue.isNull()) - { - FromString(destValue, jsonValue.asString()); - } - } - - inline Json::Value _StoneSerializeValue(const {{enum['name']}}& value) - { - std::string strValue = ToString(value); - return Json::Value(strValue); - } - - inline std::ostream& StoneDumpValue(std::ostream& out, const {{enum['name']}}& value, size_t indent = 0) - { -{% for key in enum['fields']%} if( value == {{enum['name']}}_{{key}}) - { - out << MakeIndent(indent) << "{{key}}"; - } -{%endfor%} return out; - } - -{%endfor%} -{% for struct in structs%} -#ifdef _MSC_VER -#pragma region {{struct['name']}} -#endif //_MSC_VER - - struct {{struct['name']}} - { -{% if struct %}{% if struct['fields'] %}{% for key in struct['fields'] %} {{CanonToCpp(struct['fields'][key]['type'])}} {{key}}; -{% endfor %}{% endif %}{% endif %} - {{struct['name']}}({% if struct %}{% if struct['fields'] %}{% for key in struct['fields'] %}{{CanonToCpp(struct['fields'][key]['type'])}} {{key}} = {% if struct['fields'][key]['defaultValue'] %}{{DefaultValueToCpp(rootName,enums,struct['fields'][key])}} {%else%} {{CanonToCpp(struct['fields'][key]['type'])}}() {%endif%} {{ ", " if not loop.last }}{% endfor %}{% endif %}{% endif %}) - { -{% if struct %}{% if struct['fields'] %}{% for key in struct['fields']%} this->{{key}} = {{key}}; -{% endfor %}{% endif %}{% endif %} } - }; - - inline void _StoneDeserializeValue({{struct['name']}}& destValue, const Json::Value& value) - { - if (!value.isNull()) - { -{% if struct %}{% if struct['fields'] %}{% for key in struct['fields']%} _StoneDeserializeValue(destValue.{{key}}, value["{{key}}"]); -{% endfor %}{% endif %}{% endif %} } - } - - inline Json::Value _StoneSerializeValue(const {{struct['name']}}& value) - { - Json::Value result(Json::objectValue); -{% if struct %}{% if struct['fields'] %}{% for key in struct['fields']%} result["{{key}}"] = _StoneSerializeValue(value.{{key}}); -{% endfor %}{% endif %}{% endif %} - return result; - } - - inline std::ostream& StoneDumpValue(std::ostream& out, const {{struct['name']}}& value, size_t indent = 0) - { - out << MakeIndent(indent) << "{\n"; -{% if struct %}{% if struct['fields'] %}{% for key in struct['fields']%} out << MakeIndent(indent+2) << "{{key}}: "; - StoneDumpValue(out, value.{{key}},indent+2); - out << ", \n"; -{% endfor %}{% endif %}{% endif %} - out << MakeIndent(indent) << "}"; - return out; - } - - inline void StoneDeserialize({{struct['name']}}& destValue, const Json::Value& value) - { - StoneCheckSerializedValueType(value, "{{rootName}}.{{struct['name']}}"); - _StoneDeserializeValue(destValue, value["value"]); - } - - inline Json::Value StoneSerializeToJson(const {{struct['name']}}& value) - { - Json::Value result(Json::objectValue); - result["type"] = "{{rootName}}.{{struct['name']}}"; - result["value"] = _StoneSerializeValue(value); - return result; - } - - inline std::string StoneSerialize(const {{struct['name']}}& value) - { - Json::Value resultJson = StoneSerializeToJson(value); - std::string resultStr = resultJson.toStyledString(); - return resultStr; - } - -#ifdef _MSC_VER -#pragma endregion {{struct['name']}} -#endif //_MSC_VER -{% endfor %} -#ifdef _MSC_VER -#pragma region Dispatching code -#endif //_MSC_VER - - class IHandler - { - public: -{% for struct in structs%}{% if struct['__meta__'].handleInCpp %} virtual bool Handle(const {{struct['name']}}& value) = 0; -{% endif %}{% endfor %} }; - - /** Service function for StoneDispatchToHandler */ - inline bool StoneDispatchJsonToHandler( - const Json::Value& jsonValue, IHandler* handler) - { - StoneCheckSerializedValueTypeGeneric(jsonValue); - std::string type = jsonValue["type"].asString(); - if (type == "") - { - // this should never ever happen - throw std::runtime_error("Caught empty type while dispatching"); - } -{% for struct in structs%}{% if struct['__meta__'].handleInCpp %} else if (type == "{{rootName}}.{{struct['name']}}") - { - {{struct['name']}} value; - _StoneDeserializeValue(value, jsonValue["value"]); - return handler->Handle(value); - } -{% endif %}{% endfor %} else - { - return false; - } - } - - /** Takes a serialized type and passes this to the handler */ - inline bool StoneDispatchToHandler(std::string strValue, IHandler* handler) - { - Json::Value readValue; - - Json::CharReaderBuilder builder; - Json::CharReader* reader = builder.newCharReader(); - - StoneSmartPtr<Json::CharReader> ptr(reader); - - std::string errors; - - bool ok = reader->parse( - strValue.c_str(), - strValue.c_str() + strValue.size(), - &readValue, - &errors - ); - if (!ok) - { - std::stringstream ss; - ss << "Jsoncpp parsing error: " << errors; - throw std::runtime_error(ss.str()); - } - return StoneDispatchJsonToHandler(readValue, handler); - } - -#ifdef _MSC_VER -#pragma endregion Dispatching code -#endif //_MSC_VER -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/template.in.ts.j2 Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,136 +0,0 @@ -/* - 1 2 3 4 5 6 7 -12345678901234567890123456789012345678901234567890123456789012345678901234567890 - -Generated on {{currentDatetime}} by stonegentool - -*/ - -function StoneCheckSerializedValueType(value: any, typeStr: string) -{ - StoneCheckSerializedValueTypeGeneric(value); - - if (value['type'] != typeStr) - { - throw new Error( - `Cannot deserialize type ${value['type']} into ${typeStr}`); - } -} - -function isString(val: any) :boolean -{ - return ((typeof val === 'string') || (val instanceof String)); -} - -function StoneCheckSerializedValueTypeGeneric(value: any) -{ - // console.//log("+-------------------------------------------------+"); - // console.//log("| StoneCheckSerializedValueTypeGeneric |"); - // console.//log("+-------------------------------------------------+"); - // console.//log("value = "); - // console.//log(value); - if ( (!('type' in value)) || (!isString(value.type)) ) - { - throw new Error( - "Cannot deserialize value ('type' key invalid)"); - } -} - -// end of generic methods -{% for enum in enums%} -export enum {{enum['name']}} { -{% for key in enum['fields']%} {{key}} = "{{key}}"{% if not loop.last %},{%endif%} -{%endfor%}}; - -export function {{enum['name']}}_FromString(strValue:string) : {{enum['name']}} -{ -{% for key in enum['fields'] %} if( strValue == "{{key}}" ) - { - return {{enum['name']}}.{{key}}; - } -{%endfor%} - let msg : string = `String ${strValue} cannot be converted to {{enum['name']}}. Possible values are: {% for key in enum['fields']%}{{key}}{% if not loop.last %}, {%endif%}{% endfor %}`; - throw new Error(msg); -} - -export function {{enum['name']}}_ToString(value:{{enum['name']}}) : string -{ -{% for key in enum['fields'] %} if( value == {{enum['name']}}.{{key}} ) - { - return "{{key}}"; - } -{%endfor%} - let msg : string = `Value ${value} cannot be converted to {{enum['name']}}. Possible values are: `; -{% for key in enum['fields']%} { - let _{{key}}_enumValue : string = {{enum['name']}}.{{key}}; // enums are strings in stonecodegen, so this will work. - let msg_{{key}} : string = `{{key}} (${_{{key}}_enumValue}){% if not loop.last %}, {%endif%}`; - msg = msg + msg_{{key}}; - } -{%endfor%} throw new Error(msg); -} -{%endfor%} - - -{% for struct in structs%}export class {{struct['name']}} { -{% if struct %}{% if struct['fields'] %}{% for key in struct['fields']%} {{key}}:{{CanonToTs(struct['fields'][key]['type'])}}; -{% endfor %}{% endif %}{% endif %} - constructor() { -{% if struct %}{% if struct['fields'] %}{% for key in struct['fields']%}{% if NeedsTsConstruction(enums,CanonToTs(struct['fields'][key]['type'])) %} this.{{key}} = new {{CanonToTs(struct['fields'][key]['type'])}}(); -{% endif %} -{% if struct['fields'][key]['defaultValue'] %} this.{{key}} = {{DefaultValueToTs(enums,struct['fields'][key])}}; -{% endif %}{% endfor %}{% endif %}{% endif %} } - - public StoneSerialize(): string { - let container: object = {}; - container['type'] = '{{rootName}}.{{struct['name']}}'; - container['value'] = this; - return JSON.stringify(container); - } - - public static StoneDeserialize(valueStr: string) : {{struct['name']}} - { - let value: any = JSON.parse(valueStr); - StoneCheckSerializedValueType(value, '{{rootName}}.{{struct['name']}}'); - let result: {{struct['name']}} = value['value'] as {{struct['name']}}; - return result; - } -} -{% endfor %} -export interface IHandler { -{% for struct in structs%}{% if struct['__meta__'].handleInTypescript %} Handle{{struct['name']}}(value: {{struct['name']}}): boolean; -{% endif %}{% endfor %}}; - -/** Service function for StoneDispatchToHandler */ -export function StoneDispatchJsonToHandler( - jsonValue: any, handler: IHandler): boolean -{ - StoneCheckSerializedValueTypeGeneric(jsonValue); - let type: string = jsonValue["type"]; - if (type == "") - { - // this should never ever happen - throw new Error("Caught empty type while dispatching"); - } -{% for struct in structs%}{% if struct['__meta__'].handleInTypescript %} else if (type == "{{rootName}}.{{struct['name']}}") - { - let value = jsonValue["value"] as {{struct['name']}}; - return handler.Handle{{struct['name']}}(value); - } -{% endif %}{% endfor %} else - { - return false; - } -} - -/** Takes a serialized type and passes this to the handler */ -export function StoneDispatchToHandler( - strValue: string, handler: IHandler): boolean -{ - // console.//log("+------------------------------------------------+"); - // console.//log("| StoneDispatchToHandler |"); - // console.//log("+------------------------------------------------+"); - // console.//log("strValue = "); - // console.//log(strValue); - let jsonValue: any = JSON.parse(strValue) - return StoneDispatchJsonToHandler(jsonValue, handler); -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testCppHandler/CMakeLists.txt Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -cmake_minimum_required(VERSION 2.8) - -project(testCppHandler) - -set(testCppHandler_Codegen_Deps - ${CMAKE_CURRENT_LIST_DIR}/../test_data/testTestStoneCodeGen.yaml - ${CMAKE_CURRENT_LIST_DIR}/../template.in.h.j2 -) - -add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/VsolMessages_generated.hpp - COMMAND python ${CMAKE_CURRENT_LIST_DIR}/../stonegentool.py -o ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_LIST_DIR}/../test_data/testTestStoneCodeGen.yaml - DEPENDS ${testCppHandler_Codegen_Deps} -) - -include(${CMAKE_BINARY_DIR}/conanbuildinfo_multi.cmake) -conan_basic_setup() - -add_executable(testCppHandler main.cpp ${CMAKE_CURRENT_BINARY_DIR}/VsolMessages_generated.hpp ${testCppHandler_Codegen_Deps}) - -target_include_directories(testCppHandler PUBLIC ${CMAKE_BINARY_DIR}) - -conan_target_link_libraries(testCppHandler) - -set_property(TARGET testCppHandler PROPERTY CXX_STANDARD 17) - -install(TARGETS testCppHandler DESTINATION bin) -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testCppHandler/README.md Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -Requirements -============== -- Install Python 3.x (tested with 3.7) -- Install conan with `pip install conan` (tested with 1.12.2) -- Install CMake (tested with 3.12) -- Under Windows: Visual Studio 2017 -- Under *nix*: Ninja - -How to build under *nix* -=============================== -- Navigate to `testCppHandler` folder -- `conan install . -g cmake` -- `mkdir build` -- `cd build` -- `cmake -G "Ninja" ..` -- `cmake --build . --config Debug` or - `cmake --build . --config Release` - -How to build under Windows with Visual Studio -============================================== -- Navigate to repo root -- `mkdir build` -- `cd build` -- `conan install .. -g cmake_multi -s build_type=Release` -- `conan install .. -g cmake_multi -s build_type=Debug` -- `cmake -G "Visual Studio 15 2017 Win64" ..` (modify for your current Visual Studio version) -- `cmake --build . --config Debug` or - `cmake --build . --config Release` - -How to execute the test -======================= -- `cd test_data && testCppHandler --pattern=*.json` - - - -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testCppHandler/conanfile.txt Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -[requires] -jsoncpp/1.8.4@theirix/stable -gtest/1.8.1@bincrafters/stable -boost/1.69.0@conan/stable
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testCppHandler/main.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,160 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include <string> -#include <fstream> -#include <filesystem> -#include <regex> -using namespace std; -namespace fs = std::filesystem; - -#include <boost/program_options.hpp> -using namespace boost::program_options; - -#include "TestStoneCodeGen_generated.hpp" - -/** -Transforms `str` by replacing occurrences of `oldStr` with `newStr`, using -plain text (*not* regular expressions.) -*/ -static inline void ReplaceInString( - string& str, - const std::string& oldStr, - const std::string& newStr) -{ - std::string::size_type pos = 0u; - while ((pos = str.find(oldStr, pos)) != std::string::npos) { - str.replace(pos, oldStr.length(), newStr); - pos += newStr.length(); - } -} - -string SlurpFile(const string& fileName) -{ - ifstream ifs(fileName.c_str(), ios::in | ios::binary | ios::ate); - - ifstream::pos_type fileSize = ifs.tellg(); - ifs.seekg(0, ios::beg); - - vector<char> bytes(fileSize); - ifs.read(bytes.data(), fileSize); - - return string(bytes.data(), fileSize); -} - -class MyHandler : public TestStoneCodeGen::IHandler -{ -public: - virtual bool Handle(const TestStoneCodeGen::A& value) override - { - TestStoneCodeGen::StoneDumpValue(cout, value); - return true; - } - virtual bool Handle(const TestStoneCodeGen::B& value) override - { - TestStoneCodeGen::StoneDumpValue(cout, value); - return true; - } - virtual bool Handle(const TestStoneCodeGen::C& value) override - { - TestStoneCodeGen::StoneDumpValue(cout, value); - return true; - } - virtual bool Handle(const TestStoneCodeGen::Message1& value) override - { - TestStoneCodeGen::StoneDumpValue(cout, value); - return true; - } - virtual bool Handle(const TestStoneCodeGen::Message2& value) override - { - TestStoneCodeGen::StoneDumpValue(cout, value); - return true; - } -}; - -template<typename T> -void ProcessPath(T filePath) -{ - cout << "+--------------------------------------------+\n"; - cout << "| Processing: " << filePath.path().string() << "\n"; - cout << "+--------------------------------------------+\n"; - MyHandler handler; - auto contents = SlurpFile(filePath.path().string()); - TestStoneCodeGen::StoneDispatchToHandler(contents, &handler); -} - -int main(int argc, char** argv) -{ - try - { - - options_description desc("Allowed options"); - desc.add_options() - // First parameter describes option name/short name - // The second is parameter to option - // The third is description - ("help,h", "print usage message") - ("pattern,p", value<string>(), "pattern for input") - ; - - variables_map vm; - store(parse_command_line(argc, argv, desc), vm); - - if (vm.count("help")) - { - cout << desc << "\n"; - return 0; - } - - notify(vm); - - string pattern = vm["pattern"].as<string>(); - - // tranform globbing pattern into regex - // we should deal with -, ., *... - string regexPatternStr = pattern; - cout << "Pattern is: " << regexPatternStr << endl; - ReplaceInString(regexPatternStr, "\\", "\\\\"); - ReplaceInString(regexPatternStr, "-", "\\-"); - ReplaceInString(regexPatternStr, ".", "\\."); - ReplaceInString(regexPatternStr, "*", ".*"); - ReplaceInString(regexPatternStr, "?", "."); - cout << "Corresponding regex is: " << regexPatternStr << endl; - - regex regexPattern(regexPatternStr); - - for (auto& p : fs::directory_iterator(".")) - { - auto fileName = p.path().filename().string(); - if (regex_match(fileName, regexPattern)) - { - ProcessPath(p); - } - } - return 0; - - - } - catch (exception& e) - { - cerr << e.what() << "\n"; - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testCppHandler/test_data/test_Message2.json Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -{ - "type": "TestStoneCodeGen.Message2", - "value": { - "memberVectorOfMessage1": [ - { - "memberInt32": 42, - "memberString": "Benjamin", - "memberEnumMonth": "January", - "memberBool": false, - "memberFloat32": 0.1, - "memberFloat64": -0.2 - }, - { - "memberInt32": 43, - "memberString": "Sandrine", - "memberEnumMonth": "March" - } - ], - "memberVectorOfString": [ - "Mercadet", - "Poisson" - ], - "memberMapStringString": { - "44": "key 44", - "45": "key 45" - }, - "memberMapStringStruct": { - "54": { - "memberInt32": 43, - "memberString": "Sandrine", - "memberEnumMonth": "March" - }, - "55": { - "memberInt32": 42, - "memberString": "Benjamin", - "memberEnumMonth": "January", - "memberBool": false - } - }, - "memberString": "Prout zizi", - "memberMapEnumFloat" : { - "SaltAndPepper" : 0.1, - "CreamAndChives" : -0.2 - }, - "memberJson" : {"custom-key": "custom-value"} - } -} \ No newline at end of file
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/CMakeLists.txt Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -cmake_minimum_required(VERSION 2.8) - -project(testWasmIntegratedCpp) - -set(WASM_FLAGS "-s WASM=1 -O0 -g0") -set(WASM_MODULE_NAME "TestWasmIntegratedModule" CACHE STRING "Name of the WebAssembly module") -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WASM_FLAGS}") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WASM_FLAGS}") -#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --js-library ${STONE_SOURCES_DIR}/Platforms/Wasm/WasmWebService.js --js-library ${STONE_SOURCES_DIR}/Platforms/Wasm/WasmDelayedCallExecutor.js --js-library ${STONE_SOURCES_DIR}/Platforms/Wasm/default-library.js -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"ccall\", \"cwrap\"]'") -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --js-library ${CMAKE_CURRENT_LIST_DIR}/DefaultLibrary.js -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"ccall\", \"cwrap\"]'") -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s DISABLE_EXCEPTION_CATCHING=0 -s EXPORT_NAME='\"${WASM_MODULE_NAME}\"' -s ALLOW_MEMORY_GROWTH=1 -s TOTAL_MEMORY=536870912 -s TOTAL_STACK=128000000") # 512MB + resize - -add_definitions(-DORTHANC_ENABLE_WASM=1) - -set(testWasmIntegratedCpp_Codegen_Deps - ${CMAKE_CURRENT_LIST_DIR}/testWasmIntegratedCpp_api.yaml - ${CMAKE_CURRENT_LIST_DIR}/../template.in.h.j2 - ${CMAKE_CURRENT_LIST_DIR}/../template.in.ts.j2 -) - -set(jsoncppRootDir ${CMAKE_CURRENT_LIST_DIR}/jsoncpp-1.8.4) - -add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/TestStoneCodeGen_generated.hpp ${CMAKE_CURRENT_BINARY_DIR}/TestStoneCodeGen_generated.ts - COMMAND python3 ${CMAKE_CURRENT_LIST_DIR}/../stonegentool.py -o ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_LIST_DIR}/../test_data/testTestStoneCodeGen.yaml - DEPENDS ${testCppHandler_Codegen_Deps} ${CMAKE_CURRENT_LIST_DIR}/../test_data/testTestStoneCodeGen.yaml -) - -add_executable(testWasmIntegratedCpp - main.cpp - ${CMAKE_CURRENT_BINARY_DIR}/TestStoneCodeGen_generated.hpp - ${jsoncppRootDir}/jsoncpp.cpp - ${testCppHandler_Codegen_Deps}) - -target_include_directories(testWasmIntegratedCpp PUBLIC ${CMAKE_BINARY_DIR}) -target_include_directories(testWasmIntegratedCpp PUBLIC ${jsoncppRootDir}) - -set_property(TARGET testWasmIntegratedCpp PROPERTY CXX_STANDARD 11) - -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/DefaultLibrary.js Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -// this file contains the JS method you want to expose to C++ code - -mergeInto(LibraryManager.library, { - // each time the Application updates its status, it may signal it through this method. i.e, to change the status of a button in the web interface - // It needs to be put in this file so that the emscripten SDK linker knows where to find it. - SendFreeTextFromCppJS: function(statusUpdateMessage) { - var statusUpdateMessage_ = UTF8ToString(statusUpdateMessage); - window.SendFreeTextFromCpp(statusUpdateMessage_); - }, - SendMessageFromCppJS: function(statusUpdateMessage) { - var statusUpdateMessage_ = UTF8ToString(statusUpdateMessage); - window.SendMessageFromCpp(statusUpdateMessage_); - } -}); -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/build-web.sh Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -#!/bin/bash -set -e - -mkdir -p build-final - -# compile TS to JS -tsc --module commonjs --sourceMap -t ES2015 --outDir "build-tsc/" build-wasm/TestStoneCodeGen_generated.ts testWasmIntegrated.ts - -# bundle JS files to final build dir -browserify "build-tsc/build-wasm/testWasmIntegratedCpp_generated.js" "build-tsc/testWasmIntegrated.js" -o "build-final/testWasmIntegratedApp.js" - -# copy WASM loader JS file to final build dir -cp build-wasm/testWasmIntegratedCpp.js build-final/ - -# copy HTML start page to output dir -cp testWasmIntegrated.html build-final/ - - -# copy styles to output dir -cp styles.css build-final/ - -# copy WASM binary to output dir -cp build-wasm/testWasmIntegratedCpp.wasm build-final/ - -cp ../test_data/testTestStoneCodeGen.yaml build-final/ -cp ../testCppHandler/test_data/test_Message2.json build-final/cppHandler_test_Message2.json - -echo "...Serving files at http://127.0.0.1:8080/build-final/testWasmIntegrated.html" - -sudo python3 serve.py -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/build.sh Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -#!/bin/bash - -set -e - -mkdir -p build-wasm -cd build-wasm - -# shellcheck source="$HOME/apps/emsdk/emsdk_env.sh" -source "$HOME/apps/emsdk/emsdk_env.sh" -cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=${EMSCRIPTEN}/cmake/Modules/Platform/Emscripten.cmake -DCMAKE_BUILD_TYPE=Debug -DENABLE_WASM=ON .. - -ninja - -cd .. - -./build-web.sh -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/jsoncpp-1.8.4/json/json-forwards.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,344 +0,0 @@ -/// Json-cpp amalgamated forward header (http://jsoncpp.sourceforge.net/). -/// It is intended to be used with #include "json/json-forwards.h" -/// This header provides forward declaration for all JsonCpp types. - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - -/* -The JsonCpp library's source code, including accompanying documentation, -tests and demonstration applications, are licensed under the following -conditions... - -Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all -jurisdictions which recognize such a disclaimer. In such jurisdictions, -this software is released into the Public Domain. - -In jurisdictions which do not recognize Public Domain property (e.g. Germany as of -2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and -The JsonCpp Authors, and is released under the terms of the MIT License (see below). - -In jurisdictions which recognize Public Domain property, the user of this -software may choose to accept it either as 1) Public Domain, 2) under the -conditions of the MIT License (see below), or 3) under the terms of dual -Public Domain/MIT License conditions described here, as they choose. - -The MIT License is about as close to Public Domain as a license can get, and is -described in clear, concise terms at: - - http://en.wikipedia.org/wiki/MIT_License - -The full text of the MIT License follows: - -======================================================================== -Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, copy, -modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -======================================================================== -(END LICENSE TEXT) - -The MIT license is compatible with both the GPL and commercial -software, affording one all of the rights of Public Domain with the -minor nuisance of being required to keep the above copyright notice -and license text in the source code. Note also that by accepting the -Public Domain "license" you can re-license your copy using whatever -license you like. - -*/ - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - - - - - -#ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED -# define JSON_FORWARD_AMALGAMATED_H_INCLUDED -/// If defined, indicates that the source file is amalgamated -/// to prevent private header inclusion. -#define JSON_IS_AMALGAMATION - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/config.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_CONFIG_H_INCLUDED -#define JSON_CONFIG_H_INCLUDED -#include <cstddef> -#include <cstdint> -#include <istream> -#include <memory> -#include <ostream> -#include <sstream> -#include <string> -#include <type_traits> - -/// If defined, indicates that json library is embedded in CppTL library. -//# define JSON_IN_CPPTL 1 - -/// If defined, indicates that json may leverage CppTL library -//# define JSON_USE_CPPTL 1 -/// If defined, indicates that cpptl vector based map should be used instead of -/// std::map -/// as Value container. -//# define JSON_USE_CPPTL_SMALLMAP 1 - -// If non-zero, the library uses exceptions to report bad input instead of C -// assertion macros. The default is to use exceptions. -#ifndef JSON_USE_EXCEPTION -#define JSON_USE_EXCEPTION 1 -#endif - -/// If defined, indicates that the source file is amalgamated -/// to prevent private header inclusion. -/// Remarks: it is automatically defined in the generated amalgamated header. -// #define JSON_IS_AMALGAMATION - -#ifdef JSON_IN_CPPTL -#include <cpptl/config.h> -#ifndef JSON_USE_CPPTL -#define JSON_USE_CPPTL 1 -#endif -#endif - -#ifdef JSON_IN_CPPTL -#define JSON_API CPPTL_API -#elif defined(JSON_DLL_BUILD) -#if defined(_MSC_VER) || defined(__MINGW32__) -#define JSON_API __declspec(dllexport) -#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING -#endif // if defined(_MSC_VER) -#elif defined(JSON_DLL) -#if defined(_MSC_VER) || defined(__MINGW32__) -#define JSON_API __declspec(dllimport) -#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING -#endif // if defined(_MSC_VER) -#endif // ifdef JSON_IN_CPPTL -#if !defined(JSON_API) -#define JSON_API -#endif - -#if defined(_MSC_VER) && _MSC_VER < 1800 -#error \ - "ERROR: Visual Studio 12 (2013) with _MSC_VER=1800 is the oldest supported compiler with sufficient C++11 capabilities" -#endif - -#if defined(_MSC_VER) && _MSC_VER < 1900 -// As recommended at -// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010 -extern JSON_API int -msvc_pre1900_c99_snprintf(char* outBuf, size_t size, const char* format, ...); -#define jsoncpp_snprintf msvc_pre1900_c99_snprintf -#else -#define jsoncpp_snprintf std::snprintf -#endif - -// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for -// integer -// Storages, and 64 bits integer support is disabled. -// #define JSON_NO_INT64 1 - -#if defined(_MSC_VER) // MSVC -#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) -#endif // defined(_MSC_VER) - -// JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools. -// C++11 should be used directly in JSONCPP. -#define JSONCPP_OVERRIDE override - -#if __cplusplus >= 201103L -#define JSONCPP_NOEXCEPT noexcept -#define JSONCPP_OP_EXPLICIT explicit -#elif defined(_MSC_VER) && _MSC_VER < 1900 -#define JSONCPP_NOEXCEPT throw() -#define JSONCPP_OP_EXPLICIT explicit -#elif defined(_MSC_VER) && _MSC_VER >= 1900 -#define JSONCPP_NOEXCEPT noexcept -#define JSONCPP_OP_EXPLICIT explicit -#else -#define JSONCPP_NOEXCEPT throw() -#define JSONCPP_OP_EXPLICIT -#endif - -#ifndef JSON_HAS_RVALUE_REFERENCES - -#if defined(_MSC_VER) -#define JSON_HAS_RVALUE_REFERENCES 1 -#endif // MSVC >= 2013 - -#ifdef __clang__ -#if __has_feature(cxx_rvalue_references) -#define JSON_HAS_RVALUE_REFERENCES 1 -#endif // has_feature - -#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) -#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L) -#define JSON_HAS_RVALUE_REFERENCES 1 -#endif // GXX_EXPERIMENTAL - -#endif // __clang__ || __GNUC__ - -#endif // not defined JSON_HAS_RVALUE_REFERENCES - -#ifndef JSON_HAS_RVALUE_REFERENCES -#define JSON_HAS_RVALUE_REFERENCES 0 -#endif - -#ifdef __clang__ -#if __has_extension(attribute_deprecated_with_message) -#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) -#endif -#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) -#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) -#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) -#elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) -#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) -#endif // GNUC version -#endif // __clang__ || __GNUC__ - -#if !defined(JSONCPP_DEPRECATED) -#define JSONCPP_DEPRECATED(message) -#endif // if !defined(JSONCPP_DEPRECATED) - -#if __GNUC__ >= 6 -#define JSON_USE_INT64_DOUBLE_CONVERSION 1 -#endif - -#if !defined(JSON_IS_AMALGAMATION) - -#include "allocator.h" -#include "version.h" - -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { -typedef int Int; -typedef unsigned int UInt; -#if defined(JSON_NO_INT64) -typedef int LargestInt; -typedef unsigned int LargestUInt; -#undef JSON_HAS_INT64 -#else // if defined(JSON_NO_INT64) -// For Microsoft Visual use specific types as long long is not supported -#if defined(_MSC_VER) // Microsoft Visual Studio -typedef __int64 Int64; -typedef unsigned __int64 UInt64; -#else // if defined(_MSC_VER) // Other platforms, use long long -typedef int64_t Int64; -typedef uint64_t UInt64; -#endif // if defined(_MSC_VER) -typedef Int64 LargestInt; -typedef UInt64 LargestUInt; -#define JSON_HAS_INT64 -#endif // if defined(JSON_NO_INT64) - -template <typename T> -using Allocator = typename std::conditional<JSONCPP_USING_SECURE_MEMORY, - SecureAllocator<T>, - std::allocator<T>>::type; -using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>; -using IStringStream = std::basic_istringstream<String::value_type, - String::traits_type, - String::allocator_type>; -using OStringStream = std::basic_ostringstream<String::value_type, - String::traits_type, - String::allocator_type>; -using IStream = std::istream; -using OStream = std::ostream; -} // namespace Json - -// Legacy names (formerly macros). -using JSONCPP_STRING = Json::String; -using JSONCPP_ISTRINGSTREAM = Json::IStringStream; -using JSONCPP_OSTRINGSTREAM = Json::OStringStream; -using JSONCPP_ISTREAM = Json::IStream; -using JSONCPP_OSTREAM = Json::OStream; - -#endif // JSON_CONFIG_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/config.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/forwards.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_FORWARDS_H_INCLUDED -#define JSON_FORWARDS_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "config.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { - -// writer.h -class FastWriter; -class StyledWriter; - -// reader.h -class Reader; - -// features.h -class Features; - -// value.h -typedef unsigned int ArrayIndex; -class StaticString; -class Path; -class PathArgument; -class Value; -class ValueIteratorBase; -class ValueIterator; -class ValueConstIterator; - -} // namespace Json - -#endif // JSON_FORWARDS_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/forwards.h -// ////////////////////////////////////////////////////////////////////// - - - - - -#endif //ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/jsoncpp-1.8.4/json/json.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2366 +0,0 @@ -/// Json-cpp amalgamated header (http://jsoncpp.sourceforge.net/). -/// It is intended to be used with #include "json/json.h" - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - -/* -The JsonCpp library's source code, including accompanying documentation, -tests and demonstration applications, are licensed under the following -conditions... - -Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all -jurisdictions which recognize such a disclaimer. In such jurisdictions, -this software is released into the Public Domain. - -In jurisdictions which do not recognize Public Domain property (e.g. Germany as of -2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and -The JsonCpp Authors, and is released under the terms of the MIT License (see below). - -In jurisdictions which recognize Public Domain property, the user of this -software may choose to accept it either as 1) Public Domain, 2) under the -conditions of the MIT License (see below), or 3) under the terms of dual -Public Domain/MIT License conditions described here, as they choose. - -The MIT License is about as close to Public Domain as a license can get, and is -described in clear, concise terms at: - - http://en.wikipedia.org/wiki/MIT_License - -The full text of the MIT License follows: - -======================================================================== -Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, copy, -modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -======================================================================== -(END LICENSE TEXT) - -The MIT license is compatible with both the GPL and commercial -software, affording one all of the rights of Public Domain with the -minor nuisance of being required to keep the above copyright notice -and license text in the source code. Note also that by accepting the -Public Domain "license" you can re-license your copy using whatever -license you like. - -*/ - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - - - - - -#ifndef JSON_AMALGAMATED_H_INCLUDED -# define JSON_AMALGAMATED_H_INCLUDED -/// If defined, indicates that the source file is amalgamated -/// to prevent private header inclusion. -#define JSON_IS_AMALGAMATION - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/version.h -// ////////////////////////////////////////////////////////////////////// - -// DO NOT EDIT. This file (and "version") is generated by CMake. -// Run CMake configure step to update it. -#ifndef JSON_VERSION_H_INCLUDED -#define JSON_VERSION_H_INCLUDED - -#define JSONCPP_VERSION_STRING "1.8.4" -#define JSONCPP_VERSION_MAJOR 1 -#define JSONCPP_VERSION_MINOR 8 -#define JSONCPP_VERSION_PATCH 4 -#define JSONCPP_VERSION_QUALIFIER -#define JSONCPP_VERSION_HEXA \ - ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \ - (JSONCPP_VERSION_PATCH << 8)) - -#ifdef JSONCPP_USING_SECURE_MEMORY -#undef JSONCPP_USING_SECURE_MEMORY -#endif -#define JSONCPP_USING_SECURE_MEMORY 0 -// If non-zero, the library zeroes any memory that it has allocated before -// it frees its memory. - -#endif // JSON_VERSION_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/version.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/allocator.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef CPPTL_JSON_ALLOCATOR_H_INCLUDED -#define CPPTL_JSON_ALLOCATOR_H_INCLUDED - -#include <cstring> -#include <memory> - -#pragma pack(push, 8) - -namespace Json { -template <typename T> class SecureAllocator { -public: - // Type definitions - using value_type = T; - using pointer = T*; - using const_pointer = const T*; - using reference = T&; - using const_reference = const T&; - using size_type = std::size_t; - using difference_type = std::ptrdiff_t; - - /** - * Allocate memory for N items using the standard allocator. - */ - pointer allocate(size_type n) { - // allocate using "global operator new" - return static_cast<pointer>(::operator new(n * sizeof(T))); - } - - /** - * Release memory which was allocated for N items at pointer P. - * - * The memory block is filled with zeroes before being released. - * The pointer argument is tagged as "volatile" to prevent the - * compiler optimizing out this critical step. - */ - void deallocate(volatile pointer p, size_type n) { - std::memset(p, 0, n * sizeof(T)); - // free using "global operator delete" - ::operator delete(p); - } - - /** - * Construct an item in-place at pointer P. - */ - template <typename... Args> void construct(pointer p, Args&&... args) { - // construct using "placement new" and "perfect forwarding" - ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...); - } - - size_type max_size() const { return size_t(-1) / sizeof(T); } - - pointer address(reference x) const { return std::addressof(x); } - - const_pointer address(const_reference x) const { return std::addressof(x); } - - /** - * Destroy an item in-place at pointer P. - */ - void destroy(pointer p) { - // destroy using "explicit destructor" - p->~T(); - } - - // Boilerplate - SecureAllocator() {} - template <typename U> SecureAllocator(const SecureAllocator<U>&) {} - template <typename U> struct rebind { using other = SecureAllocator<U>; }; -}; - -template <typename T, typename U> -bool operator==(const SecureAllocator<T>&, const SecureAllocator<U>&) { - return true; -} - -template <typename T, typename U> -bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) { - return false; -} - -} // namespace Json - -#pragma pack(pop) - -#endif // CPPTL_JSON_ALLOCATOR_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/allocator.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/config.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_CONFIG_H_INCLUDED -#define JSON_CONFIG_H_INCLUDED -#include <cstddef> -#include <cstdint> -#include <istream> -#include <memory> -#include <ostream> -#include <sstream> -#include <string> -#include <type_traits> - -/// If defined, indicates that json library is embedded in CppTL library. -//# define JSON_IN_CPPTL 1 - -/// If defined, indicates that json may leverage CppTL library -//# define JSON_USE_CPPTL 1 -/// If defined, indicates that cpptl vector based map should be used instead of -/// std::map -/// as Value container. -//# define JSON_USE_CPPTL_SMALLMAP 1 - -// If non-zero, the library uses exceptions to report bad input instead of C -// assertion macros. The default is to use exceptions. -#ifndef JSON_USE_EXCEPTION -#define JSON_USE_EXCEPTION 1 -#endif - -/// If defined, indicates that the source file is amalgamated -/// to prevent private header inclusion. -/// Remarks: it is automatically defined in the generated amalgamated header. -// #define JSON_IS_AMALGAMATION - -#ifdef JSON_IN_CPPTL -#include <cpptl/config.h> -#ifndef JSON_USE_CPPTL -#define JSON_USE_CPPTL 1 -#endif -#endif - -#ifdef JSON_IN_CPPTL -#define JSON_API CPPTL_API -#elif defined(JSON_DLL_BUILD) -#if defined(_MSC_VER) || defined(__MINGW32__) -#define JSON_API __declspec(dllexport) -#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING -#endif // if defined(_MSC_VER) -#elif defined(JSON_DLL) -#if defined(_MSC_VER) || defined(__MINGW32__) -#define JSON_API __declspec(dllimport) -#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING -#endif // if defined(_MSC_VER) -#endif // ifdef JSON_IN_CPPTL -#if !defined(JSON_API) -#define JSON_API -#endif - -#if defined(_MSC_VER) && _MSC_VER < 1800 -#error \ - "ERROR: Visual Studio 12 (2013) with _MSC_VER=1800 is the oldest supported compiler with sufficient C++11 capabilities" -#endif - -#if defined(_MSC_VER) && _MSC_VER < 1900 -// As recommended at -// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010 -extern JSON_API int -msvc_pre1900_c99_snprintf(char* outBuf, size_t size, const char* format, ...); -#define jsoncpp_snprintf msvc_pre1900_c99_snprintf -#else -#define jsoncpp_snprintf std::snprintf -#endif - -// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for -// integer -// Storages, and 64 bits integer support is disabled. -// #define JSON_NO_INT64 1 - -#if defined(_MSC_VER) // MSVC -#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) -#endif // defined(_MSC_VER) - -// JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools. -// C++11 should be used directly in JSONCPP. -#define JSONCPP_OVERRIDE override - -#if __cplusplus >= 201103L -#define JSONCPP_NOEXCEPT noexcept -#define JSONCPP_OP_EXPLICIT explicit -#elif defined(_MSC_VER) && _MSC_VER < 1900 -#define JSONCPP_NOEXCEPT throw() -#define JSONCPP_OP_EXPLICIT explicit -#elif defined(_MSC_VER) && _MSC_VER >= 1900 -#define JSONCPP_NOEXCEPT noexcept -#define JSONCPP_OP_EXPLICIT explicit -#else -#define JSONCPP_NOEXCEPT throw() -#define JSONCPP_OP_EXPLICIT -#endif - -#ifndef JSON_HAS_RVALUE_REFERENCES - -#if defined(_MSC_VER) -#define JSON_HAS_RVALUE_REFERENCES 1 -#endif // MSVC >= 2013 - -#ifdef __clang__ -#if __has_feature(cxx_rvalue_references) -#define JSON_HAS_RVALUE_REFERENCES 1 -#endif // has_feature - -#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) -#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L) -#define JSON_HAS_RVALUE_REFERENCES 1 -#endif // GXX_EXPERIMENTAL - -#endif // __clang__ || __GNUC__ - -#endif // not defined JSON_HAS_RVALUE_REFERENCES - -#ifndef JSON_HAS_RVALUE_REFERENCES -#define JSON_HAS_RVALUE_REFERENCES 0 -#endif - -#ifdef __clang__ -#if __has_extension(attribute_deprecated_with_message) -#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) -#endif -#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) -#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) -#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) -#elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) -#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) -#endif // GNUC version -#endif // __clang__ || __GNUC__ - -#if !defined(JSONCPP_DEPRECATED) -#define JSONCPP_DEPRECATED(message) -#endif // if !defined(JSONCPP_DEPRECATED) - -#if __GNUC__ >= 6 -#define JSON_USE_INT64_DOUBLE_CONVERSION 1 -#endif - -#if !defined(JSON_IS_AMALGAMATION) - -#include "allocator.h" -#include "version.h" - -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { -typedef int Int; -typedef unsigned int UInt; -#if defined(JSON_NO_INT64) -typedef int LargestInt; -typedef unsigned int LargestUInt; -#undef JSON_HAS_INT64 -#else // if defined(JSON_NO_INT64) -// For Microsoft Visual use specific types as long long is not supported -#if defined(_MSC_VER) // Microsoft Visual Studio -typedef __int64 Int64; -typedef unsigned __int64 UInt64; -#else // if defined(_MSC_VER) // Other platforms, use long long -typedef int64_t Int64; -typedef uint64_t UInt64; -#endif // if defined(_MSC_VER) -typedef Int64 LargestInt; -typedef UInt64 LargestUInt; -#define JSON_HAS_INT64 -#endif // if defined(JSON_NO_INT64) - -template <typename T> -using Allocator = typename std::conditional<JSONCPP_USING_SECURE_MEMORY, - SecureAllocator<T>, - std::allocator<T>>::type; -using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>; -using IStringStream = std::basic_istringstream<String::value_type, - String::traits_type, - String::allocator_type>; -using OStringStream = std::basic_ostringstream<String::value_type, - String::traits_type, - String::allocator_type>; -using IStream = std::istream; -using OStream = std::ostream; -} // namespace Json - -// Legacy names (formerly macros). -using JSONCPP_STRING = Json::String; -using JSONCPP_ISTRINGSTREAM = Json::IStringStream; -using JSONCPP_OSTRINGSTREAM = Json::OStringStream; -using JSONCPP_ISTREAM = Json::IStream; -using JSONCPP_OSTREAM = Json::OStream; - -#endif // JSON_CONFIG_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/config.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/forwards.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_FORWARDS_H_INCLUDED -#define JSON_FORWARDS_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "config.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { - -// writer.h -class FastWriter; -class StyledWriter; - -// reader.h -class Reader; - -// features.h -class Features; - -// value.h -typedef unsigned int ArrayIndex; -class StaticString; -class Path; -class PathArgument; -class Value; -class ValueIteratorBase; -class ValueIterator; -class ValueConstIterator; - -} // namespace Json - -#endif // JSON_FORWARDS_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/forwards.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/features.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef CPPTL_JSON_FEATURES_H_INCLUDED -#define CPPTL_JSON_FEATURES_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "forwards.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -#pragma pack(push, 8) - -namespace Json { - -/** \brief Configuration passed to reader and writer. - * This configuration object can be used to force the Reader or Writer - * to behave in a standard conforming way. - */ -class JSON_API Features { -public: - /** \brief A configuration that allows all features and assumes all strings - * are UTF-8. - * - C & C++ comments are allowed - * - Root object can be any JSON value - * - Assumes Value strings are encoded in UTF-8 - */ - static Features all(); - - /** \brief A configuration that is strictly compatible with the JSON - * specification. - * - Comments are forbidden. - * - Root object must be either an array or an object value. - * - Assumes Value strings are encoded in UTF-8 - */ - static Features strictMode(); - - /** \brief Initialize the configuration like JsonConfig::allFeatures; - */ - Features(); - - /// \c true if comments are allowed. Default: \c true. - bool allowComments_{true}; - - /// \c true if root must be either an array or an object value. Default: \c - /// false. - bool strictRoot_{false}; - - /// \c true if dropped null placeholders are allowed. Default: \c false. - bool allowDroppedNullPlaceholders_{false}; - - /// \c true if numeric object key are allowed. Default: \c false. - bool allowNumericKeys_{false}; -}; - -} // namespace Json - -#pragma pack(pop) - -#endif // CPPTL_JSON_FEATURES_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/features.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/value.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef CPPTL_JSON_H_INCLUDED -#define CPPTL_JSON_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "forwards.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include <exception> -#include <string> -#include <vector> - -#ifndef JSON_USE_CPPTL_SMALLMAP -#include <map> -#else -#include <cpptl/smallmap.h> -#endif -#ifdef JSON_USE_CPPTL -#include <cpptl/forwards.h> -#endif - -// Conditional NORETURN attribute on the throw functions would: -// a) suppress false positives from static code analysis -// b) possibly improve optimization opportunities. -#if !defined(JSONCPP_NORETURN) -#if defined(_MSC_VER) -#define JSONCPP_NORETURN __declspec(noreturn) -#elif defined(__GNUC__) -#define JSONCPP_NORETURN __attribute__((__noreturn__)) -#else -#define JSONCPP_NORETURN -#endif -#endif - -// Disable warning C4251: <data member>: <type> needs to have dll-interface to -// be used by... -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(push) -#pragma warning(disable : 4251) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -#pragma pack(push, 8) - -/** \brief JSON (JavaScript Object Notation). - */ -namespace Json { - -/** Base class for all exceptions we throw. - * - * We use nothing but these internally. Of course, STL can throw others. - */ -class JSON_API Exception : public std::exception { -public: - Exception(String msg); - ~Exception() JSONCPP_NOEXCEPT override; - char const* what() const JSONCPP_NOEXCEPT override; - -protected: - String msg_; -}; - -/** Exceptions which the user cannot easily avoid. - * - * E.g. out-of-memory (when we use malloc), stack-overflow, malicious input - * - * \remark derived from Json::Exception - */ -class JSON_API RuntimeError : public Exception { -public: - RuntimeError(String const& msg); -}; - -/** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros. - * - * These are precondition-violations (user bugs) and internal errors (our bugs). - * - * \remark derived from Json::Exception - */ -class JSON_API LogicError : public Exception { -public: - LogicError(String const& msg); -}; - -/// used internally -JSONCPP_NORETURN void throwRuntimeError(String const& msg); -/// used internally -JSONCPP_NORETURN void throwLogicError(String const& msg); - -/** \brief Type of the value held by a Value object. - */ -enum ValueType { - nullValue = 0, ///< 'null' value - intValue, ///< signed integer value - uintValue, ///< unsigned integer value - realValue, ///< double value - stringValue, ///< UTF-8 string value - booleanValue, ///< bool value - arrayValue, ///< array value (ordered list) - objectValue ///< object value (collection of name/value pairs). -}; - -enum CommentPlacement { - commentBefore = 0, ///< a comment placed on the line before a value - commentAfterOnSameLine, ///< a comment just after a value on the same line - commentAfter, ///< a comment on the line after a value (only make sense for - /// root value) - numberOfCommentPlacement -}; - -/** \brief Type of precision for formatting of real values. - */ -enum PrecisionType { - significantDigits = 0, ///< we set max number of significant digits in string - decimalPlaces ///< we set max number of digits after "." in string -}; - -//# ifdef JSON_USE_CPPTL -// typedef CppTL::AnyEnumerator<const char *> EnumMemberNames; -// typedef CppTL::AnyEnumerator<const Value &> EnumValues; -//# endif - -/** \brief Lightweight wrapper to tag static string. - * - * Value constructor and objectValue member assignment takes advantage of the - * StaticString and avoid the cost of string duplication when storing the - * string or the member name. - * - * Example of usage: - * \code - * Json::Value aValue( StaticString("some text") ); - * Json::Value object; - * static const StaticString code("code"); - * object[code] = 1234; - * \endcode - */ -class JSON_API StaticString { -public: - explicit StaticString(const char* czstring) : c_str_(czstring) {} - - operator const char*() const { return c_str_; } - - const char* c_str() const { return c_str_; } - -private: - const char* c_str_; -}; - -/** \brief Represents a <a HREF="http://www.json.org">JSON</a> value. - * - * This class is a discriminated union wrapper that can represents a: - * - signed integer [range: Value::minInt - Value::maxInt] - * - unsigned integer (range: 0 - Value::maxUInt) - * - double - * - UTF-8 string - * - boolean - * - 'null' - * - an ordered list of Value - * - collection of name/value pairs (javascript object) - * - * The type of the held value is represented by a #ValueType and - * can be obtained using type(). - * - * Values of an #objectValue or #arrayValue can be accessed using operator[]() - * methods. - * Non-const methods will automatically create the a #nullValue element - * if it does not exist. - * The sequence of an #arrayValue will be automatically resized and initialized - * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. - * - * The get() methods can be used to obtain default value in the case the - * required element does not exist. - * - * It is possible to iterate over the list of member keys of an object using - * the getMemberNames() method. - * - * \note #Value string-length fit in size_t, but keys must be < 2^30. - * (The reason is an implementation detail.) A #CharReader will raise an - * exception if a bound is exceeded to avoid security holes in your app, - * but the Value API does *not* check bounds. That is the responsibility - * of the caller. - */ -class JSON_API Value { - friend class ValueIteratorBase; - -public: - typedef std::vector<String> Members; - typedef ValueIterator iterator; - typedef ValueConstIterator const_iterator; - typedef Json::UInt UInt; - typedef Json::Int Int; -#if defined(JSON_HAS_INT64) - typedef Json::UInt64 UInt64; - typedef Json::Int64 Int64; -#endif // defined(JSON_HAS_INT64) - typedef Json::LargestInt LargestInt; - typedef Json::LargestUInt LargestUInt; - typedef Json::ArrayIndex ArrayIndex; - - // Required for boost integration, e. g. BOOST_TEST - typedef std::string value_type; - - static const Value& null; ///< We regret this reference to a global instance; - ///< prefer the simpler Value(). - static const Value& nullRef; ///< just a kludge for binary-compatibility; same - ///< as null - static Value const& nullSingleton(); ///< Prefer this to null or nullRef. - - /// Minimum signed integer value that can be stored in a Json::Value. - static const LargestInt minLargestInt; - /// Maximum signed integer value that can be stored in a Json::Value. - static const LargestInt maxLargestInt; - /// Maximum unsigned integer value that can be stored in a Json::Value. - static const LargestUInt maxLargestUInt; - - /// Minimum signed int value that can be stored in a Json::Value. - static const Int minInt; - /// Maximum signed int value that can be stored in a Json::Value. - static const Int maxInt; - /// Maximum unsigned int value that can be stored in a Json::Value. - static const UInt maxUInt; - -#if defined(JSON_HAS_INT64) - /// Minimum signed 64 bits int value that can be stored in a Json::Value. - static const Int64 minInt64; - /// Maximum signed 64 bits int value that can be stored in a Json::Value. - static const Int64 maxInt64; - /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. - static const UInt64 maxUInt64; -#endif // defined(JSON_HAS_INT64) - - /// Default precision for real value for string representation. - static const UInt defaultRealPrecision; - -// Workaround for bug in the NVIDIAs CUDA 9.1 nvcc compiler -// when using gcc and clang backend compilers. CZString -// cannot be defined as private. See issue #486 -#ifdef __NVCC__ -public: -#else -private: -#endif -#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - class CZString { - public: - enum DuplicationPolicy { noDuplication = 0, duplicate, duplicateOnCopy }; - CZString(ArrayIndex index); - CZString(char const* str, unsigned length, DuplicationPolicy allocate); - CZString(CZString const& other); -#if JSON_HAS_RVALUE_REFERENCES - CZString(CZString&& other); -#endif - ~CZString(); - CZString& operator=(const CZString& other); - -#if JSON_HAS_RVALUE_REFERENCES - CZString& operator=(CZString&& other); -#endif - - bool operator<(CZString const& other) const; - bool operator==(CZString const& other) const; - ArrayIndex index() const; - // const char* c_str() const; ///< \deprecated - char const* data() const; - unsigned length() const; - bool isStaticString() const; - - private: - void swap(CZString& other); - - struct StringStorage { - unsigned policy_ : 2; - unsigned length_ : 30; // 1GB max - }; - - char const* cstr_; // actually, a prefixed string, unless policy is noDup - union { - ArrayIndex index_; - StringStorage storage_; - }; - }; - -public: -#ifndef JSON_USE_CPPTL_SMALLMAP - typedef std::map<CZString, Value> ObjectValues; -#else - typedef CppTL::SmallMap<CZString, Value> ObjectValues; -#endif // ifndef JSON_USE_CPPTL_SMALLMAP -#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - -public: - /** \brief Create a default Value of the given type. - - This is a very useful constructor. - To create an empty array, pass arrayValue. - To create an empty object, pass objectValue. - Another Value can then be set to this one by assignment. -This is useful since clear() and resize() will not alter types. - - Examples: -\code -Json::Value null_value; // null -Json::Value arr_value(Json::arrayValue); // [] -Json::Value obj_value(Json::objectValue); // {} -\endcode - */ - Value(ValueType type = nullValue); - Value(Int value); - Value(UInt value); -#if defined(JSON_HAS_INT64) - Value(Int64 value); - Value(UInt64 value); -#endif // if defined(JSON_HAS_INT64) - Value(double value); - Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.) - Value(const char* begin, const char* end); ///< Copy all, incl zeroes. - /** \brief Constructs a value from a static string. - - * Like other value string constructor but do not duplicate the string for - * internal storage. The given string must remain alive after the call to this - * constructor. - * \note This works only for null-terminated strings. (We cannot change the - * size of this class, so we have nowhere to store the length, - * which might be computed later for various operations.) - * - * Example of usage: - * \code - * static StaticString foo("some text"); - * Json::Value aValue(foo); - * \endcode - */ - Value(const StaticString& value); - Value(const String& value); ///< Copy data() til size(). Embedded - ///< zeroes too. -#ifdef JSON_USE_CPPTL - Value(const CppTL::ConstString& value); -#endif - Value(bool value); - Value(const Value& other); - Value(Value&& other); - ~Value(); - - /// \note Overwrite existing comments. To preserve comments, use - /// #swapPayload(). - Value& operator=(const Value& other); - Value& operator=(Value&& other); - - /// Swap everything. - void swap(Value& other); - /// Swap values but leave comments and source offsets in place. - void swapPayload(Value& other); - - /// copy everything. - void copy(const Value& other); - /// copy values but leave comments and source offsets in place. - void copyPayload(const Value& other); - - ValueType type() const; - - /// Compare payload only, not comments etc. - bool operator<(const Value& other) const; - bool operator<=(const Value& other) const; - bool operator>=(const Value& other) const; - bool operator>(const Value& other) const; - bool operator==(const Value& other) const; - bool operator!=(const Value& other) const; - int compare(const Value& other) const; - - const char* asCString() const; ///< Embedded zeroes could cause you trouble! -#if JSONCPP_USING_SECURE_MEMORY - unsigned getCStringLength() const; // Allows you to understand the length of - // the CString -#endif - String asString() const; ///< Embedded zeroes are possible. - /** Get raw char* of string-value. - * \return false if !string. (Seg-fault if str or end are NULL.) - */ - bool getString(char const** begin, char const** end) const; -#ifdef JSON_USE_CPPTL - CppTL::ConstString asConstString() const; -#endif - Int asInt() const; - UInt asUInt() const; -#if defined(JSON_HAS_INT64) - Int64 asInt64() const; - UInt64 asUInt64() const; -#endif // if defined(JSON_HAS_INT64) - LargestInt asLargestInt() const; - LargestUInt asLargestUInt() const; - float asFloat() const; - double asDouble() const; - bool asBool() const; - - bool isNull() const; - bool isBool() const; - bool isInt() const; - bool isInt64() const; - bool isUInt() const; - bool isUInt64() const; - bool isIntegral() const; - bool isDouble() const; - bool isNumeric() const; - bool isString() const; - bool isArray() const; - bool isObject() const; - - bool isConvertibleTo(ValueType other) const; - - /// Number of values in array or object - ArrayIndex size() const; - - /// \brief Return true if empty array, empty object, or null; - /// otherwise, false. - bool empty() const; - - /// Return !isNull() - JSONCPP_OP_EXPLICIT operator bool() const; - - /// Remove all object members and array elements. - /// \pre type() is arrayValue, objectValue, or nullValue - /// \post type() is unchanged - void clear(); - - /// Resize the array to newSize elements. - /// New elements are initialized to null. - /// May only be called on nullValue or arrayValue. - /// \pre type() is arrayValue or nullValue - /// \post type() is arrayValue - void resize(ArrayIndex newSize); - - /// Access an array element (zero based index ). - /// If the array contains less than index element, then null value are - /// inserted - /// in the array so that its size is index+1. - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - Value& operator[](ArrayIndex index); - - /// Access an array element (zero based index ). - /// If the array contains less than index element, then null value are - /// inserted - /// in the array so that its size is index+1. - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - Value& operator[](int index); - - /// Access an array element (zero based index ) - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - const Value& operator[](ArrayIndex index) const; - - /// Access an array element (zero based index ) - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - const Value& operator[](int index) const; - - /// If the array contains at least index+1 elements, returns the element - /// value, - /// otherwise returns defaultValue. - Value get(ArrayIndex index, const Value& defaultValue) const; - /// Return true if index < size(). - bool isValidIndex(ArrayIndex index) const; - /// \brief Append value to array at the end. - /// - /// Equivalent to jsonvalue[jsonvalue.size()] = value; - Value& append(const Value& value); - -#if JSON_HAS_RVALUE_REFERENCES - Value& append(Value&& value); -#endif - - /// Access an object value by name, create a null member if it does not exist. - /// \note Because of our implementation, keys are limited to 2^30 -1 chars. - /// Exceeding that will cause an exception. - Value& operator[](const char* key); - /// Access an object value by name, returns null if there is no member with - /// that name. - const Value& operator[](const char* key) const; - /// Access an object value by name, create a null member if it does not exist. - /// \param key may contain embedded nulls. - Value& operator[](const String& key); - /// Access an object value by name, returns null if there is no member with - /// that name. - /// \param key may contain embedded nulls. - const Value& operator[](const String& key) const; - /** \brief Access an object value by name, create a null member if it does not - exist. - - * If the object has no entry for that name, then the member name used to - store - * the new entry is not duplicated. - * Example of use: - * \code - * Json::Value object; - * static const StaticString code("code"); - * object[code] = 1234; - * \endcode - */ - Value& operator[](const StaticString& key); -#ifdef JSON_USE_CPPTL - /// Access an object value by name, create a null member if it does not exist. - Value& operator[](const CppTL::ConstString& key); - /// Access an object value by name, returns null if there is no member with - /// that name. - const Value& operator[](const CppTL::ConstString& key) const; -#endif - /// Return the member named key if it exist, defaultValue otherwise. - /// \note deep copy - Value get(const char* key, const Value& defaultValue) const; - /// Return the member named key if it exist, defaultValue otherwise. - /// \note deep copy - /// \note key may contain embedded nulls. - Value - get(const char* begin, const char* end, const Value& defaultValue) const; - /// Return the member named key if it exist, defaultValue otherwise. - /// \note deep copy - /// \param key may contain embedded nulls. - Value get(const String& key, const Value& defaultValue) const; -#ifdef JSON_USE_CPPTL - /// Return the member named key if it exist, defaultValue otherwise. - /// \note deep copy - Value get(const CppTL::ConstString& key, const Value& defaultValue) const; -#endif - /// Most general and efficient version of isMember()const, get()const, - /// and operator[]const - /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 - Value const* find(char const* begin, char const* end) const; - /// Most general and efficient version of object-mutators. - /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 - /// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue. - Value const* demand(char const* begin, char const* end); - /// \brief Remove and return the named member. - /// - /// Do nothing if it did not exist. - /// \pre type() is objectValue or nullValue - /// \post type() is unchanged - void removeMember(const char* key); - /// Same as removeMember(const char*) - /// \param key may contain embedded nulls. - void removeMember(const String& key); - /// Same as removeMember(const char* begin, const char* end, Value* removed), - /// but 'key' is null-terminated. - bool removeMember(const char* key, Value* removed); - /** \brief Remove the named map member. - - Update 'removed' iff removed. - \param key may contain embedded nulls. - \return true iff removed (no exceptions) - */ - bool removeMember(String const& key, Value* removed); - /// Same as removeMember(String const& key, Value* removed) - bool removeMember(const char* begin, const char* end, Value* removed); - /** \brief Remove the indexed array element. - - O(n) expensive operations. - Update 'removed' iff removed. - \return true if removed (no exceptions) - */ - bool removeIndex(ArrayIndex index, Value* removed); - - /// Return true if the object has a member named key. - /// \note 'key' must be null-terminated. - bool isMember(const char* key) const; - /// Return true if the object has a member named key. - /// \param key may contain embedded nulls. - bool isMember(const String& key) const; - /// Same as isMember(String const& key)const - bool isMember(const char* begin, const char* end) const; -#ifdef JSON_USE_CPPTL - /// Return true if the object has a member named key. - bool isMember(const CppTL::ConstString& key) const; -#endif - - /// \brief Return a list of the member names. - /// - /// If null, return an empty list. - /// \pre type() is objectValue or nullValue - /// \post if type() was nullValue, it remains nullValue - Members getMemberNames() const; - - //# ifdef JSON_USE_CPPTL - // EnumMemberNames enumMemberNames() const; - // EnumValues enumValues() const; - //# endif - - /// \deprecated Always pass len. - JSONCPP_DEPRECATED("Use setComment(String const&) instead.") - void setComment(const char* comment, CommentPlacement placement); - /// Comments must be //... or /* ... */ - void setComment(const char* comment, size_t len, CommentPlacement placement); - /// Comments must be //... or /* ... */ - void setComment(const String& comment, CommentPlacement placement); - bool hasComment(CommentPlacement placement) const; - /// Include delimiters and embedded newlines. - String getComment(CommentPlacement placement) const; - - String toStyledString() const; - - const_iterator begin() const; - const_iterator end() const; - - iterator begin(); - iterator end(); - - // Accessors for the [start, limit) range of bytes within the JSON text from - // which this value was parsed, if any. - void setOffsetStart(ptrdiff_t start); - void setOffsetLimit(ptrdiff_t limit); - ptrdiff_t getOffsetStart() const; - ptrdiff_t getOffsetLimit() const; - -private: - void setType(ValueType v) { bits_.value_type_ = v; } - bool isAllocated() const { return bits_.allocated_; } - void setIsAllocated(bool v) { bits_.allocated_ = v; } - - void initBasic(ValueType type, bool allocated = false); - void dupPayload(const Value& other); - void releasePayload(); - void dupMeta(const Value& other); - - Value& resolveReference(const char* key); - Value& resolveReference(const char* key, const char* end); - - struct CommentInfo { - CommentInfo(); - ~CommentInfo(); - - void setComment(const char* text, size_t len); - - char* comment_{nullptr}; - }; - - // struct MemberNamesTransform - //{ - // typedef const char *result_type; - // const char *operator()( const CZString &name ) const - // { - // return name.c_str(); - // } - //}; - - union ValueHolder { - LargestInt int_; - LargestUInt uint_; - double real_; - bool bool_; - char* string_; // if allocated_, ptr to { unsigned, char[] }. - ObjectValues* map_; - } value_; - - struct { - // Really a ValueType, but types should agree for bitfield packing. - unsigned int value_type_ : 8; - // Unless allocated_, string_ must be null-terminated. - unsigned int allocated_ : 1; - } bits_; - - CommentInfo* comments_; - - // [start, limit) byte offsets in the source JSON text from which this Value - // was extracted. - ptrdiff_t start_; - ptrdiff_t limit_; -}; - -/** \brief Experimental and untested: represents an element of the "path" to - * access a node. - */ -class JSON_API PathArgument { -public: - friend class Path; - - PathArgument(); - PathArgument(ArrayIndex index); - PathArgument(const char* key); - PathArgument(const String& key); - -private: - enum Kind { kindNone = 0, kindIndex, kindKey }; - String key_; - ArrayIndex index_{}; - Kind kind_{kindNone}; -}; - -/** \brief Experimental and untested: represents a "path" to access a node. - * - * Syntax: - * - "." => root node - * - ".[n]" => elements at index 'n' of root node (an array value) - * - ".name" => member named 'name' of root node (an object value) - * - ".name1.name2.name3" - * - ".[0][1][2].name1[3]" - * - ".%" => member name is provided as parameter - * - ".[%]" => index is provied as parameter - */ -class JSON_API Path { -public: - Path(const String& path, - const PathArgument& a1 = PathArgument(), - const PathArgument& a2 = PathArgument(), - const PathArgument& a3 = PathArgument(), - const PathArgument& a4 = PathArgument(), - const PathArgument& a5 = PathArgument()); - - const Value& resolve(const Value& root) const; - Value resolve(const Value& root, const Value& defaultValue) const; - /// Creates the "path" to access the specified node and returns a reference on - /// the node. - Value& make(Value& root) const; - -private: - typedef std::vector<const PathArgument*> InArgs; - typedef std::vector<PathArgument> Args; - - void makePath(const String& path, const InArgs& in); - void addPathInArg(const String& path, - const InArgs& in, - InArgs::const_iterator& itInArg, - PathArgument::Kind kind); - static void invalidPath(const String& path, int location); - - Args args_; -}; - -/** \brief base class for Value iterators. - * - */ -class JSON_API ValueIteratorBase { -public: - typedef std::bidirectional_iterator_tag iterator_category; - typedef unsigned int size_t; - typedef int difference_type; - typedef ValueIteratorBase SelfType; - - bool operator==(const SelfType& other) const { return isEqual(other); } - - bool operator!=(const SelfType& other) const { return !isEqual(other); } - - difference_type operator-(const SelfType& other) const { - return other.computeDistance(*this); - } - - /// Return either the index or the member name of the referenced value as a - /// Value. - Value key() const; - - /// Return the index of the referenced Value, or -1 if it is not an - /// arrayValue. - UInt index() const; - - /// Return the member name of the referenced Value, or "" if it is not an - /// objectValue. - /// \note Avoid `c_str()` on result, as embedded zeroes are possible. - String name() const; - - /// Return the member name of the referenced Value. "" if it is not an - /// objectValue. - /// \deprecated This cannot be used for UTF-8 strings, since there can be - /// embedded nulls. - JSONCPP_DEPRECATED("Use `key = name();` instead.") - char const* memberName() const; - /// Return the member name of the referenced Value, or NULL if it is not an - /// objectValue. - /// \note Better version than memberName(). Allows embedded nulls. - char const* memberName(char const** end) const; - -protected: - Value& deref() const; - - void increment(); - - void decrement(); - - difference_type computeDistance(const SelfType& other) const; - - bool isEqual(const SelfType& other) const; - - void copy(const SelfType& other); - -private: - Value::ObjectValues::iterator current_; - // Indicates that iterator is for a null value. - bool isNull_{true}; - -public: - // For some reason, BORLAND needs these at the end, rather - // than earlier. No idea why. - ValueIteratorBase(); - explicit ValueIteratorBase(const Value::ObjectValues::iterator& current); -}; - -/** \brief const iterator for object and array value. - * - */ -class JSON_API ValueConstIterator : public ValueIteratorBase { - friend class Value; - -public: - typedef const Value value_type; - // typedef unsigned int size_t; - // typedef int difference_type; - typedef const Value& reference; - typedef const Value* pointer; - typedef ValueConstIterator SelfType; - - ValueConstIterator(); - ValueConstIterator(ValueIterator const& other); - -private: - /*! \internal Use by Value to create an iterator. - */ - explicit ValueConstIterator(const Value::ObjectValues::iterator& current); - -public: - SelfType& operator=(const ValueIteratorBase& other); - - SelfType operator++(int) { - SelfType temp(*this); - ++*this; - return temp; - } - - SelfType operator--(int) { - SelfType temp(*this); - --*this; - return temp; - } - - SelfType& operator--() { - decrement(); - return *this; - } - - SelfType& operator++() { - increment(); - return *this; - } - - reference operator*() const { return deref(); } - - pointer operator->() const { return &deref(); } -}; - -/** \brief Iterator for object and array value. - */ -class JSON_API ValueIterator : public ValueIteratorBase { - friend class Value; - -public: - typedef Value value_type; - typedef unsigned int size_t; - typedef int difference_type; - typedef Value& reference; - typedef Value* pointer; - typedef ValueIterator SelfType; - - ValueIterator(); - explicit ValueIterator(const ValueConstIterator& other); - ValueIterator(const ValueIterator& other); - -private: - /*! \internal Use by Value to create an iterator. - */ - explicit ValueIterator(const Value::ObjectValues::iterator& current); - -public: - SelfType& operator=(const SelfType& other); - - SelfType operator++(int) { - SelfType temp(*this); - ++*this; - return temp; - } - - SelfType operator--(int) { - SelfType temp(*this); - --*this; - return temp; - } - - SelfType& operator--() { - decrement(); - return *this; - } - - SelfType& operator++() { - increment(); - return *this; - } - - reference operator*() const { return deref(); } - - pointer operator->() const { return &deref(); } -}; - -inline void swap(Value& a, Value& b) { a.swap(b); } - -} // namespace Json - -#pragma pack(pop) - -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(pop) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -#endif // CPPTL_JSON_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/value.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/reader.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef CPPTL_JSON_READER_H_INCLUDED -#define CPPTL_JSON_READER_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "features.h" -#include "value.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include <deque> -#include <iosfwd> -#include <istream> -#include <stack> -#include <string> - -// Disable warning C4251: <data member>: <type> needs to have dll-interface to -// be used by... -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(push) -#pragma warning(disable : 4251) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -#pragma pack(push, 8) - -namespace Json { - -/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a - *Value. - * - * \deprecated Use CharReader and CharReaderBuilder. - */ -class JSON_API Reader { -public: - typedef char Char; - typedef const Char* Location; - - /** \brief An error tagged with where in the JSON text it was encountered. - * - * The offsets give the [start, limit) range of bytes within the text. Note - * that this is bytes, not codepoints. - * - */ - struct StructuredError { - ptrdiff_t offset_start; - ptrdiff_t offset_limit; - String message; - }; - - /** \brief Constructs a Reader allowing all features - * for parsing. - */ - JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") - Reader(); - - /** \brief Constructs a Reader allowing the specified feature set - * for parsing. - */ - JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") - Reader(const Features& features); - - /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> - * document. - * \param document UTF-8 encoded string containing the document to read. - * \param root [out] Contains the root value of the document if it was - * successfully parsed. - * \param collectComments \c true to collect comment and allow writing them - * back during - * serialization, \c false to discard comments. - * This parameter is ignored if - * Features::allowComments_ - * is \c false. - * \return \c true if the document was successfully parsed, \c false if an - * error occurred. - */ - bool - parse(const std::string& document, Value& root, bool collectComments = true); - - /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> - document. - * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the - document to read. - * \param endDoc Pointer on the end of the UTF-8 encoded string of the - document to read. - * Must be >= beginDoc. - * \param root [out] Contains the root value of the document if it was - * successfully parsed. - * \param collectComments \c true to collect comment and allow writing them - back during - * serialization, \c false to discard comments. - * This parameter is ignored if - Features::allowComments_ - * is \c false. - * \return \c true if the document was successfully parsed, \c false if an - error occurred. - */ - bool parse(const char* beginDoc, - const char* endDoc, - Value& root, - bool collectComments = true); - - /// \brief Parse from input stream. - /// \see Json::operator>>(std::istream&, Json::Value&). - bool parse(IStream& is, Value& root, bool collectComments = true); - - /** \brief Returns a user friendly string that list errors in the parsed - * document. - * \return Formatted error message with the list of errors with their location - * in - * the parsed document. An empty string is returned if no error - * occurred - * during parsing. - * \deprecated Use getFormattedErrorMessages() instead (typo fix). - */ - JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.") - String getFormatedErrorMessages() const; - - /** \brief Returns a user friendly string that list errors in the parsed - * document. - * \return Formatted error message with the list of errors with their location - * in - * the parsed document. An empty string is returned if no error - * occurred - * during parsing. - */ - String getFormattedErrorMessages() const; - - /** \brief Returns a vector of structured erros encounted while parsing. - * \return A (possibly empty) vector of StructuredError objects. Currently - * only one error can be returned, but the caller should tolerate - * multiple - * errors. This can occur if the parser recovers from a non-fatal - * parse error and then encounters additional errors. - */ - std::vector<StructuredError> getStructuredErrors() const; - - /** \brief Add a semantic error message. - * \param value JSON Value location associated with the error - * \param message The error message. - * \return \c true if the error was successfully added, \c false if the - * Value offset exceeds the document size. - */ - bool pushError(const Value& value, const String& message); - - /** \brief Add a semantic error message with extra context. - * \param value JSON Value location associated with the error - * \param message The error message. - * \param extra Additional JSON Value location to contextualize the error - * \return \c true if the error was successfully added, \c false if either - * Value offset exceeds the document size. - */ - bool pushError(const Value& value, const String& message, const Value& extra); - - /** \brief Return whether there are any errors. - * \return \c true if there are no errors to report \c false if - * errors have occurred. - */ - bool good() const; - -private: - enum TokenType { - tokenEndOfStream = 0, - tokenObjectBegin, - tokenObjectEnd, - tokenArrayBegin, - tokenArrayEnd, - tokenString, - tokenNumber, - tokenTrue, - tokenFalse, - tokenNull, - tokenArraySeparator, - tokenMemberSeparator, - tokenComment, - tokenError - }; - - class Token { - public: - TokenType type_; - Location start_; - Location end_; - }; - - class ErrorInfo { - public: - Token token_; - String message_; - Location extra_; - }; - - typedef std::deque<ErrorInfo> Errors; - - bool readToken(Token& token); - void skipSpaces(); - bool match(Location pattern, int patternLength); - bool readComment(); - bool readCStyleComment(); - bool readCppStyleComment(); - bool readString(); - void readNumber(); - bool readValue(); - bool readObject(Token& token); - bool readArray(Token& token); - bool decodeNumber(Token& token); - bool decodeNumber(Token& token, Value& decoded); - bool decodeString(Token& token); - bool decodeString(Token& token, String& decoded); - bool decodeDouble(Token& token); - bool decodeDouble(Token& token, Value& decoded); - bool decodeUnicodeCodePoint(Token& token, - Location& current, - Location end, - unsigned int& unicode); - bool decodeUnicodeEscapeSequence(Token& token, - Location& current, - Location end, - unsigned int& unicode); - bool addError(const String& message, Token& token, Location extra = nullptr); - bool recoverFromError(TokenType skipUntilToken); - bool addErrorAndRecover(const String& message, - Token& token, - TokenType skipUntilToken); - void skipUntilSpace(); - Value& currentValue(); - Char getNextChar(); - void - getLocationLineAndColumn(Location location, int& line, int& column) const; - String getLocationLineAndColumn(Location location) const; - void addComment(Location begin, Location end, CommentPlacement placement); - void skipCommentTokens(Token& token); - - static bool containsNewLine(Location begin, Location end); - static String normalizeEOL(Location begin, Location end); - - typedef std::stack<Value*> Nodes; - Nodes nodes_; - Errors errors_; - String document_; - Location begin_{}; - Location end_{}; - Location current_{}; - Location lastValueEnd_{}; - Value* lastValue_{}; - String commentsBefore_; - Features features_; - bool collectComments_{}; -}; // Reader - -/** Interface for reading JSON from a char array. - */ -class JSON_API CharReader { -public: - virtual ~CharReader() = default; - /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> - document. - * The document must be a UTF-8 encoded string containing the document to - read. - * - * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the - document to read. - * \param endDoc Pointer on the end of the UTF-8 encoded string of the - document to read. - * Must be >= beginDoc. - * \param root [out] Contains the root value of the document if it was - * successfully parsed. - * \param errs [out] Formatted error messages (if not NULL) - * a user friendly string that lists errors in the parsed - * document. - * \return \c true if the document was successfully parsed, \c false if an - error occurred. - */ - virtual bool parse(char const* beginDoc, - char const* endDoc, - Value* root, - String* errs) = 0; - - class JSON_API Factory { - public: - virtual ~Factory() = default; - /** \brief Allocate a CharReader via operator new(). - * \throw std::exception if something goes wrong (e.g. invalid settings) - */ - virtual CharReader* newCharReader() const = 0; - }; // Factory -}; // CharReader - -/** \brief Build a CharReader implementation. - -Usage: -\code - using namespace Json; - CharReaderBuilder builder; - builder["collectComments"] = false; - Value value; - String errs; - bool ok = parseFromStream(builder, std::cin, &value, &errs); -\endcode -*/ -class JSON_API CharReaderBuilder : public CharReader::Factory { -public: - // Note: We use a Json::Value so that we can add data-members to this class - // without a major version bump. - /** Configuration of this builder. - These are case-sensitive. - Available settings (case-sensitive): - - `"collectComments": false or true` - - true to collect comment and allow writing them - back during serialization, false to discard comments. - This parameter is ignored if allowComments is false. - - `"allowComments": false or true` - - true if comments are allowed. - - `"strictRoot": false or true` - - true if root must be either an array or an object value - - `"allowDroppedNullPlaceholders": false or true` - - true if dropped null placeholders are allowed. (See - StreamWriterBuilder.) - - `"allowNumericKeys": false or true` - - true if numeric object keys are allowed. - - `"allowSingleQuotes": false or true` - - true if '' are allowed for strings (both keys and values) - - `"stackLimit": integer` - - Exceeding stackLimit (recursive depth of `readValue()`) will - cause an exception. - - This is a security issue (seg-faults caused by deeply nested JSON), - so the default is low. - - `"failIfExtra": false or true` - - If true, `parse()` returns false when extra non-whitespace trails - the JSON value in the input string. - - `"rejectDupKeys": false or true` - - If true, `parse()` returns false when a key is duplicated within an - object. - - `"allowSpecialFloats": false or true` - - If true, special float values (NaNs and infinities) are allowed - and their values are lossfree restorable. - - You can examine 'settings_` yourself - to see the defaults. You can also write and read them just like any - JSON Value. - \sa setDefaults() - */ - Json::Value settings_; - - CharReaderBuilder(); - ~CharReaderBuilder() override; - - CharReader* newCharReader() const override; - - /** \return true if 'settings' are legal and consistent; - * otherwise, indicate bad settings via 'invalid'. - */ - bool validate(Json::Value* invalid) const; - - /** A simple way to update a specific setting. - */ - Value& operator[](const String& key); - - /** Called by ctor, but you can use this to reset settings_. - * \pre 'settings' != NULL (but Json::null is fine) - * \remark Defaults: - * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults - */ - static void setDefaults(Json::Value* settings); - /** Same as old Features::strictMode(). - * \pre 'settings' != NULL (but Json::null is fine) - * \remark Defaults: - * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode - */ - static void strictMode(Json::Value* settings); -}; - -/** Consume entire stream and use its begin/end. - * Someday we might have a real StreamReader, but for now this - * is convenient. - */ -bool JSON_API parseFromStream(CharReader::Factory const&, - IStream&, - Value* root, - std::string* errs); - -/** \brief Read from 'sin' into 'root'. - - Always keep comments from the input JSON. - - This can be used to read a file into a particular sub-object. - For example: - \code - Json::Value root; - cin >> root["dir"]["file"]; - cout << root; - \endcode - Result: - \verbatim - { - "dir": { - "file": { - // The input stream JSON would be nested here. - } - } - } - \endverbatim - \throw std::exception on parse error. - \see Json::operator<<() -*/ -JSON_API IStream& operator>>(IStream&, Value&); - -} // namespace Json - -#pragma pack(pop) - -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(pop) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -#endif // CPPTL_JSON_READER_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/reader.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/writer.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_WRITER_H_INCLUDED -#define JSON_WRITER_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "value.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include <ostream> -#include <string> -#include <vector> - -// Disable warning C4251: <data member>: <type> needs to have dll-interface to -// be used by... -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) && defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable : 4251) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -#pragma pack(push, 8) - -namespace Json { - -class Value; - -/** - -Usage: -\code - using namespace Json; - void writeToStdout(StreamWriter::Factory const& factory, Value const& value) { - std::unique_ptr<StreamWriter> const writer( - factory.newStreamWriter()); - writer->write(value, &std::cout); - std::cout << std::endl; // add lf and flush - } -\endcode -*/ -class JSON_API StreamWriter { -protected: - OStream* sout_; // not owned; will not delete -public: - StreamWriter(); - virtual ~StreamWriter(); - /** Write Value into document as configured in sub-class. - Do not take ownership of sout, but maintain a reference during function. - \pre sout != NULL - \return zero on success (For now, we always return zero, so check the - stream instead.) \throw std::exception possibly, depending on configuration - */ - virtual int write(Value const& root, OStream* sout) = 0; - - /** \brief A simple abstract factory. - */ - class JSON_API Factory { - public: - virtual ~Factory(); - /** \brief Allocate a CharReader via operator new(). - * \throw std::exception if something goes wrong (e.g. invalid settings) - */ - virtual StreamWriter* newStreamWriter() const = 0; - }; // Factory -}; // StreamWriter - -/** \brief Write into stringstream, then return string, for convenience. - * A StreamWriter will be created from the factory, used, and then deleted. - */ -String JSON_API writeString(StreamWriter::Factory const& factory, - Value const& root); - -/** \brief Build a StreamWriter implementation. - -Usage: -\code - using namespace Json; - Value value = ...; - StreamWriterBuilder builder; - builder["commentStyle"] = "None"; - builder["indentation"] = " "; // or whatever you like - std::unique_ptr<Json::StreamWriter> writer( - builder.newStreamWriter()); - writer->write(value, &std::cout); - std::cout << std::endl; // add lf and flush -\endcode -*/ -class JSON_API StreamWriterBuilder : public StreamWriter::Factory { -public: - // Note: We use a Json::Value so that we can add data-members to this class - // without a major version bump. - /** Configuration of this builder. - Available settings (case-sensitive): - - "commentStyle": "None" or "All" - - "indentation": "<anything>". - - Setting this to an empty string also omits newline characters. - - "enableYAMLCompatibility": false or true - - slightly change the whitespace around colons - - "dropNullPlaceholders": false or true - - Drop the "null" string from the writer's output for nullValues. - Strictly speaking, this is not valid JSON. But when the output is being - fed to a browser's JavaScript, it makes for smaller output and the - browser can handle the output just fine. - - "useSpecialFloats": false or true - - If true, outputs non-finite floating point values in the following way: - NaN values as "NaN", positive infinity as "Infinity", and negative - infinity as "-Infinity". - - "precision": int - - Number of precision digits for formatting of real values. - - "precisionType": "significant"(default) or "decimal" - - Type of precision for formatting of real values. - - You can examine 'settings_` yourself - to see the defaults. You can also write and read them just like any - JSON Value. - \sa setDefaults() - */ - Json::Value settings_; - - StreamWriterBuilder(); - ~StreamWriterBuilder() override; - - /** - * \throw std::exception if something goes wrong (e.g. invalid settings) - */ - StreamWriter* newStreamWriter() const override; - - /** \return true if 'settings' are legal and consistent; - * otherwise, indicate bad settings via 'invalid'. - */ - bool validate(Json::Value* invalid) const; - /** A simple way to update a specific setting. - */ - Value& operator[](const String& key); - - /** Called by ctor, but you can use this to reset settings_. - * \pre 'settings' != NULL (but Json::null is fine) - * \remark Defaults: - * \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults - */ - static void setDefaults(Json::Value* settings); -}; - -/** \brief Abstract class for writers. - * \deprecated Use StreamWriter. (And really, this is an implementation detail.) - */ -class JSONCPP_DEPRECATED("Use StreamWriter instead") JSON_API Writer { -public: - virtual ~Writer(); - - virtual String write(const Value& root) = 0; -}; - -/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format - *without formatting (not human friendly). - * - * The JSON document is written in a single line. It is not intended for 'human' - *consumption, - * but may be useful to support feature such as RPC where bandwidth is limited. - * \sa Reader, Value - * \deprecated Use StreamWriterBuilder. - */ -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable : 4996) // Deriving from deprecated class -#endif -class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter - : public Writer { -public: - FastWriter(); - ~FastWriter() override = default; - - void enableYAMLCompatibility(); - - /** \brief Drop the "null" string from the writer's output for nullValues. - * Strictly speaking, this is not valid JSON. But when the output is being - * fed to a browser's JavaScript, it makes for smaller output and the - * browser can handle the output just fine. - */ - void dropNullPlaceholders(); - - void omitEndingLineFeed(); - -public: // overridden from Writer - String write(const Value& root) override; - -private: - void writeValue(const Value& value); - - String document_; - bool yamlCompatibilityEnabled_{false}; - bool dropNullPlaceholders_{false}; - bool omitEndingLineFeed_{false}; -}; -#if defined(_MSC_VER) -#pragma warning(pop) -#endif - -/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a - *human friendly way. - * - * The rules for line break and indent are as follow: - * - Object value: - * - if empty then print {} without indent and line break - * - if not empty the print '{', line break & indent, print one value per - *line - * and then unindent and line break and print '}'. - * - Array value: - * - if empty then print [] without indent and line break - * - if the array contains no object value, empty array or some other value - *types, - * and all the values fit on one lines, then print the array on a single - *line. - * - otherwise, it the values do not fit on one line, or the array contains - * object or non empty array, then print one value per line. - * - * If the Value have comments then they are outputed according to their - *#CommentPlacement. - * - * \sa Reader, Value, Value::setComment() - * \deprecated Use StreamWriterBuilder. - */ -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable : 4996) // Deriving from deprecated class -#endif -class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API - StyledWriter : public Writer { -public: - StyledWriter(); - ~StyledWriter() override = default; - -public: // overridden from Writer - /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format. - * \param root Value to serialize. - * \return String containing the JSON document that represents the root value. - */ - String write(const Value& root) override; - -private: - void writeValue(const Value& value); - void writeArrayValue(const Value& value); - bool isMultilineArray(const Value& value); - void pushValue(const String& value); - void writeIndent(); - void writeWithIndent(const String& value); - void indent(); - void unindent(); - void writeCommentBeforeValue(const Value& root); - void writeCommentAfterValueOnSameLine(const Value& root); - static bool hasCommentForValue(const Value& value); - static String normalizeEOL(const String& text); - - typedef std::vector<String> ChildValues; - - ChildValues childValues_; - String document_; - String indentString_; - unsigned int rightMargin_{74}; - unsigned int indentSize_{3}; - bool addChildValues_{false}; -}; -#if defined(_MSC_VER) -#pragma warning(pop) -#endif - -/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a - human friendly way, - to a stream rather than to a string. - * - * The rules for line break and indent are as follow: - * - Object value: - * - if empty then print {} without indent and line break - * - if not empty the print '{', line break & indent, print one value per - line - * and then unindent and line break and print '}'. - * - Array value: - * - if empty then print [] without indent and line break - * - if the array contains no object value, empty array or some other value - types, - * and all the values fit on one lines, then print the array on a single - line. - * - otherwise, it the values do not fit on one line, or the array contains - * object or non empty array, then print one value per line. - * - * If the Value have comments then they are outputed according to their - #CommentPlacement. - * - * \sa Reader, Value, Value::setComment() - * \deprecated Use StreamWriterBuilder. - */ -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable : 4996) // Deriving from deprecated class -#endif -class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API - StyledStreamWriter { -public: - /** - * \param indentation Each level will be indented by this amount extra. - */ - StyledStreamWriter(String indentation = "\t"); - ~StyledStreamWriter() = default; - -public: - /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format. - * \param out Stream to write to. (Can be ostringstream, e.g.) - * \param root Value to serialize. - * \note There is no point in deriving from Writer, since write() should not - * return a value. - */ - void write(OStream& out, const Value& root); - -private: - void writeValue(const Value& value); - void writeArrayValue(const Value& value); - bool isMultilineArray(const Value& value); - void pushValue(const String& value); - void writeIndent(); - void writeWithIndent(const String& value); - void indent(); - void unindent(); - void writeCommentBeforeValue(const Value& root); - void writeCommentAfterValueOnSameLine(const Value& root); - static bool hasCommentForValue(const Value& value); - static String normalizeEOL(const String& text); - - typedef std::vector<String> ChildValues; - - ChildValues childValues_; - OStream* document_; - String indentString_; - unsigned int rightMargin_{74}; - String indentation_; - bool addChildValues_ : 1; - bool indented_ : 1; -}; -#if defined(_MSC_VER) -#pragma warning(pop) -#endif - -#if defined(JSON_HAS_INT64) -String JSON_API valueToString(Int value); -String JSON_API valueToString(UInt value); -#endif // if defined(JSON_HAS_INT64) -String JSON_API valueToString(LargestInt value); -String JSON_API valueToString(LargestUInt value); -String JSON_API -valueToString(double value, - unsigned int precision = Value::defaultRealPrecision, - PrecisionType precisionType = PrecisionType::significantDigits); -String JSON_API valueToString(bool value); -String JSON_API valueToQuotedString(const char* value); - -/// \brief Output using the StyledStreamWriter. -/// \see Json::operator>>() -JSON_API OStream& operator<<(OStream&, const Value& root); - -} // namespace Json - -#pragma pack(pop) - -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(pop) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -#endif // JSON_WRITER_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/writer.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/assertions.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED -#define CPPTL_JSON_ASSERTIONS_H_INCLUDED - -#include <cstdlib> -#include <sstream> - -#if !defined(JSON_IS_AMALGAMATION) -#include "config.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -/** It should not be possible for a maliciously designed file to - * cause an abort() or seg-fault, so these macros are used only - * for pre-condition violations and internal logic errors. - */ -#if JSON_USE_EXCEPTION - -// @todo <= add detail about condition in exception -#define JSON_ASSERT(condition) \ - { \ - if (!(condition)) { \ - Json::throwLogicError("assert json failed"); \ - } \ - } - -#define JSON_FAIL_MESSAGE(message) \ - { \ - OStringStream oss; \ - oss << message; \ - Json::throwLogicError(oss.str()); \ - abort(); \ - } - -#else // JSON_USE_EXCEPTION - -#define JSON_ASSERT(condition) assert(condition) - -// The call to assert() will show the failure message in debug builds. In -// release builds we abort, for a core-dump or debugger. -#define JSON_FAIL_MESSAGE(message) \ - { \ - OStringStream oss; \ - oss << message; \ - assert(false && oss.str().c_str()); \ - abort(); \ - } - -#endif - -#define JSON_ASSERT_MESSAGE(condition, message) \ - if (!(condition)) { \ - JSON_FAIL_MESSAGE(message); \ - } - -#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/assertions.h -// ////////////////////////////////////////////////////////////////////// - - - - - -#endif //ifndef JSON_AMALGAMATED_H_INCLUDED
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/jsoncpp-1.8.4/jsoncpp.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5418 +0,0 @@ -/// Json-cpp amalgamated source (http://jsoncpp.sourceforge.net/). -/// It is intended to be used with #include "json/json.h" - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - -/* -The JsonCpp library's source code, including accompanying documentation, -tests and demonstration applications, are licensed under the following -conditions... - -Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all -jurisdictions which recognize such a disclaimer. In such jurisdictions, -this software is released into the Public Domain. - -In jurisdictions which do not recognize Public Domain property (e.g. Germany as of -2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and -The JsonCpp Authors, and is released under the terms of the MIT License (see below). - -In jurisdictions which recognize Public Domain property, the user of this -software may choose to accept it either as 1) Public Domain, 2) under the -conditions of the MIT License (see below), or 3) under the terms of dual -Public Domain/MIT License conditions described here, as they choose. - -The MIT License is about as close to Public Domain as a license can get, and is -described in clear, concise terms at: - - http://en.wikipedia.org/wiki/MIT_License - -The full text of the MIT License follows: - -======================================================================== -Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, copy, -modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -======================================================================== -(END LICENSE TEXT) - -The MIT license is compatible with both the GPL and commercial -software, affording one all of the rights of Public Domain with the -minor nuisance of being required to keep the above copyright notice -and license text in the source code. Note also that by accepting the -Public Domain "license" you can re-license your copy using whatever -license you like. - -*/ - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - - - - - - -#include "json/json.h" - -#ifndef JSON_IS_AMALGAMATION -#error "Compile with -I PATH_TO_JSON_DIRECTORY" -#endif - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_tool.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED -#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include <json/config.h> -#endif - -// Also support old flag NO_LOCALE_SUPPORT -#ifdef NO_LOCALE_SUPPORT -#define JSONCPP_NO_LOCALE_SUPPORT -#endif - -#ifndef JSONCPP_NO_LOCALE_SUPPORT -#include <clocale> -#endif - -/* This header provides common string manipulation support, such as UTF-8, - * portable conversion from/to string... - * - * It is an internal header that must not be exposed. - */ - -namespace Json { -static inline char getDecimalPoint() { -#ifdef JSONCPP_NO_LOCALE_SUPPORT - return '\0'; -#else - struct lconv* lc = localeconv(); - return lc ? *(lc->decimal_point) : '\0'; -#endif -} - -/// Converts a unicode code-point to UTF-8. -static inline String codePointToUTF8(unsigned int cp) { - String result; - - // based on description from http://en.wikipedia.org/wiki/UTF-8 - - if (cp <= 0x7f) { - result.resize(1); - result[0] = static_cast<char>(cp); - } else if (cp <= 0x7FF) { - result.resize(2); - result[1] = static_cast<char>(0x80 | (0x3f & cp)); - result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6))); - } else if (cp <= 0xFFFF) { - result.resize(3); - result[2] = static_cast<char>(0x80 | (0x3f & cp)); - result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6))); - result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12))); - } else if (cp <= 0x10FFFF) { - result.resize(4); - result[3] = static_cast<char>(0x80 | (0x3f & cp)); - result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6))); - result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12))); - result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18))); - } - - return result; -} - -enum { - /// Constant that specify the size of the buffer that must be passed to - /// uintToString. - uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1 -}; - -// Defines a char buffer for use with uintToString(). -typedef char UIntToStringBuffer[uintToStringBufferSize]; - -/** Converts an unsigned integer to string. - * @param value Unsigned integer to convert to string - * @param current Input/Output string buffer. - * Must have at least uintToStringBufferSize chars free. - */ -static inline void uintToString(LargestUInt value, char*& current) { - *--current = 0; - do { - *--current = static_cast<char>(value % 10U + static_cast<unsigned>('0')); - value /= 10; - } while (value != 0); -} - -/** Change ',' to '.' everywhere in buffer. - * - * We had a sophisticated way, but it did not work in WinCE. - * @see https://github.com/open-source-parsers/jsoncpp/pull/9 - */ -template <typename Iter> Iter fixNumericLocale(Iter begin, Iter end) { - for (; begin != end; ++begin) { - if (*begin == ',') { - *begin = '.'; - } - } - return begin; -} - -template <typename Iter> void fixNumericLocaleInput(Iter begin, Iter end) { - char decimalPoint = getDecimalPoint(); - if (decimalPoint == '\0' || decimalPoint == '.') { - return; - } - for (; begin != end; ++begin) { - if (*begin == '.') { - *begin = decimalPoint; - } - } -} - -/** - * Return iterator that would be the new end of the range [begin,end), if we - * were to delete zeros in the end of string, but not the last zero before '.'. - */ -template <typename Iter> Iter fixZerosInTheEnd(Iter begin, Iter end) { - for (; begin != end; --end) { - if (*(end - 1) != '0') { - return end; - } - // Don't delete the last zero before the decimal point. - if (begin != (end - 1) && *(end - 2) == '.') { - return end; - } - } - return end; -} - -} // namespace Json - -#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_tool.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_reader.cpp -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2011 Baptiste Lepilleur and The JsonCpp Authors -// Copyright (C) 2016 InfoTeCS JSC. All rights reserved. -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#if !defined(JSON_IS_AMALGAMATION) -#include "json_tool.h" -#include <json/assertions.h> -#include <json/reader.h> -#include <json/value.h> -#endif // if !defined(JSON_IS_AMALGAMATION) -#include <cassert> -#include <cstring> -#include <istream> -#include <limits> -#include <memory> -#include <set> -#include <sstream> -#include <utility> - -#include <cstdio> -#if __cplusplus >= 201103L - -#if !defined(sscanf) -#define sscanf std::sscanf -#endif - -#endif //__cplusplus - -#if defined(_MSC_VER) -#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES) -#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 -#endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES -#endif //_MSC_VER - -#if defined(_MSC_VER) -// Disable warning about strdup being deprecated. -#pragma warning(disable : 4996) -#endif - -// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile -// time to change the stack limit -#if !defined(JSONCPP_DEPRECATED_STACK_LIMIT) -#define JSONCPP_DEPRECATED_STACK_LIMIT 1000 -#endif - -static size_t const stackLimit_g = - JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue() - -namespace Json { - -#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) -typedef std::unique_ptr<CharReader> CharReaderPtr; -#else -typedef std::unique_ptr<CharReader> CharReaderPtr; -#endif - -// Implementation of class Features -// //////////////////////////////// - -Features::Features() = default; - -Features Features::all() { return {}; } - -Features Features::strictMode() { - Features features; - features.allowComments_ = false; - features.strictRoot_ = true; - features.allowDroppedNullPlaceholders_ = false; - features.allowNumericKeys_ = false; - return features; -} - -// Implementation of class Reader -// //////////////////////////////// - -bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) { - for (; begin < end; ++begin) - if (*begin == '\n' || *begin == '\r') - return true; - return false; -} - -// Class Reader -// ////////////////////////////////////////////////////////////////// - -Reader::Reader() - : errors_(), document_(), commentsBefore_(), features_(Features::all()) {} - -Reader::Reader(const Features& features) - : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), - lastValue_(), commentsBefore_(), features_(features), collectComments_() { -} - -bool Reader::parse(const std::string& document, - Value& root, - bool collectComments) { - document_.assign(document.begin(), document.end()); - const char* begin = document_.c_str(); - const char* end = begin + document_.length(); - return parse(begin, end, root, collectComments); -} - -bool Reader::parse(std::istream& is, Value& root, bool collectComments) { - // std::istream_iterator<char> begin(is); - // std::istream_iterator<char> end; - // Those would allow streamed input from a file, if parse() were a - // template function. - - // Since String is reference-counted, this at least does not - // create an extra copy. - String doc; - std::getline(is, doc, (char)EOF); - return parse(doc.data(), doc.data() + doc.size(), root, collectComments); -} - -bool Reader::parse(const char* beginDoc, - const char* endDoc, - Value& root, - bool collectComments) { - if (!features_.allowComments_) { - collectComments = false; - } - - begin_ = beginDoc; - end_ = endDoc; - collectComments_ = collectComments; - current_ = begin_; - lastValueEnd_ = nullptr; - lastValue_ = nullptr; - commentsBefore_.clear(); - errors_.clear(); - while (!nodes_.empty()) - nodes_.pop(); - nodes_.push(&root); - - bool successful = readValue(); - Token token; - skipCommentTokens(token); - if (collectComments_ && !commentsBefore_.empty()) - root.setComment(commentsBefore_, commentAfter); - if (features_.strictRoot_) { - if (!root.isArray() && !root.isObject()) { - // Set error location to start of doc, ideally should be first token found - // in doc - token.type_ = tokenError; - token.start_ = beginDoc; - token.end_ = endDoc; - addError( - "A valid JSON document must be either an array or an object value.", - token); - return false; - } - } - return successful; -} - -bool Reader::readValue() { - // readValue() may call itself only if it calls readObject() or ReadArray(). - // These methods execute nodes_.push() just before and nodes_.pop)() just - // after calling readValue(). parse() executes one nodes_.push(), so > instead - // of >=. - if (nodes_.size() > stackLimit_g) - throwRuntimeError("Exceeded stackLimit in readValue()."); - - Token token; - skipCommentTokens(token); - bool successful = true; - - if (collectComments_ && !commentsBefore_.empty()) { - currentValue().setComment(commentsBefore_, commentBefore); - commentsBefore_.clear(); - } - - switch (token.type_) { - case tokenObjectBegin: - successful = readObject(token); - currentValue().setOffsetLimit(current_ - begin_); - break; - case tokenArrayBegin: - successful = readArray(token); - currentValue().setOffsetLimit(current_ - begin_); - break; - case tokenNumber: - successful = decodeNumber(token); - break; - case tokenString: - successful = decodeString(token); - break; - case tokenTrue: { - Value v(true); - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } break; - case tokenFalse: { - Value v(false); - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } break; - case tokenNull: { - Value v; - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } break; - case tokenArraySeparator: - case tokenObjectEnd: - case tokenArrayEnd: - if (features_.allowDroppedNullPlaceholders_) { - // "Un-read" the current token and mark the current value as a null - // token. - current_--; - Value v; - currentValue().swapPayload(v); - currentValue().setOffsetStart(current_ - begin_ - 1); - currentValue().setOffsetLimit(current_ - begin_); - break; - } // Else, fall through... - default: - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return addError("Syntax error: value, object or array expected.", token); - } - - if (collectComments_) { - lastValueEnd_ = current_; - lastValue_ = ¤tValue(); - } - - return successful; -} - -void Reader::skipCommentTokens(Token& token) { - if (features_.allowComments_) { - do { - readToken(token); - } while (token.type_ == tokenComment); - } else { - readToken(token); - } -} - -bool Reader::readToken(Token& token) { - skipSpaces(); - token.start_ = current_; - Char c = getNextChar(); - bool ok = true; - switch (c) { - case '{': - token.type_ = tokenObjectBegin; - break; - case '}': - token.type_ = tokenObjectEnd; - break; - case '[': - token.type_ = tokenArrayBegin; - break; - case ']': - token.type_ = tokenArrayEnd; - break; - case '"': - token.type_ = tokenString; - ok = readString(); - break; - case '/': - token.type_ = tokenComment; - ok = readComment(); - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - token.type_ = tokenNumber; - readNumber(); - break; - case 't': - token.type_ = tokenTrue; - ok = match("rue", 3); - break; - case 'f': - token.type_ = tokenFalse; - ok = match("alse", 4); - break; - case 'n': - token.type_ = tokenNull; - ok = match("ull", 3); - break; - case ',': - token.type_ = tokenArraySeparator; - break; - case ':': - token.type_ = tokenMemberSeparator; - break; - case 0: - token.type_ = tokenEndOfStream; - break; - default: - ok = false; - break; - } - if (!ok) - token.type_ = tokenError; - token.end_ = current_; - return true; -} - -void Reader::skipSpaces() { - while (current_ != end_) { - Char c = *current_; - if (c == ' ' || c == '\t' || c == '\r' || c == '\n') - ++current_; - else - break; - } -} - -bool Reader::match(Location pattern, int patternLength) { - if (end_ - current_ < patternLength) - return false; - int index = patternLength; - while (index--) - if (current_[index] != pattern[index]) - return false; - current_ += patternLength; - return true; -} - -bool Reader::readComment() { - Location commentBegin = current_ - 1; - Char c = getNextChar(); - bool successful = false; - if (c == '*') - successful = readCStyleComment(); - else if (c == '/') - successful = readCppStyleComment(); - if (!successful) - return false; - - if (collectComments_) { - CommentPlacement placement = commentBefore; - if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { - if (c != '*' || !containsNewLine(commentBegin, current_)) - placement = commentAfterOnSameLine; - } - - addComment(commentBegin, current_, placement); - } - return true; -} - -String Reader::normalizeEOL(Reader::Location begin, Reader::Location end) { - String normalized; - normalized.reserve(static_cast<size_t>(end - begin)); - Reader::Location current = begin; - while (current != end) { - char c = *current++; - if (c == '\r') { - if (current != end && *current == '\n') - // convert dos EOL - ++current; - // convert Mac EOL - normalized += '\n'; - } else { - normalized += c; - } - } - return normalized; -} - -void Reader::addComment(Location begin, - Location end, - CommentPlacement placement) { - assert(collectComments_); - const String& normalized = normalizeEOL(begin, end); - if (placement == commentAfterOnSameLine) { - assert(lastValue_ != nullptr); - lastValue_->setComment(normalized, placement); - } else { - commentsBefore_ += normalized; - } -} - -bool Reader::readCStyleComment() { - while ((current_ + 1) < end_) { - Char c = getNextChar(); - if (c == '*' && *current_ == '/') - break; - } - return getNextChar() == '/'; -} - -bool Reader::readCppStyleComment() { - while (current_ != end_) { - Char c = getNextChar(); - if (c == '\n') - break; - if (c == '\r') { - // Consume DOS EOL. It will be normalized in addComment. - if (current_ != end_ && *current_ == '\n') - getNextChar(); - // Break on Moc OS 9 EOL. - break; - } - } - return true; -} - -void Reader::readNumber() { - const char* p = current_; - char c = '0'; // stopgap for already consumed character - // integral part - while (c >= '0' && c <= '9') - c = (current_ = p) < end_ ? *p++ : '\0'; - // fractional part - if (c == '.') { - c = (current_ = p) < end_ ? *p++ : '\0'; - while (c >= '0' && c <= '9') - c = (current_ = p) < end_ ? *p++ : '\0'; - } - // exponential part - if (c == 'e' || c == 'E') { - c = (current_ = p) < end_ ? *p++ : '\0'; - if (c == '+' || c == '-') - c = (current_ = p) < end_ ? *p++ : '\0'; - while (c >= '0' && c <= '9') - c = (current_ = p) < end_ ? *p++ : '\0'; - } -} - -bool Reader::readString() { - Char c = '\0'; - while (current_ != end_) { - c = getNextChar(); - if (c == '\\') - getNextChar(); - else if (c == '"') - break; - } - return c == '"'; -} - -bool Reader::readObject(Token& token) { - Token tokenName; - String name; - Value init(objectValue); - currentValue().swapPayload(init); - currentValue().setOffsetStart(token.start_ - begin_); - while (readToken(tokenName)) { - bool initialTokenOk = true; - while (tokenName.type_ == tokenComment && initialTokenOk) - initialTokenOk = readToken(tokenName); - if (!initialTokenOk) - break; - if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object - return true; - name.clear(); - if (tokenName.type_ == tokenString) { - if (!decodeString(tokenName, name)) - return recoverFromError(tokenObjectEnd); - } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { - Value numberName; - if (!decodeNumber(tokenName, numberName)) - return recoverFromError(tokenObjectEnd); - name = String(numberName.asCString()); - } else { - break; - } - - Token colon; - if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { - return addErrorAndRecover("Missing ':' after object member name", colon, - tokenObjectEnd); - } - Value& value = currentValue()[name]; - nodes_.push(&value); - bool ok = readValue(); - nodes_.pop(); - if (!ok) // error already set - return recoverFromError(tokenObjectEnd); - - Token comma; - if (!readToken(comma) || - (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && - comma.type_ != tokenComment)) { - return addErrorAndRecover("Missing ',' or '}' in object declaration", - comma, tokenObjectEnd); - } - bool finalizeTokenOk = true; - while (comma.type_ == tokenComment && finalizeTokenOk) - finalizeTokenOk = readToken(comma); - if (comma.type_ == tokenObjectEnd) - return true; - } - return addErrorAndRecover("Missing '}' or object member name", tokenName, - tokenObjectEnd); -} - -bool Reader::readArray(Token& token) { - Value init(arrayValue); - currentValue().swapPayload(init); - currentValue().setOffsetStart(token.start_ - begin_); - skipSpaces(); - if (current_ != end_ && *current_ == ']') // empty array - { - Token endArray; - readToken(endArray); - return true; - } - int index = 0; - for (;;) { - Value& value = currentValue()[index++]; - nodes_.push(&value); - bool ok = readValue(); - nodes_.pop(); - if (!ok) // error already set - return recoverFromError(tokenArrayEnd); - - Token currentToken; - // Accept Comment after last item in the array. - ok = readToken(currentToken); - while (currentToken.type_ == tokenComment && ok) { - ok = readToken(currentToken); - } - bool badTokenType = (currentToken.type_ != tokenArraySeparator && - currentToken.type_ != tokenArrayEnd); - if (!ok || badTokenType) { - return addErrorAndRecover("Missing ',' or ']' in array declaration", - currentToken, tokenArrayEnd); - } - if (currentToken.type_ == tokenArrayEnd) - break; - } - return true; -} - -bool Reader::decodeNumber(Token& token) { - Value decoded; - if (!decodeNumber(token, decoded)) - return false; - currentValue().swapPayload(decoded); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool Reader::decodeNumber(Token& token, Value& decoded) { - // Attempts to parse the number as an integer. If the number is - // larger than the maximum supported value of an integer then - // we decode the number as a double. - Location current = token.start_; - bool isNegative = *current == '-'; - if (isNegative) - ++current; - // TODO: Help the compiler do the div and mod at compile time or get rid of - // them. - Value::LargestUInt maxIntegerValue = - isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1 - : Value::maxLargestUInt; - Value::LargestUInt threshold = maxIntegerValue / 10; - Value::LargestUInt value = 0; - while (current < token.end_) { - Char c = *current++; - if (c < '0' || c > '9') - return decodeDouble(token, decoded); - auto digit(static_cast<Value::UInt>(c - '0')); - if (value >= threshold) { - // We've hit or exceeded the max value divided by 10 (rounded down). If - // a) we've only just touched the limit, b) this is the last digit, and - // c) it's small enough to fit in that rounding delta, we're okay. - // Otherwise treat this number as a double to avoid overflow. - if (value > threshold || current != token.end_ || - digit > maxIntegerValue % 10) { - return decodeDouble(token, decoded); - } - } - value = value * 10 + digit; - } - if (isNegative && value == maxIntegerValue) - decoded = Value::minLargestInt; - else if (isNegative) - decoded = -Value::LargestInt(value); - else if (value <= Value::LargestUInt(Value::maxInt)) - decoded = Value::LargestInt(value); - else - decoded = value; - return true; -} - -bool Reader::decodeDouble(Token& token) { - Value decoded; - if (!decodeDouble(token, decoded)) - return false; - currentValue().swapPayload(decoded); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool Reader::decodeDouble(Token& token, Value& decoded) { - double value = 0; - String buffer(token.start_, token.end_); - IStringStream is(buffer); - if (!(is >> value)) - return addError( - "'" + String(token.start_, token.end_) + "' is not a number.", token); - decoded = value; - return true; -} - -bool Reader::decodeString(Token& token) { - String decoded_string; - if (!decodeString(token, decoded_string)) - return false; - Value decoded(decoded_string); - currentValue().swapPayload(decoded); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool Reader::decodeString(Token& token, String& decoded) { - decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2)); - Location current = token.start_ + 1; // skip '"' - Location end = token.end_ - 1; // do not include '"' - while (current != end) { - Char c = *current++; - if (c == '"') - break; - else if (c == '\\') { - if (current == end) - return addError("Empty escape sequence in string", token, current); - Char escape = *current++; - switch (escape) { - case '"': - decoded += '"'; - break; - case '/': - decoded += '/'; - break; - case '\\': - decoded += '\\'; - break; - case 'b': - decoded += '\b'; - break; - case 'f': - decoded += '\f'; - break; - case 'n': - decoded += '\n'; - break; - case 'r': - decoded += '\r'; - break; - case 't': - decoded += '\t'; - break; - case 'u': { - unsigned int unicode; - if (!decodeUnicodeCodePoint(token, current, end, unicode)) - return false; - decoded += codePointToUTF8(unicode); - } break; - default: - return addError("Bad escape sequence in string", token, current); - } - } else { - decoded += c; - } - } - return true; -} - -bool Reader::decodeUnicodeCodePoint(Token& token, - Location& current, - Location end, - unsigned int& unicode) { - - if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) - return false; - if (unicode >= 0xD800 && unicode <= 0xDBFF) { - // surrogate pairs - if (end - current < 6) - return addError( - "additional six characters expected to parse unicode surrogate pair.", - token, current); - if (*(current++) == '\\' && *(current++) == 'u') { - unsigned int surrogatePair; - if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { - unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); - } else - return false; - } else - return addError("expecting another \\u token to begin the second half of " - "a unicode surrogate pair", - token, current); - } - return true; -} - -bool Reader::decodeUnicodeEscapeSequence(Token& token, - Location& current, - Location end, - unsigned int& ret_unicode) { - if (end - current < 4) - return addError( - "Bad unicode escape sequence in string: four digits expected.", token, - current); - int unicode = 0; - for (int index = 0; index < 4; ++index) { - Char c = *current++; - unicode *= 16; - if (c >= '0' && c <= '9') - unicode += c - '0'; - else if (c >= 'a' && c <= 'f') - unicode += c - 'a' + 10; - else if (c >= 'A' && c <= 'F') - unicode += c - 'A' + 10; - else - return addError( - "Bad unicode escape sequence in string: hexadecimal digit expected.", - token, current); - } - ret_unicode = static_cast<unsigned int>(unicode); - return true; -} - -bool Reader::addError(const String& message, Token& token, Location extra) { - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = extra; - errors_.push_back(info); - return false; -} - -bool Reader::recoverFromError(TokenType skipUntilToken) { - size_t const errorCount = errors_.size(); - Token skip; - for (;;) { - if (!readToken(skip)) - errors_.resize(errorCount); // discard errors caused by recovery - if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) - break; - } - errors_.resize(errorCount); - return false; -} - -bool Reader::addErrorAndRecover(const String& message, - Token& token, - TokenType skipUntilToken) { - addError(message, token); - return recoverFromError(skipUntilToken); -} - -Value& Reader::currentValue() { return *(nodes_.top()); } - -Reader::Char Reader::getNextChar() { - if (current_ == end_) - return 0; - return *current_++; -} - -void Reader::getLocationLineAndColumn(Location location, - int& line, - int& column) const { - Location current = begin_; - Location lastLineStart = current; - line = 0; - while (current < location && current != end_) { - Char c = *current++; - if (c == '\r') { - if (*current == '\n') - ++current; - lastLineStart = current; - ++line; - } else if (c == '\n') { - lastLineStart = current; - ++line; - } - } - // column & line start at 1 - column = int(location - lastLineStart) + 1; - ++line; -} - -String Reader::getLocationLineAndColumn(Location location) const { - int line, column; - getLocationLineAndColumn(location, line, column); - char buffer[18 + 16 + 16 + 1]; - jsoncpp_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); - return buffer; -} - -// Deprecated. Preserved for backward compatibility -String Reader::getFormatedErrorMessages() const { - return getFormattedErrorMessages(); -} - -String Reader::getFormattedErrorMessages() const { - String formattedMessage; - for (const auto& error : errors_) { - formattedMessage += - "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; - formattedMessage += " " + error.message_ + "\n"; - if (error.extra_) - formattedMessage += - "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; - } - return formattedMessage; -} - -std::vector<Reader::StructuredError> Reader::getStructuredErrors() const { - std::vector<Reader::StructuredError> allErrors; - for (const auto& error : errors_) { - Reader::StructuredError structured; - structured.offset_start = error.token_.start_ - begin_; - structured.offset_limit = error.token_.end_ - begin_; - structured.message = error.message_; - allErrors.push_back(structured); - } - return allErrors; -} - -bool Reader::pushError(const Value& value, const String& message) { - ptrdiff_t const length = end_ - begin_; - if (value.getOffsetStart() > length || value.getOffsetLimit() > length) - return false; - Token token; - token.type_ = tokenError; - token.start_ = begin_ + value.getOffsetStart(); - token.end_ = end_ + value.getOffsetLimit(); - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = nullptr; - errors_.push_back(info); - return true; -} - -bool Reader::pushError(const Value& value, - const String& message, - const Value& extra) { - ptrdiff_t const length = end_ - begin_; - if (value.getOffsetStart() > length || value.getOffsetLimit() > length || - extra.getOffsetLimit() > length) - return false; - Token token; - token.type_ = tokenError; - token.start_ = begin_ + value.getOffsetStart(); - token.end_ = begin_ + value.getOffsetLimit(); - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = begin_ + extra.getOffsetStart(); - errors_.push_back(info); - return true; -} - -bool Reader::good() const { return errors_.empty(); } - -// exact copy of Features -class OurFeatures { -public: - static OurFeatures all(); - bool allowComments_; - bool strictRoot_; - bool allowDroppedNullPlaceholders_; - bool allowNumericKeys_; - bool allowSingleQuotes_; - bool failIfExtra_; - bool rejectDupKeys_; - bool allowSpecialFloats_; - size_t stackLimit_; -}; // OurFeatures - -// exact copy of Implementation of class Features -// //////////////////////////////// - -OurFeatures OurFeatures::all() { return {}; } - -// Implementation of class Reader -// //////////////////////////////// - -// exact copy of Reader, renamed to OurReader -class OurReader { -public: - typedef char Char; - typedef const Char* Location; - struct StructuredError { - ptrdiff_t offset_start; - ptrdiff_t offset_limit; - String message; - }; - - OurReader(OurFeatures const& features); - bool parse(const char* beginDoc, - const char* endDoc, - Value& root, - bool collectComments = true); - String getFormattedErrorMessages() const; - std::vector<StructuredError> getStructuredErrors() const; - bool pushError(const Value& value, const String& message); - bool pushError(const Value& value, const String& message, const Value& extra); - bool good() const; - -private: - OurReader(OurReader const&); // no impl - void operator=(OurReader const&); // no impl - - enum TokenType { - tokenEndOfStream = 0, - tokenObjectBegin, - tokenObjectEnd, - tokenArrayBegin, - tokenArrayEnd, - tokenString, - tokenNumber, - tokenTrue, - tokenFalse, - tokenNull, - tokenNaN, - tokenPosInf, - tokenNegInf, - tokenArraySeparator, - tokenMemberSeparator, - tokenComment, - tokenError - }; - - class Token { - public: - TokenType type_; - Location start_; - Location end_; - }; - - class ErrorInfo { - public: - Token token_; - String message_; - Location extra_; - }; - - typedef std::deque<ErrorInfo> Errors; - - bool readToken(Token& token); - void skipSpaces(); - bool match(Location pattern, int patternLength); - bool readComment(); - bool readCStyleComment(); - bool readCppStyleComment(); - bool readString(); - bool readStringSingleQuote(); - bool readNumber(bool checkInf); - bool readValue(); - bool readObject(Token& token); - bool readArray(Token& token); - bool decodeNumber(Token& token); - bool decodeNumber(Token& token, Value& decoded); - bool decodeString(Token& token); - bool decodeString(Token& token, String& decoded); - bool decodeDouble(Token& token); - bool decodeDouble(Token& token, Value& decoded); - bool decodeUnicodeCodePoint(Token& token, - Location& current, - Location end, - unsigned int& unicode); - bool decodeUnicodeEscapeSequence(Token& token, - Location& current, - Location end, - unsigned int& unicode); - bool addError(const String& message, Token& token, Location extra = nullptr); - bool recoverFromError(TokenType skipUntilToken); - bool addErrorAndRecover(const String& message, - Token& token, - TokenType skipUntilToken); - void skipUntilSpace(); - Value& currentValue(); - Char getNextChar(); - void - getLocationLineAndColumn(Location location, int& line, int& column) const; - String getLocationLineAndColumn(Location location) const; - void addComment(Location begin, Location end, CommentPlacement placement); - void skipCommentTokens(Token& token); - - static String normalizeEOL(Location begin, Location end); - static bool containsNewLine(Location begin, Location end); - - typedef std::stack<Value*> Nodes; - Nodes nodes_; - Errors errors_; - String document_; - Location begin_; - Location end_; - Location current_; - Location lastValueEnd_; - Value* lastValue_; - String commentsBefore_; - - OurFeatures const features_; - bool collectComments_; -}; // OurReader - -// complete copy of Read impl, for OurReader - -bool OurReader::containsNewLine(OurReader::Location begin, - OurReader::Location end) { - for (; begin < end; ++begin) - if (*begin == '\n' || *begin == '\r') - return true; - return false; -} - -OurReader::OurReader(OurFeatures const& features) - : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), - lastValue_(), commentsBefore_(), features_(features), collectComments_() { -} - -bool OurReader::parse(const char* beginDoc, - const char* endDoc, - Value& root, - bool collectComments) { - if (!features_.allowComments_) { - collectComments = false; - } - - begin_ = beginDoc; - end_ = endDoc; - collectComments_ = collectComments; - current_ = begin_; - lastValueEnd_ = nullptr; - lastValue_ = nullptr; - commentsBefore_.clear(); - errors_.clear(); - while (!nodes_.empty()) - nodes_.pop(); - nodes_.push(&root); - - bool successful = readValue(); - Token token; - skipCommentTokens(token); - if (features_.failIfExtra_) { - if ((features_.strictRoot_ || token.type_ != tokenError) && - token.type_ != tokenEndOfStream) { - addError("Extra non-whitespace after JSON value.", token); - return false; - } - } - if (collectComments_ && !commentsBefore_.empty()) - root.setComment(commentsBefore_, commentAfter); - if (features_.strictRoot_) { - if (!root.isArray() && !root.isObject()) { - // Set error location to start of doc, ideally should be first token found - // in doc - token.type_ = tokenError; - token.start_ = beginDoc; - token.end_ = endDoc; - addError( - "A valid JSON document must be either an array or an object value.", - token); - return false; - } - } - return successful; -} - -bool OurReader::readValue() { - // To preserve the old behaviour we cast size_t to int. - if (nodes_.size() > features_.stackLimit_) - throwRuntimeError("Exceeded stackLimit in readValue()."); - Token token; - skipCommentTokens(token); - bool successful = true; - - if (collectComments_ && !commentsBefore_.empty()) { - currentValue().setComment(commentsBefore_, commentBefore); - commentsBefore_.clear(); - } - - switch (token.type_) { - case tokenObjectBegin: - successful = readObject(token); - currentValue().setOffsetLimit(current_ - begin_); - break; - case tokenArrayBegin: - successful = readArray(token); - currentValue().setOffsetLimit(current_ - begin_); - break; - case tokenNumber: - successful = decodeNumber(token); - break; - case tokenString: - successful = decodeString(token); - break; - case tokenTrue: { - Value v(true); - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } break; - case tokenFalse: { - Value v(false); - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } break; - case tokenNull: { - Value v; - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } break; - case tokenNaN: { - Value v(std::numeric_limits<double>::quiet_NaN()); - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } break; - case tokenPosInf: { - Value v(std::numeric_limits<double>::infinity()); - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } break; - case tokenNegInf: { - Value v(-std::numeric_limits<double>::infinity()); - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } break; - case tokenArraySeparator: - case tokenObjectEnd: - case tokenArrayEnd: - if (features_.allowDroppedNullPlaceholders_) { - // "Un-read" the current token and mark the current value as a null - // token. - current_--; - Value v; - currentValue().swapPayload(v); - currentValue().setOffsetStart(current_ - begin_ - 1); - currentValue().setOffsetLimit(current_ - begin_); - break; - } // else, fall through ... - default: - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return addError("Syntax error: value, object or array expected.", token); - } - - if (collectComments_) { - lastValueEnd_ = current_; - lastValue_ = ¤tValue(); - } - - return successful; -} - -void OurReader::skipCommentTokens(Token& token) { - if (features_.allowComments_) { - do { - readToken(token); - } while (token.type_ == tokenComment); - } else { - readToken(token); - } -} - -bool OurReader::readToken(Token& token) { - skipSpaces(); - token.start_ = current_; - Char c = getNextChar(); - bool ok = true; - switch (c) { - case '{': - token.type_ = tokenObjectBegin; - break; - case '}': - token.type_ = tokenObjectEnd; - break; - case '[': - token.type_ = tokenArrayBegin; - break; - case ']': - token.type_ = tokenArrayEnd; - break; - case '"': - token.type_ = tokenString; - ok = readString(); - break; - case '\'': - if (features_.allowSingleQuotes_) { - token.type_ = tokenString; - ok = readStringSingleQuote(); - break; - } // else fall through - case '/': - token.type_ = tokenComment; - ok = readComment(); - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - token.type_ = tokenNumber; - readNumber(false); - break; - case '-': - if (readNumber(true)) { - token.type_ = tokenNumber; - } else { - token.type_ = tokenNegInf; - ok = features_.allowSpecialFloats_ && match("nfinity", 7); - } - break; - case 't': - token.type_ = tokenTrue; - ok = match("rue", 3); - break; - case 'f': - token.type_ = tokenFalse; - ok = match("alse", 4); - break; - case 'n': - token.type_ = tokenNull; - ok = match("ull", 3); - break; - case 'N': - if (features_.allowSpecialFloats_) { - token.type_ = tokenNaN; - ok = match("aN", 2); - } else { - ok = false; - } - break; - case 'I': - if (features_.allowSpecialFloats_) { - token.type_ = tokenPosInf; - ok = match("nfinity", 7); - } else { - ok = false; - } - break; - case ',': - token.type_ = tokenArraySeparator; - break; - case ':': - token.type_ = tokenMemberSeparator; - break; - case 0: - token.type_ = tokenEndOfStream; - break; - default: - ok = false; - break; - } - if (!ok) - token.type_ = tokenError; - token.end_ = current_; - return true; -} - -void OurReader::skipSpaces() { - while (current_ != end_) { - Char c = *current_; - if (c == ' ' || c == '\t' || c == '\r' || c == '\n') - ++current_; - else - break; - } -} - -bool OurReader::match(Location pattern, int patternLength) { - if (end_ - current_ < patternLength) - return false; - int index = patternLength; - while (index--) - if (current_[index] != pattern[index]) - return false; - current_ += patternLength; - return true; -} - -bool OurReader::readComment() { - Location commentBegin = current_ - 1; - Char c = getNextChar(); - bool successful = false; - if (c == '*') - successful = readCStyleComment(); - else if (c == '/') - successful = readCppStyleComment(); - if (!successful) - return false; - - if (collectComments_) { - CommentPlacement placement = commentBefore; - if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { - if (c != '*' || !containsNewLine(commentBegin, current_)) - placement = commentAfterOnSameLine; - } - - addComment(commentBegin, current_, placement); - } - return true; -} - -String OurReader::normalizeEOL(OurReader::Location begin, - OurReader::Location end) { - String normalized; - normalized.reserve(static_cast<size_t>(end - begin)); - OurReader::Location current = begin; - while (current != end) { - char c = *current++; - if (c == '\r') { - if (current != end && *current == '\n') - // convert dos EOL - ++current; - // convert Mac EOL - normalized += '\n'; - } else { - normalized += c; - } - } - return normalized; -} - -void OurReader::addComment(Location begin, - Location end, - CommentPlacement placement) { - assert(collectComments_); - const String& normalized = normalizeEOL(begin, end); - if (placement == commentAfterOnSameLine) { - assert(lastValue_ != nullptr); - lastValue_->setComment(normalized, placement); - } else { - commentsBefore_ += normalized; - } -} - -bool OurReader::readCStyleComment() { - while ((current_ + 1) < end_) { - Char c = getNextChar(); - if (c == '*' && *current_ == '/') - break; - } - return getNextChar() == '/'; -} - -bool OurReader::readCppStyleComment() { - while (current_ != end_) { - Char c = getNextChar(); - if (c == '\n') - break; - if (c == '\r') { - // Consume DOS EOL. It will be normalized in addComment. - if (current_ != end_ && *current_ == '\n') - getNextChar(); - // Break on Moc OS 9 EOL. - break; - } - } - return true; -} - -bool OurReader::readNumber(bool checkInf) { - const char* p = current_; - if (checkInf && p != end_ && *p == 'I') { - current_ = ++p; - return false; - } - char c = '0'; // stopgap for already consumed character - // integral part - while (c >= '0' && c <= '9') - c = (current_ = p) < end_ ? *p++ : '\0'; - // fractional part - if (c == '.') { - c = (current_ = p) < end_ ? *p++ : '\0'; - while (c >= '0' && c <= '9') - c = (current_ = p) < end_ ? *p++ : '\0'; - } - // exponential part - if (c == 'e' || c == 'E') { - c = (current_ = p) < end_ ? *p++ : '\0'; - if (c == '+' || c == '-') - c = (current_ = p) < end_ ? *p++ : '\0'; - while (c >= '0' && c <= '9') - c = (current_ = p) < end_ ? *p++ : '\0'; - } - return true; -} -bool OurReader::readString() { - Char c = 0; - while (current_ != end_) { - c = getNextChar(); - if (c == '\\') - getNextChar(); - else if (c == '"') - break; - } - return c == '"'; -} - -bool OurReader::readStringSingleQuote() { - Char c = 0; - while (current_ != end_) { - c = getNextChar(); - if (c == '\\') - getNextChar(); - else if (c == '\'') - break; - } - return c == '\''; -} - -bool OurReader::readObject(Token& token) { - Token tokenName; - String name; - Value init(objectValue); - currentValue().swapPayload(init); - currentValue().setOffsetStart(token.start_ - begin_); - while (readToken(tokenName)) { - bool initialTokenOk = true; - while (tokenName.type_ == tokenComment && initialTokenOk) - initialTokenOk = readToken(tokenName); - if (!initialTokenOk) - break; - if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object - return true; - name.clear(); - if (tokenName.type_ == tokenString) { - if (!decodeString(tokenName, name)) - return recoverFromError(tokenObjectEnd); - } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { - Value numberName; - if (!decodeNumber(tokenName, numberName)) - return recoverFromError(tokenObjectEnd); - name = numberName.asString(); - } else { - break; - } - - Token colon; - if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { - return addErrorAndRecover("Missing ':' after object member name", colon, - tokenObjectEnd); - } - if (name.length() >= (1U << 30)) - throwRuntimeError("keylength >= 2^30"); - if (features_.rejectDupKeys_ && currentValue().isMember(name)) { - String msg = "Duplicate key: '" + name + "'"; - return addErrorAndRecover(msg, tokenName, tokenObjectEnd); - } - Value& value = currentValue()[name]; - nodes_.push(&value); - bool ok = readValue(); - nodes_.pop(); - if (!ok) // error already set - return recoverFromError(tokenObjectEnd); - - Token comma; - if (!readToken(comma) || - (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && - comma.type_ != tokenComment)) { - return addErrorAndRecover("Missing ',' or '}' in object declaration", - comma, tokenObjectEnd); - } - bool finalizeTokenOk = true; - while (comma.type_ == tokenComment && finalizeTokenOk) - finalizeTokenOk = readToken(comma); - if (comma.type_ == tokenObjectEnd) - return true; - } - return addErrorAndRecover("Missing '}' or object member name", tokenName, - tokenObjectEnd); -} - -bool OurReader::readArray(Token& token) { - Value init(arrayValue); - currentValue().swapPayload(init); - currentValue().setOffsetStart(token.start_ - begin_); - skipSpaces(); - if (current_ != end_ && *current_ == ']') // empty array - { - Token endArray; - readToken(endArray); - return true; - } - int index = 0; - for (;;) { - Value& value = currentValue()[index++]; - nodes_.push(&value); - bool ok = readValue(); - nodes_.pop(); - if (!ok) // error already set - return recoverFromError(tokenArrayEnd); - - Token currentToken; - // Accept Comment after last item in the array. - ok = readToken(currentToken); - while (currentToken.type_ == tokenComment && ok) { - ok = readToken(currentToken); - } - bool badTokenType = (currentToken.type_ != tokenArraySeparator && - currentToken.type_ != tokenArrayEnd); - if (!ok || badTokenType) { - return addErrorAndRecover("Missing ',' or ']' in array declaration", - currentToken, tokenArrayEnd); - } - if (currentToken.type_ == tokenArrayEnd) - break; - } - return true; -} - -bool OurReader::decodeNumber(Token& token) { - Value decoded; - if (!decodeNumber(token, decoded)) - return false; - currentValue().swapPayload(decoded); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool OurReader::decodeNumber(Token& token, Value& decoded) { - // Attempts to parse the number as an integer. If the number is - // larger than the maximum supported value of an integer then - // we decode the number as a double. - Location current = token.start_; - bool isNegative = *current == '-'; - if (isNegative) - ++current; - // TODO: Help the compiler do the div and mod at compile time or get rid of - // them. - Value::LargestUInt maxIntegerValue = - isNegative ? Value::LargestUInt(Value::minLargestInt) - : Value::maxLargestUInt; - Value::LargestUInt threshold = maxIntegerValue / 10; - Value::LargestUInt value = 0; - while (current < token.end_) { - Char c = *current++; - if (c < '0' || c > '9') - return decodeDouble(token, decoded); - auto digit(static_cast<Value::UInt>(c - '0')); - if (value >= threshold) { - // We've hit or exceeded the max value divided by 10 (rounded down). If - // a) we've only just touched the limit, b) this is the last digit, and - // c) it's small enough to fit in that rounding delta, we're okay. - // Otherwise treat this number as a double to avoid overflow. - if (value > threshold || current != token.end_ || - digit > maxIntegerValue % 10) { - return decodeDouble(token, decoded); - } - } - value = value * 10 + digit; - } - if (isNegative) - decoded = -Value::LargestInt(value); - else if (value <= Value::LargestUInt(Value::maxInt)) - decoded = Value::LargestInt(value); - else - decoded = value; - return true; -} - -bool OurReader::decodeDouble(Token& token) { - Value decoded; - if (!decodeDouble(token, decoded)) - return false; - currentValue().swapPayload(decoded); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool OurReader::decodeDouble(Token& token, Value& decoded) { - double value = 0; - const int bufferSize = 32; - int count; - ptrdiff_t const length = token.end_ - token.start_; - - // Sanity check to avoid buffer overflow exploits. - if (length < 0) { - return addError("Unable to parse token length", token); - } - auto const ulength = static_cast<size_t>(length); - - // Avoid using a string constant for the format control string given to - // sscanf, as this can cause hard to debug crashes on OS X. See here for more - // info: - // - // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html - char format[] = "%lf"; - - if (length <= bufferSize) { - Char buffer[bufferSize + 1]; - memcpy(buffer, token.start_, ulength); - buffer[length] = 0; - fixNumericLocaleInput(buffer, buffer + length); - count = sscanf(buffer, format, &value); - } else { - String buffer(token.start_, token.end_); - count = sscanf(buffer.c_str(), format, &value); - } - - if (count != 1) - return addError( - "'" + String(token.start_, token.end_) + "' is not a number.", token); - decoded = value; - return true; -} - -bool OurReader::decodeString(Token& token) { - String decoded_string; - if (!decodeString(token, decoded_string)) - return false; - Value decoded(decoded_string); - currentValue().swapPayload(decoded); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool OurReader::decodeString(Token& token, String& decoded) { - decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2)); - Location current = token.start_ + 1; // skip '"' - Location end = token.end_ - 1; // do not include '"' - while (current != end) { - Char c = *current++; - if (c == '"') - break; - else if (c == '\\') { - if (current == end) - return addError("Empty escape sequence in string", token, current); - Char escape = *current++; - switch (escape) { - case '"': - decoded += '"'; - break; - case '/': - decoded += '/'; - break; - case '\\': - decoded += '\\'; - break; - case 'b': - decoded += '\b'; - break; - case 'f': - decoded += '\f'; - break; - case 'n': - decoded += '\n'; - break; - case 'r': - decoded += '\r'; - break; - case 't': - decoded += '\t'; - break; - case 'u': { - unsigned int unicode; - if (!decodeUnicodeCodePoint(token, current, end, unicode)) - return false; - decoded += codePointToUTF8(unicode); - } break; - default: - return addError("Bad escape sequence in string", token, current); - } - } else { - decoded += c; - } - } - return true; -} - -bool OurReader::decodeUnicodeCodePoint(Token& token, - Location& current, - Location end, - unsigned int& unicode) { - - if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) - return false; - if (unicode >= 0xD800 && unicode <= 0xDBFF) { - // surrogate pairs - if (end - current < 6) - return addError( - "additional six characters expected to parse unicode surrogate pair.", - token, current); - if (*(current++) == '\\' && *(current++) == 'u') { - unsigned int surrogatePair; - if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { - unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); - } else - return false; - } else - return addError("expecting another \\u token to begin the second half of " - "a unicode surrogate pair", - token, current); - } - return true; -} - -bool OurReader::decodeUnicodeEscapeSequence(Token& token, - Location& current, - Location end, - unsigned int& ret_unicode) { - if (end - current < 4) - return addError( - "Bad unicode escape sequence in string: four digits expected.", token, - current); - int unicode = 0; - for (int index = 0; index < 4; ++index) { - Char c = *current++; - unicode *= 16; - if (c >= '0' && c <= '9') - unicode += c - '0'; - else if (c >= 'a' && c <= 'f') - unicode += c - 'a' + 10; - else if (c >= 'A' && c <= 'F') - unicode += c - 'A' + 10; - else - return addError( - "Bad unicode escape sequence in string: hexadecimal digit expected.", - token, current); - } - ret_unicode = static_cast<unsigned int>(unicode); - return true; -} - -bool OurReader::addError(const String& message, Token& token, Location extra) { - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = extra; - errors_.push_back(info); - return false; -} - -bool OurReader::recoverFromError(TokenType skipUntilToken) { - size_t errorCount = errors_.size(); - Token skip; - for (;;) { - if (!readToken(skip)) - errors_.resize(errorCount); // discard errors caused by recovery - if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) - break; - } - errors_.resize(errorCount); - return false; -} - -bool OurReader::addErrorAndRecover(const String& message, - Token& token, - TokenType skipUntilToken) { - addError(message, token); - return recoverFromError(skipUntilToken); -} - -Value& OurReader::currentValue() { return *(nodes_.top()); } - -OurReader::Char OurReader::getNextChar() { - if (current_ == end_) - return 0; - return *current_++; -} - -void OurReader::getLocationLineAndColumn(Location location, - int& line, - int& column) const { - Location current = begin_; - Location lastLineStart = current; - line = 0; - while (current < location && current != end_) { - Char c = *current++; - if (c == '\r') { - if (*current == '\n') - ++current; - lastLineStart = current; - ++line; - } else if (c == '\n') { - lastLineStart = current; - ++line; - } - } - // column & line start at 1 - column = int(location - lastLineStart) + 1; - ++line; -} - -String OurReader::getLocationLineAndColumn(Location location) const { - int line, column; - getLocationLineAndColumn(location, line, column); - char buffer[18 + 16 + 16 + 1]; - jsoncpp_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); - return buffer; -} - -String OurReader::getFormattedErrorMessages() const { - String formattedMessage; - for (const auto& error : errors_) { - formattedMessage += - "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; - formattedMessage += " " + error.message_ + "\n"; - if (error.extra_) - formattedMessage += - "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; - } - return formattedMessage; -} - -std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const { - std::vector<OurReader::StructuredError> allErrors; - for (const auto& error : errors_) { - OurReader::StructuredError structured; - structured.offset_start = error.token_.start_ - begin_; - structured.offset_limit = error.token_.end_ - begin_; - structured.message = error.message_; - allErrors.push_back(structured); - } - return allErrors; -} - -bool OurReader::pushError(const Value& value, const String& message) { - ptrdiff_t length = end_ - begin_; - if (value.getOffsetStart() > length || value.getOffsetLimit() > length) - return false; - Token token; - token.type_ = tokenError; - token.start_ = begin_ + value.getOffsetStart(); - token.end_ = end_ + value.getOffsetLimit(); - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = nullptr; - errors_.push_back(info); - return true; -} - -bool OurReader::pushError(const Value& value, - const String& message, - const Value& extra) { - ptrdiff_t length = end_ - begin_; - if (value.getOffsetStart() > length || value.getOffsetLimit() > length || - extra.getOffsetLimit() > length) - return false; - Token token; - token.type_ = tokenError; - token.start_ = begin_ + value.getOffsetStart(); - token.end_ = begin_ + value.getOffsetLimit(); - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = begin_ + extra.getOffsetStart(); - errors_.push_back(info); - return true; -} - -bool OurReader::good() const { return errors_.empty(); } - -class OurCharReader : public CharReader { - bool const collectComments_; - OurReader reader_; - -public: - OurCharReader(bool collectComments, OurFeatures const& features) - : collectComments_(collectComments), reader_(features) {} - bool parse(char const* beginDoc, - char const* endDoc, - Value* root, - String* errs) override { - bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_); - if (errs) { - *errs = reader_.getFormattedErrorMessages(); - } - return ok; - } -}; - -CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); } -CharReaderBuilder::~CharReaderBuilder() = default; -CharReader* CharReaderBuilder::newCharReader() const { - bool collectComments = settings_["collectComments"].asBool(); - OurFeatures features = OurFeatures::all(); - features.allowComments_ = settings_["allowComments"].asBool(); - features.strictRoot_ = settings_["strictRoot"].asBool(); - features.allowDroppedNullPlaceholders_ = - settings_["allowDroppedNullPlaceholders"].asBool(); - features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool(); - features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool(); -#if defined(JSON_HAS_INT64) - features.stackLimit_ = settings_["stackLimit"].asUInt64(); -#else - features.stackLimit_ = settings_["stackLimit"].asUInt(); -#endif - features.failIfExtra_ = settings_["failIfExtra"].asBool(); - features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool(); - features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool(); - return new OurCharReader(collectComments, features); -} -static void getValidReaderKeys(std::set<String>* valid_keys) { - valid_keys->clear(); - valid_keys->insert("collectComments"); - valid_keys->insert("allowComments"); - valid_keys->insert("strictRoot"); - valid_keys->insert("allowDroppedNullPlaceholders"); - valid_keys->insert("allowNumericKeys"); - valid_keys->insert("allowSingleQuotes"); - valid_keys->insert("stackLimit"); - valid_keys->insert("failIfExtra"); - valid_keys->insert("rejectDupKeys"); - valid_keys->insert("allowSpecialFloats"); -} -bool CharReaderBuilder::validate(Json::Value* invalid) const { - Json::Value my_invalid; - if (!invalid) - invalid = &my_invalid; // so we do not need to test for NULL - Json::Value& inv = *invalid; - std::set<String> valid_keys; - getValidReaderKeys(&valid_keys); - Value::Members keys = settings_.getMemberNames(); - size_t n = keys.size(); - for (size_t i = 0; i < n; ++i) { - String const& key = keys[i]; - if (valid_keys.find(key) == valid_keys.end()) { - inv[key] = settings_[key]; - } - } - return inv.empty(); -} -Value& CharReaderBuilder::operator[](const String& key) { - return settings_[key]; -} -// static -void CharReaderBuilder::strictMode(Json::Value* settings) { - //! [CharReaderBuilderStrictMode] - (*settings)["allowComments"] = false; - (*settings)["strictRoot"] = true; - (*settings)["allowDroppedNullPlaceholders"] = false; - (*settings)["allowNumericKeys"] = false; - (*settings)["allowSingleQuotes"] = false; - (*settings)["stackLimit"] = 1000; - (*settings)["failIfExtra"] = true; - (*settings)["rejectDupKeys"] = true; - (*settings)["allowSpecialFloats"] = false; - //! [CharReaderBuilderStrictMode] -} -// static -void CharReaderBuilder::setDefaults(Json::Value* settings) { - //! [CharReaderBuilderDefaults] - (*settings)["collectComments"] = true; - (*settings)["allowComments"] = true; - (*settings)["strictRoot"] = false; - (*settings)["allowDroppedNullPlaceholders"] = false; - (*settings)["allowNumericKeys"] = false; - (*settings)["allowSingleQuotes"] = false; - (*settings)["stackLimit"] = 1000; - (*settings)["failIfExtra"] = false; - (*settings)["rejectDupKeys"] = false; - (*settings)["allowSpecialFloats"] = false; - //! [CharReaderBuilderDefaults] -} - -////////////////////////////////// -// global functions - -bool parseFromStream(CharReader::Factory const& fact, - IStream& sin, - Value* root, - String* errs) { - OStringStream ssin; - ssin << sin.rdbuf(); - String doc = ssin.str(); - char const* begin = doc.data(); - char const* end = begin + doc.size(); - // Note that we do not actually need a null-terminator. - CharReaderPtr const reader(fact.newCharReader()); - return reader->parse(begin, end, root, errs); -} - -IStream& operator>>(IStream& sin, Value& root) { - CharReaderBuilder b; - String errs; - bool ok = parseFromStream(b, sin, &root, &errs); - if (!ok) { - throwRuntimeError(errs); - } - return sin; -} - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_reader.cpp -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_valueiterator.inl -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -// included by json_value.cpp - -namespace Json { - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueIteratorBase -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueIteratorBase::ValueIteratorBase() : current_() {} - -ValueIteratorBase::ValueIteratorBase( - const Value::ObjectValues::iterator& current) - : current_(current), isNull_(false) {} - -Value& ValueIteratorBase::deref() const { return current_->second; } - -void ValueIteratorBase::increment() { ++current_; } - -void ValueIteratorBase::decrement() { --current_; } - -ValueIteratorBase::difference_type -ValueIteratorBase::computeDistance(const SelfType& other) const { -#ifdef JSON_USE_CPPTL_SMALLMAP - return other.current_ - current_; -#else - // Iterator for null value are initialized using the default - // constructor, which initialize current_ to the default - // std::map::iterator. As begin() and end() are two instance - // of the default std::map::iterator, they can not be compared. - // To allow this, we handle this comparison specifically. - if (isNull_ && other.isNull_) { - return 0; - } - - // Usage of std::distance is not portable (does not compile with Sun Studio 12 - // RogueWave STL, - // which is the one used by default). - // Using a portable hand-made version for non random iterator instead: - // return difference_type( std::distance( current_, other.current_ ) ); - difference_type myDistance = 0; - for (Value::ObjectValues::iterator it = current_; it != other.current_; - ++it) { - ++myDistance; - } - return myDistance; -#endif -} - -bool ValueIteratorBase::isEqual(const SelfType& other) const { - if (isNull_) { - return other.isNull_; - } - return current_ == other.current_; -} - -void ValueIteratorBase::copy(const SelfType& other) { - current_ = other.current_; - isNull_ = other.isNull_; -} - -Value ValueIteratorBase::key() const { - const Value::CZString czstring = (*current_).first; - if (czstring.data()) { - if (czstring.isStaticString()) - return Value(StaticString(czstring.data())); - return Value(czstring.data(), czstring.data() + czstring.length()); - } - return Value(czstring.index()); -} - -UInt ValueIteratorBase::index() const { - const Value::CZString czstring = (*current_).first; - if (!czstring.data()) - return czstring.index(); - return Value::UInt(-1); -} - -String ValueIteratorBase::name() const { - char const* keey; - char const* end; - keey = memberName(&end); - if (!keey) - return String(); - return String(keey, end); -} - -char const* ValueIteratorBase::memberName() const { - const char* cname = (*current_).first.data(); - return cname ? cname : ""; -} - -char const* ValueIteratorBase::memberName(char const** end) const { - const char* cname = (*current_).first.data(); - if (!cname) { - *end = nullptr; - return nullptr; - } - *end = cname + (*current_).first.length(); - return cname; -} - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueConstIterator -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueConstIterator::ValueConstIterator() = default; - -ValueConstIterator::ValueConstIterator( - const Value::ObjectValues::iterator& current) - : ValueIteratorBase(current) {} - -ValueConstIterator::ValueConstIterator(ValueIterator const& other) - : ValueIteratorBase(other) {} - -ValueConstIterator& ValueConstIterator:: -operator=(const ValueIteratorBase& other) { - copy(other); - return *this; -} - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueIterator -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueIterator::ValueIterator() = default; - -ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current) - : ValueIteratorBase(current) {} - -ValueIterator::ValueIterator(const ValueConstIterator& other) - : ValueIteratorBase(other) { - throwRuntimeError("ConstIterator to Iterator should never be allowed."); -} - -ValueIterator::ValueIterator(const ValueIterator& other) = default; - -ValueIterator& ValueIterator::operator=(const SelfType& other) { - copy(other); - return *this; -} - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_valueiterator.inl -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_value.cpp -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#if !defined(JSON_IS_AMALGAMATION) -#include <json/assertions.h> -#include <json/value.h> -#include <json/writer.h> -#endif // if !defined(JSON_IS_AMALGAMATION) -#include <cassert> -#include <cmath> -#include <cstring> -#include <sstream> -#include <utility> -#ifdef JSON_USE_CPPTL -#include <cpptl/conststring.h> -#endif -#include <algorithm> // min() -#include <cstddef> // size_t - -// Provide implementation equivalent of std::snprintf for older _MSC compilers -#if defined(_MSC_VER) && _MSC_VER < 1900 -#include <stdarg.h> -static int msvc_pre1900_c99_vsnprintf(char* outBuf, - size_t size, - const char* format, - va_list ap) { - int count = -1; - if (size != 0) - count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap); - if (count == -1) - count = _vscprintf(format, ap); - return count; -} - -int JSON_API msvc_pre1900_c99_snprintf(char* outBuf, - size_t size, - const char* format, - ...) { - va_list ap; - va_start(ap, format); - const int count = msvc_pre1900_c99_vsnprintf(outBuf, size, format, ap); - va_end(ap); - return count; -} -#endif - -// Disable warning C4702 : unreachable code -#if defined(_MSC_VER) -#pragma warning(disable : 4702) -#endif - -#define JSON_ASSERT_UNREACHABLE assert(false) - -namespace Json { - -// This is a walkaround to avoid the static initialization of Value::null. -// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of -// 8 (instead of 4) as a bit of future-proofing. -#if defined(__ARMEL__) -#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) -#else -#define ALIGNAS(byte_alignment) -#endif -// static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 }; -// const unsigned char& kNullRef = kNull[0]; -// const Value& Value::null = reinterpret_cast<const Value&>(kNullRef); -// const Value& Value::nullRef = null; - -// static -Value const& Value::nullSingleton() { - static Value const nullStatic; - return nullStatic; -} - -// for backwards compatibility, we'll leave these global references around, but -// DO NOT use them in JSONCPP library code any more! -Value const& Value::null = Value::nullSingleton(); -Value const& Value::nullRef = Value::nullSingleton(); - -const Int Value::minInt = Int(~(UInt(-1) / 2)); -const Int Value::maxInt = Int(UInt(-1) / 2); -const UInt Value::maxUInt = UInt(-1); -#if defined(JSON_HAS_INT64) -const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2)); -const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2); -const UInt64 Value::maxUInt64 = UInt64(-1); -// The constant is hard-coded because some compiler have trouble -// converting Value::maxUInt64 to a double correctly (AIX/xlC). -// Assumes that UInt64 is a 64 bits integer. -static const double maxUInt64AsDouble = 18446744073709551615.0; -#endif // defined(JSON_HAS_INT64) -const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2)); -const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2); -const LargestUInt Value::maxLargestUInt = LargestUInt(-1); - -const UInt Value::defaultRealPrecision = 17; - -#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) -template <typename T, typename U> -static inline bool InRange(double d, T min, U max) { - // The casts can lose precision, but we are looking only for - // an approximate range. Might fail on edge cases though. ~cdunn - // return d >= static_cast<double>(min) && d <= static_cast<double>(max); - return d >= min && d <= max; -} -#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) -static inline double integerToDouble(Json::UInt64 value) { - return static_cast<double>(Int64(value / 2)) * 2.0 + - static_cast<double>(Int64(value & 1)); -} - -template <typename T> static inline double integerToDouble(T value) { - return static_cast<double>(value); -} - -template <typename T, typename U> -static inline bool InRange(double d, T min, U max) { - return d >= integerToDouble(min) && d <= integerToDouble(max); -} -#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - -/** Duplicates the specified string value. - * @param value Pointer to the string to duplicate. Must be zero-terminated if - * length is "unknown". - * @param length Length of the value. if equals to unknown, then it will be - * computed using strlen(value). - * @return Pointer on the duplicate instance of string. - */ -static inline char* duplicateStringValue(const char* value, size_t length) { - // Avoid an integer overflow in the call to malloc below by limiting length - // to a sane value. - if (length >= static_cast<size_t>(Value::maxInt)) - length = Value::maxInt - 1; - - char* newString = static_cast<char*>(malloc(length + 1)); - if (newString == nullptr) { - throwRuntimeError("in Json::Value::duplicateStringValue(): " - "Failed to allocate string value buffer"); - } - memcpy(newString, value, length); - newString[length] = 0; - return newString; -} - -/* Record the length as a prefix. - */ -static inline char* duplicateAndPrefixStringValue(const char* value, - unsigned int length) { - // Avoid an integer overflow in the call to malloc below by limiting length - // to a sane value. - JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) - - sizeof(unsigned) - 1U, - "in Json::Value::duplicateAndPrefixStringValue(): " - "length too big for prefixing"); - unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U; - char* newString = static_cast<char*>(malloc(actualLength)); - if (newString == nullptr) { - throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): " - "Failed to allocate string value buffer"); - } - *reinterpret_cast<unsigned*>(newString) = length; - memcpy(newString + sizeof(unsigned), value, length); - newString[actualLength - 1U] = - 0; // to avoid buffer over-run accidents by users later - return newString; -} -inline static void decodePrefixedString(bool isPrefixed, - char const* prefixed, - unsigned* length, - char const** value) { - if (!isPrefixed) { - *length = static_cast<unsigned>(strlen(prefixed)); - *value = prefixed; - } else { - *length = *reinterpret_cast<unsigned const*>(prefixed); - *value = prefixed + sizeof(unsigned); - } -} -/** Free the string duplicated by - * duplicateStringValue()/duplicateAndPrefixStringValue(). - */ -#if JSONCPP_USING_SECURE_MEMORY -static inline void releasePrefixedStringValue(char* value) { - unsigned length = 0; - char const* valueDecoded; - decodePrefixedString(true, value, &length, &valueDecoded); - size_t const size = sizeof(unsigned) + length + 1U; - memset(value, 0, size); - free(value); -} -static inline void releaseStringValue(char* value, unsigned length) { - // length==0 => we allocated the strings memory - size_t size = (length == 0) ? strlen(value) : length; - memset(value, 0, size); - free(value); -} -#else // !JSONCPP_USING_SECURE_MEMORY -static inline void releasePrefixedStringValue(char* value) { free(value); } -static inline void releaseStringValue(char* value, unsigned) { free(value); } -#endif // JSONCPP_USING_SECURE_MEMORY - -} // namespace Json - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ValueInternals... -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -#if !defined(JSON_IS_AMALGAMATION) - -#include "json_valueiterator.inl" -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { - -Exception::Exception(String msg) : msg_(std::move(msg)) {} -Exception::~Exception() JSONCPP_NOEXCEPT {} -char const* Exception::what() const JSONCPP_NOEXCEPT { return msg_.c_str(); } -RuntimeError::RuntimeError(String const& msg) : Exception(msg) {} -LogicError::LogicError(String const& msg) : Exception(msg) {} -JSONCPP_NORETURN void throwRuntimeError(String const& msg) { - throw RuntimeError(msg); -} -JSONCPP_NORETURN void throwLogicError(String const& msg) { - throw LogicError(msg); -} - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::CommentInfo -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -Value::CommentInfo::CommentInfo() = default; - -Value::CommentInfo::~CommentInfo() { - if (comment_) - releaseStringValue(comment_, 0u); -} - -void Value::CommentInfo::setComment(const char* text, size_t len) { - if (comment_) { - releaseStringValue(comment_, 0u); - comment_ = nullptr; - } - JSON_ASSERT(text != nullptr); - JSON_ASSERT_MESSAGE( - text[0] == '\0' || text[0] == '/', - "in Json::Value::setComment(): Comments must start with /"); - // It seems that /**/ style comments are acceptable as well. - comment_ = duplicateStringValue(text, len); -} - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::CZString -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -// Notes: policy_ indicates if the string was allocated when -// a string is stored. - -Value::CZString::CZString(ArrayIndex index) : cstr_(nullptr), index_(index) {} - -Value::CZString::CZString(char const* str, - unsigned length, - DuplicationPolicy allocate) - : cstr_(str) { - // allocate != duplicate - storage_.policy_ = allocate & 0x3; - storage_.length_ = length & 0x3FFFFFFF; -} - -Value::CZString::CZString(const CZString& other) { - cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != nullptr - ? duplicateStringValue(other.cstr_, other.storage_.length_) - : other.cstr_); - storage_.policy_ = - static_cast<unsigned>( - other.cstr_ - ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == - noDuplication - ? noDuplication - : duplicate) - : static_cast<DuplicationPolicy>(other.storage_.policy_)) & - 3U; - storage_.length_ = other.storage_.length_; -} - -#if JSON_HAS_RVALUE_REFERENCES -Value::CZString::CZString(CZString&& other) - : cstr_(other.cstr_), index_(other.index_) { - other.cstr_ = nullptr; -} -#endif - -Value::CZString::~CZString() { - if (cstr_ && storage_.policy_ == duplicate) { - releaseStringValue(const_cast<char*>(cstr_), - storage_.length_ + 1u); // +1 for null terminating - // character for sake of - // completeness but not actually - // necessary - } -} - -void Value::CZString::swap(CZString& other) { - std::swap(cstr_, other.cstr_); - std::swap(index_, other.index_); -} - -Value::CZString& Value::CZString::operator=(const CZString& other) { - cstr_ = other.cstr_; - index_ = other.index_; - return *this; -} - -#if JSON_HAS_RVALUE_REFERENCES -Value::CZString& Value::CZString::operator=(CZString&& other) { - cstr_ = other.cstr_; - index_ = other.index_; - other.cstr_ = nullptr; - return *this; -} -#endif - -bool Value::CZString::operator<(const CZString& other) const { - if (!cstr_) - return index_ < other.index_; - // return strcmp(cstr_, other.cstr_) < 0; - // Assume both are strings. - unsigned this_len = this->storage_.length_; - unsigned other_len = other.storage_.length_; - unsigned min_len = std::min<unsigned>(this_len, other_len); - JSON_ASSERT(this->cstr_ && other.cstr_); - int comp = memcmp(this->cstr_, other.cstr_, min_len); - if (comp < 0) - return true; - if (comp > 0) - return false; - return (this_len < other_len); -} - -bool Value::CZString::operator==(const CZString& other) const { - if (!cstr_) - return index_ == other.index_; - // return strcmp(cstr_, other.cstr_) == 0; - // Assume both are strings. - unsigned this_len = this->storage_.length_; - unsigned other_len = other.storage_.length_; - if (this_len != other_len) - return false; - JSON_ASSERT(this->cstr_ && other.cstr_); - int comp = memcmp(this->cstr_, other.cstr_, this_len); - return comp == 0; -} - -ArrayIndex Value::CZString::index() const { return index_; } - -// const char* Value::CZString::c_str() const { return cstr_; } -const char* Value::CZString::data() const { return cstr_; } -unsigned Value::CZString::length() const { return storage_.length_; } -bool Value::CZString::isStaticString() const { - return storage_.policy_ == noDuplication; -} - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::Value -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -/*! \internal Default constructor initialization must be equivalent to: - * memset( this, 0, sizeof(Value) ) - * This optimization is used in ValueInternalMap fast allocator. - */ -Value::Value(ValueType type) { - static char const emptyString[] = ""; - initBasic(type); - switch (type) { - case nullValue: - break; - case intValue: - case uintValue: - value_.int_ = 0; - break; - case realValue: - value_.real_ = 0.0; - break; - case stringValue: - // allocated_ == false, so this is safe. - value_.string_ = const_cast<char*>(static_cast<char const*>(emptyString)); - break; - case arrayValue: - case objectValue: - value_.map_ = new ObjectValues(); - break; - case booleanValue: - value_.bool_ = false; - break; - default: - JSON_ASSERT_UNREACHABLE; - } -} - -Value::Value(Int value) { - initBasic(intValue); - value_.int_ = value; -} - -Value::Value(UInt value) { - initBasic(uintValue); - value_.uint_ = value; -} -#if defined(JSON_HAS_INT64) -Value::Value(Int64 value) { - initBasic(intValue); - value_.int_ = value; -} -Value::Value(UInt64 value) { - initBasic(uintValue); - value_.uint_ = value; -} -#endif // defined(JSON_HAS_INT64) - -Value::Value(double value) { - initBasic(realValue); - value_.real_ = value; -} - -Value::Value(const char* value) { - initBasic(stringValue, true); - JSON_ASSERT_MESSAGE(value != nullptr, - "Null Value Passed to Value Constructor"); - value_.string_ = duplicateAndPrefixStringValue( - value, static_cast<unsigned>(strlen(value))); -} - -Value::Value(const char* begin, const char* end) { - initBasic(stringValue, true); - value_.string_ = - duplicateAndPrefixStringValue(begin, static_cast<unsigned>(end - begin)); -} - -Value::Value(const String& value) { - initBasic(stringValue, true); - value_.string_ = duplicateAndPrefixStringValue( - value.data(), static_cast<unsigned>(value.length())); -} - -Value::Value(const StaticString& value) { - initBasic(stringValue); - value_.string_ = const_cast<char*>(value.c_str()); -} - -#ifdef JSON_USE_CPPTL -Value::Value(const CppTL::ConstString& value) { - initBasic(stringValue, true); - value_.string_ = duplicateAndPrefixStringValue( - value, static_cast<unsigned>(value.length())); -} -#endif - -Value::Value(bool value) { - initBasic(booleanValue); - value_.bool_ = value; -} - -Value::Value(const Value& other) { - dupPayload(other); - dupMeta(other); -} - -Value::Value(Value&& other) { - initBasic(nullValue); - swap(other); -} - -Value::~Value() { - releasePayload(); - delete[] comments_; - value_.uint_ = 0; -} - -Value& Value::operator=(const Value& other) { - Value(other).swap(*this); - return *this; -} - -Value& Value::operator=(Value&& other) { - other.swap(*this); - return *this; -} - -void Value::swapPayload(Value& other) { - std::swap(bits_, other.bits_); - std::swap(value_, other.value_); -} - -void Value::copyPayload(const Value& other) { - releasePayload(); - dupPayload(other); -} - -void Value::swap(Value& other) { - swapPayload(other); - std::swap(comments_, other.comments_); - std::swap(start_, other.start_); - std::swap(limit_, other.limit_); -} - -void Value::copy(const Value& other) { - copyPayload(other); - delete[] comments_; - dupMeta(other); -} - -ValueType Value::type() const { - return static_cast<ValueType>(bits_.value_type_); -} - -int Value::compare(const Value& other) const { - if (*this < other) - return -1; - if (*this > other) - return 1; - return 0; -} - -bool Value::operator<(const Value& other) const { - int typeDelta = type() - other.type(); - if (typeDelta) - return typeDelta < 0 ? true : false; - switch (type()) { - case nullValue: - return false; - case intValue: - return value_.int_ < other.value_.int_; - case uintValue: - return value_.uint_ < other.value_.uint_; - case realValue: - return value_.real_ < other.value_.real_; - case booleanValue: - return value_.bool_ < other.value_.bool_; - case stringValue: { - if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) { - if (other.value_.string_) - return true; - else - return false; - } - unsigned this_len; - unsigned other_len; - char const* this_str; - char const* other_str; - decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, - &this_str); - decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len, - &other_str); - unsigned min_len = std::min<unsigned>(this_len, other_len); - JSON_ASSERT(this_str && other_str); - int comp = memcmp(this_str, other_str, min_len); - if (comp < 0) - return true; - if (comp > 0) - return false; - return (this_len < other_len); - } - case arrayValue: - case objectValue: { - int delta = int(value_.map_->size() - other.value_.map_->size()); - if (delta) - return delta < 0; - return (*value_.map_) < (*other.value_.map_); - } - default: - JSON_ASSERT_UNREACHABLE; - } - return false; // unreachable -} - -bool Value::operator<=(const Value& other) const { return !(other < *this); } - -bool Value::operator>=(const Value& other) const { return !(*this < other); } - -bool Value::operator>(const Value& other) const { return other < *this; } - -bool Value::operator==(const Value& other) const { - if (type() != other.type()) - return false; - switch (type()) { - case nullValue: - return true; - case intValue: - return value_.int_ == other.value_.int_; - case uintValue: - return value_.uint_ == other.value_.uint_; - case realValue: - return value_.real_ == other.value_.real_; - case booleanValue: - return value_.bool_ == other.value_.bool_; - case stringValue: { - if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) { - return (value_.string_ == other.value_.string_); - } - unsigned this_len; - unsigned other_len; - char const* this_str; - char const* other_str; - decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, - &this_str); - decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len, - &other_str); - if (this_len != other_len) - return false; - JSON_ASSERT(this_str && other_str); - int comp = memcmp(this_str, other_str, this_len); - return comp == 0; - } - case arrayValue: - case objectValue: - return value_.map_->size() == other.value_.map_->size() && - (*value_.map_) == (*other.value_.map_); - default: - JSON_ASSERT_UNREACHABLE; - } - return false; // unreachable -} - -bool Value::operator!=(const Value& other) const { return !(*this == other); } - -const char* Value::asCString() const { - JSON_ASSERT_MESSAGE(type() == stringValue, - "in Json::Value::asCString(): requires stringValue"); - if (value_.string_ == nullptr) - return nullptr; - unsigned this_len; - char const* this_str; - decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, - &this_str); - return this_str; -} - -#if JSONCPP_USING_SECURE_MEMORY -unsigned Value::getCStringLength() const { - JSON_ASSERT_MESSAGE(type() == stringValue, - "in Json::Value::asCString(): requires stringValue"); - if (value_.string_ == 0) - return 0; - unsigned this_len; - char const* this_str; - decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, - &this_str); - return this_len; -} -#endif - -bool Value::getString(char const** begin, char const** end) const { - if (type() != stringValue) - return false; - if (value_.string_ == nullptr) - return false; - unsigned length; - decodePrefixedString(this->isAllocated(), this->value_.string_, &length, - begin); - *end = *begin + length; - return true; -} - -String Value::asString() const { - switch (type()) { - case nullValue: - return ""; - case stringValue: { - if (value_.string_ == nullptr) - return ""; - unsigned this_len; - char const* this_str; - decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, - &this_str); - return String(this_str, this_len); - } - case booleanValue: - return value_.bool_ ? "true" : "false"; - case intValue: - return valueToString(value_.int_); - case uintValue: - return valueToString(value_.uint_); - case realValue: - return valueToString(value_.real_); - default: - JSON_FAIL_MESSAGE("Type is not convertible to string"); - } -} - -#ifdef JSON_USE_CPPTL -CppTL::ConstString Value::asConstString() const { - unsigned len; - char const* str; - decodePrefixedString(isAllocated(), value_.string_, &len, &str); - return CppTL::ConstString(str, len); -} -#endif - -Value::Int Value::asInt() const { - switch (type()) { - case intValue: - JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range"); - return Int(value_.int_); - case uintValue: - JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range"); - return Int(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), - "double out of Int range"); - return Int(value_.real_); - case nullValue: - return 0; - case booleanValue: - return value_.bool_ ? 1 : 0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to Int."); -} - -Value::UInt Value::asUInt() const { - switch (type()) { - case intValue: - JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range"); - return UInt(value_.int_); - case uintValue: - JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range"); - return UInt(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), - "double out of UInt range"); - return UInt(value_.real_); - case nullValue: - return 0; - case booleanValue: - return value_.bool_ ? 1 : 0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to UInt."); -} - -#if defined(JSON_HAS_INT64) - -Value::Int64 Value::asInt64() const { - switch (type()) { - case intValue: - return Int64(value_.int_); - case uintValue: - JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range"); - return Int64(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), - "double out of Int64 range"); - return Int64(value_.real_); - case nullValue: - return 0; - case booleanValue: - return value_.bool_ ? 1 : 0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to Int64."); -} - -Value::UInt64 Value::asUInt64() const { - switch (type()) { - case intValue: - JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range"); - return UInt64(value_.int_); - case uintValue: - return UInt64(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), - "double out of UInt64 range"); - return UInt64(value_.real_); - case nullValue: - return 0; - case booleanValue: - return value_.bool_ ? 1 : 0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to UInt64."); -} -#endif // if defined(JSON_HAS_INT64) - -LargestInt Value::asLargestInt() const { -#if defined(JSON_NO_INT64) - return asInt(); -#else - return asInt64(); -#endif -} - -LargestUInt Value::asLargestUInt() const { -#if defined(JSON_NO_INT64) - return asUInt(); -#else - return asUInt64(); -#endif -} - -double Value::asDouble() const { - switch (type()) { - case intValue: - return static_cast<double>(value_.int_); - case uintValue: -#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return static_cast<double>(value_.uint_); -#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return integerToDouble(value_.uint_); -#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - case realValue: - return value_.real_; - case nullValue: - return 0.0; - case booleanValue: - return value_.bool_ ? 1.0 : 0.0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to double."); -} - -float Value::asFloat() const { - switch (type()) { - case intValue: - return static_cast<float>(value_.int_); - case uintValue: -#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return static_cast<float>(value_.uint_); -#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - // This can fail (silently?) if the value is bigger than MAX_FLOAT. - return static_cast<float>(integerToDouble(value_.uint_)); -#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - case realValue: - return static_cast<float>(value_.real_); - case nullValue: - return 0.0; - case booleanValue: - return value_.bool_ ? 1.0f : 0.0f; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to float."); -} - -bool Value::asBool() const { - switch (type()) { - case booleanValue: - return value_.bool_; - case nullValue: - return false; - case intValue: - return value_.int_ ? true : false; - case uintValue: - return value_.uint_ ? true : false; - case realValue: - // This is kind of strange. Not recommended. - return (value_.real_ != 0.0) ? true : false; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to bool."); -} - -bool Value::isConvertibleTo(ValueType other) const { - switch (other) { - case nullValue: - return (isNumeric() && asDouble() == 0.0) || - (type() == booleanValue && value_.bool_ == false) || - (type() == stringValue && asString().empty()) || - (type() == arrayValue && value_.map_->empty()) || - (type() == objectValue && value_.map_->empty()) || - type() == nullValue; - case intValue: - return isInt() || - (type() == realValue && InRange(value_.real_, minInt, maxInt)) || - type() == booleanValue || type() == nullValue; - case uintValue: - return isUInt() || - (type() == realValue && InRange(value_.real_, 0, maxUInt)) || - type() == booleanValue || type() == nullValue; - case realValue: - return isNumeric() || type() == booleanValue || type() == nullValue; - case booleanValue: - return isNumeric() || type() == booleanValue || type() == nullValue; - case stringValue: - return isNumeric() || type() == booleanValue || type() == stringValue || - type() == nullValue; - case arrayValue: - return type() == arrayValue || type() == nullValue; - case objectValue: - return type() == objectValue || type() == nullValue; - } - JSON_ASSERT_UNREACHABLE; - return false; -} - -/// Number of values in array or object -ArrayIndex Value::size() const { - switch (type()) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - case stringValue: - return 0; - case arrayValue: // size of the array is highest index + 1 - if (!value_.map_->empty()) { - ObjectValues::const_iterator itLast = value_.map_->end(); - --itLast; - return (*itLast).first.index() + 1; - } - return 0; - case objectValue: - return ArrayIndex(value_.map_->size()); - } - JSON_ASSERT_UNREACHABLE; - return 0; // unreachable; -} - -bool Value::empty() const { - if (isNull() || isArray() || isObject()) - return size() == 0u; - else - return false; -} - -Value::operator bool() const { return !isNull(); } - -void Value::clear() { - JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue || - type() == objectValue, - "in Json::Value::clear(): requires complex value"); - start_ = 0; - limit_ = 0; - switch (type()) { - case arrayValue: - case objectValue: - value_.map_->clear(); - break; - default: - break; - } -} - -void Value::resize(ArrayIndex newSize) { - JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue, - "in Json::Value::resize(): requires arrayValue"); - if (type() == nullValue) - *this = Value(arrayValue); - ArrayIndex oldSize = size(); - if (newSize == 0) - clear(); - else if (newSize > oldSize) - this->operator[](newSize - 1); - else { - for (ArrayIndex index = newSize; index < oldSize; ++index) { - value_.map_->erase(index); - } - JSON_ASSERT(size() == newSize); - } -} - -Value& Value::operator[](ArrayIndex index) { - JSON_ASSERT_MESSAGE( - type() == nullValue || type() == arrayValue, - "in Json::Value::operator[](ArrayIndex): requires arrayValue"); - if (type() == nullValue) - *this = Value(arrayValue); - CZString key(index); - auto it = value_.map_->lower_bound(key); - if (it != value_.map_->end() && (*it).first == key) - return (*it).second; - - ObjectValues::value_type defaultValue(key, nullSingleton()); - it = value_.map_->insert(it, defaultValue); - return (*it).second; -} - -Value& Value::operator[](int index) { - JSON_ASSERT_MESSAGE( - index >= 0, - "in Json::Value::operator[](int index): index cannot be negative"); - return (*this)[ArrayIndex(index)]; -} - -const Value& Value::operator[](ArrayIndex index) const { - JSON_ASSERT_MESSAGE( - type() == nullValue || type() == arrayValue, - "in Json::Value::operator[](ArrayIndex)const: requires arrayValue"); - if (type() == nullValue) - return nullSingleton(); - CZString key(index); - ObjectValues::const_iterator it = value_.map_->find(key); - if (it == value_.map_->end()) - return nullSingleton(); - return (*it).second; -} - -const Value& Value::operator[](int index) const { - JSON_ASSERT_MESSAGE( - index >= 0, - "in Json::Value::operator[](int index) const: index cannot be negative"); - return (*this)[ArrayIndex(index)]; -} - -void Value::initBasic(ValueType type, bool allocated) { - setType(type); - setIsAllocated(allocated); - comments_ = nullptr; - start_ = 0; - limit_ = 0; -} - -void Value::dupPayload(const Value& other) { - setType(other.type()); - setIsAllocated(false); - switch (type()) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - value_ = other.value_; - break; - case stringValue: - if (other.value_.string_ && other.isAllocated()) { - unsigned len; - char const* str; - decodePrefixedString(other.isAllocated(), other.value_.string_, &len, - &str); - value_.string_ = duplicateAndPrefixStringValue(str, len); - setIsAllocated(true); - } else { - value_.string_ = other.value_.string_; - } - break; - case arrayValue: - case objectValue: - value_.map_ = new ObjectValues(*other.value_.map_); - break; - default: - JSON_ASSERT_UNREACHABLE; - } -} - -void Value::releasePayload() { - switch (type()) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - break; - case stringValue: - if (isAllocated()) - releasePrefixedStringValue(value_.string_); - break; - case arrayValue: - case objectValue: - delete value_.map_; - break; - default: - JSON_ASSERT_UNREACHABLE; - } -} - -void Value::dupMeta(const Value& other) { - if (other.comments_) { - comments_ = new CommentInfo[numberOfCommentPlacement]; - for (int comment = 0; comment < numberOfCommentPlacement; ++comment) { - const CommentInfo& otherComment = other.comments_[comment]; - if (otherComment.comment_) - comments_[comment].setComment(otherComment.comment_, - strlen(otherComment.comment_)); - } - } else { - comments_ = nullptr; - } - start_ = other.start_; - limit_ = other.limit_; -} - -// Access an object value by name, create a null member if it does not exist. -// @pre Type of '*this' is object or null. -// @param key is null-terminated. -Value& Value::resolveReference(const char* key) { - JSON_ASSERT_MESSAGE( - type() == nullValue || type() == objectValue, - "in Json::Value::resolveReference(): requires objectValue"); - if (type() == nullValue) - *this = Value(objectValue); - CZString actualKey(key, static_cast<unsigned>(strlen(key)), - CZString::noDuplication); // NOTE! - auto it = value_.map_->lower_bound(actualKey); - if (it != value_.map_->end() && (*it).first == actualKey) - return (*it).second; - - ObjectValues::value_type defaultValue(actualKey, nullSingleton()); - it = value_.map_->insert(it, defaultValue); - Value& value = (*it).second; - return value; -} - -// @param key is not null-terminated. -Value& Value::resolveReference(char const* key, char const* end) { - JSON_ASSERT_MESSAGE( - type() == nullValue || type() == objectValue, - "in Json::Value::resolveReference(key, end): requires objectValue"); - if (type() == nullValue) - *this = Value(objectValue); - CZString actualKey(key, static_cast<unsigned>(end - key), - CZString::duplicateOnCopy); - auto it = value_.map_->lower_bound(actualKey); - if (it != value_.map_->end() && (*it).first == actualKey) - return (*it).second; - - ObjectValues::value_type defaultValue(actualKey, nullSingleton()); - it = value_.map_->insert(it, defaultValue); - Value& value = (*it).second; - return value; -} - -Value Value::get(ArrayIndex index, const Value& defaultValue) const { - const Value* value = &((*this)[index]); - return value == &nullSingleton() ? defaultValue : *value; -} - -bool Value::isValidIndex(ArrayIndex index) const { return index < size(); } - -Value const* Value::find(char const* begin, char const* end) const { - JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue, - "in Json::Value::find(key, end, found): requires " - "objectValue or nullValue"); - if (type() == nullValue) - return nullptr; - CZString actualKey(begin, static_cast<unsigned>(end - begin), - CZString::noDuplication); - ObjectValues::const_iterator it = value_.map_->find(actualKey); - if (it == value_.map_->end()) - return nullptr; - return &(*it).second; -} -const Value& Value::operator[](const char* key) const { - Value const* found = find(key, key + strlen(key)); - if (!found) - return nullSingleton(); - return *found; -} -Value const& Value::operator[](const String& key) const { - Value const* found = find(key.data(), key.data() + key.length()); - if (!found) - return nullSingleton(); - return *found; -} - -Value& Value::operator[](const char* key) { - return resolveReference(key, key + strlen(key)); -} - -Value& Value::operator[](const String& key) { - return resolveReference(key.data(), key.data() + key.length()); -} - -Value& Value::operator[](const StaticString& key) { - return resolveReference(key.c_str()); -} - -#ifdef JSON_USE_CPPTL -Value& Value::operator[](const CppTL::ConstString& key) { - return resolveReference(key.c_str(), key.end_c_str()); -} -Value const& Value::operator[](CppTL::ConstString const& key) const { - Value const* found = find(key.c_str(), key.end_c_str()); - if (!found) - return nullSingleton(); - return *found; -} -#endif - -Value& Value::append(const Value& value) { return (*this)[size()] = value; } - -#if JSON_HAS_RVALUE_REFERENCES -Value& Value::append(Value&& value) { - return (*this)[size()] = std::move(value); -} -#endif - -Value Value::get(char const* begin, - char const* end, - Value const& defaultValue) const { - Value const* found = find(begin, end); - return !found ? defaultValue : *found; -} -Value Value::get(char const* key, Value const& defaultValue) const { - return get(key, key + strlen(key), defaultValue); -} -Value Value::get(String const& key, Value const& defaultValue) const { - return get(key.data(), key.data() + key.length(), defaultValue); -} - -bool Value::removeMember(const char* begin, const char* end, Value* removed) { - if (type() != objectValue) { - return false; - } - CZString actualKey(begin, static_cast<unsigned>(end - begin), - CZString::noDuplication); - auto it = value_.map_->find(actualKey); - if (it == value_.map_->end()) - return false; - if (removed) -#if JSON_HAS_RVALUE_REFERENCES - *removed = std::move(it->second); -#else - *removed = it->second; -#endif - value_.map_->erase(it); - return true; -} -bool Value::removeMember(const char* key, Value* removed) { - return removeMember(key, key + strlen(key), removed); -} -bool Value::removeMember(String const& key, Value* removed) { - return removeMember(key.data(), key.data() + key.length(), removed); -} -void Value::removeMember(const char* key) { - JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue, - "in Json::Value::removeMember(): requires objectValue"); - if (type() == nullValue) - return; - - CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication); - value_.map_->erase(actualKey); -} -void Value::removeMember(const String& key) { removeMember(key.c_str()); } - -bool Value::removeIndex(ArrayIndex index, Value* removed) { - if (type() != arrayValue) { - return false; - } - CZString key(index); - auto it = value_.map_->find(key); - if (it == value_.map_->end()) { - return false; - } - if (removed) - *removed = it->second; - ArrayIndex oldSize = size(); - // shift left all items left, into the place of the "removed" - for (ArrayIndex i = index; i < (oldSize - 1); ++i) { - CZString keey(i); - (*value_.map_)[keey] = (*this)[i + 1]; - } - // erase the last one ("leftover") - CZString keyLast(oldSize - 1); - auto itLast = value_.map_->find(keyLast); - value_.map_->erase(itLast); - return true; -} - -#ifdef JSON_USE_CPPTL -Value Value::get(const CppTL::ConstString& key, - const Value& defaultValue) const { - return get(key.c_str(), key.end_c_str(), defaultValue); -} -#endif - -bool Value::isMember(char const* begin, char const* end) const { - Value const* value = find(begin, end); - return nullptr != value; -} -bool Value::isMember(char const* key) const { - return isMember(key, key + strlen(key)); -} -bool Value::isMember(String const& key) const { - return isMember(key.data(), key.data() + key.length()); -} - -#ifdef JSON_USE_CPPTL -bool Value::isMember(const CppTL::ConstString& key) const { - return isMember(key.c_str(), key.end_c_str()); -} -#endif - -Value::Members Value::getMemberNames() const { - JSON_ASSERT_MESSAGE( - type() == nullValue || type() == objectValue, - "in Json::Value::getMemberNames(), value must be objectValue"); - if (type() == nullValue) - return Value::Members(); - Members members; - members.reserve(value_.map_->size()); - ObjectValues::const_iterator it = value_.map_->begin(); - ObjectValues::const_iterator itEnd = value_.map_->end(); - for (; it != itEnd; ++it) { - members.push_back(String((*it).first.data(), (*it).first.length())); - } - return members; -} -// -//# ifdef JSON_USE_CPPTL -// EnumMemberNames -// Value::enumMemberNames() const -//{ -// if ( type() == objectValue ) -// { -// return CppTL::Enum::any( CppTL::Enum::transform( -// CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ), -// MemberNamesTransform() ) ); -// } -// return EnumMemberNames(); -//} -// -// -// EnumValues -// Value::enumValues() const -//{ -// if ( type() == objectValue || type() == arrayValue ) -// return CppTL::Enum::anyValues( *(value_.map_), -// CppTL::Type<const Value &>() ); -// return EnumValues(); -//} -// -//# endif - -static bool IsIntegral(double d) { - double integral_part; - return modf(d, &integral_part) == 0.0; -} - -bool Value::isNull() const { return type() == nullValue; } - -bool Value::isBool() const { return type() == booleanValue; } - -bool Value::isInt() const { - switch (type()) { - case intValue: -#if defined(JSON_HAS_INT64) - return value_.int_ >= minInt && value_.int_ <= maxInt; -#else - return true; -#endif - case uintValue: - return value_.uint_ <= UInt(maxInt); - case realValue: - return value_.real_ >= minInt && value_.real_ <= maxInt && - IsIntegral(value_.real_); - default: - break; - } - return false; -} - -bool Value::isUInt() const { - switch (type()) { - case intValue: -#if defined(JSON_HAS_INT64) - return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt); -#else - return value_.int_ >= 0; -#endif - case uintValue: -#if defined(JSON_HAS_INT64) - return value_.uint_ <= maxUInt; -#else - return true; -#endif - case realValue: - return value_.real_ >= 0 && value_.real_ <= maxUInt && - IsIntegral(value_.real_); - default: - break; - } - return false; -} - -bool Value::isInt64() const { -#if defined(JSON_HAS_INT64) - switch (type()) { - case intValue: - return true; - case uintValue: - return value_.uint_ <= UInt64(maxInt64); - case realValue: - // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a - // double, so double(maxInt64) will be rounded up to 2^63. Therefore we - // require the value to be strictly less than the limit. - return value_.real_ >= double(minInt64) && - value_.real_ < double(maxInt64) && IsIntegral(value_.real_); - default: - break; - } -#endif // JSON_HAS_INT64 - return false; -} - -bool Value::isUInt64() const { -#if defined(JSON_HAS_INT64) - switch (type()) { - case intValue: - return value_.int_ >= 0; - case uintValue: - return true; - case realValue: - // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a - // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we - // require the value to be strictly less than the limit. - return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble && - IsIntegral(value_.real_); - default: - break; - } -#endif // JSON_HAS_INT64 - return false; -} - -bool Value::isIntegral() const { - switch (type()) { - case intValue: - case uintValue: - return true; - case realValue: -#if defined(JSON_HAS_INT64) - // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a - // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we - // require the value to be strictly less than the limit. - return value_.real_ >= double(minInt64) && - value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_); -#else - return value_.real_ >= minInt && value_.real_ <= maxUInt && - IsIntegral(value_.real_); -#endif // JSON_HAS_INT64 - default: - break; - } - return false; -} - -bool Value::isDouble() const { - return type() == intValue || type() == uintValue || type() == realValue; -} - -bool Value::isNumeric() const { return isDouble(); } - -bool Value::isString() const { return type() == stringValue; } - -bool Value::isArray() const { return type() == arrayValue; } - -bool Value::isObject() const { return type() == objectValue; } - -void Value::setComment(const char* comment, - size_t len, - CommentPlacement placement) { - if (!comments_) - comments_ = new CommentInfo[numberOfCommentPlacement]; - if ((len > 0) && (comment[len - 1] == '\n')) { - // Always discard trailing newline, to aid indentation. - len -= 1; - } - comments_[placement].setComment(comment, len); -} - -void Value::setComment(const char* comment, CommentPlacement placement) { - setComment(comment, strlen(comment), placement); -} - -void Value::setComment(const String& comment, CommentPlacement placement) { - setComment(comment.c_str(), comment.length(), placement); -} - -bool Value::hasComment(CommentPlacement placement) const { - return comments_ != nullptr && comments_[placement].comment_ != nullptr; -} - -String Value::getComment(CommentPlacement placement) const { - if (hasComment(placement)) - return comments_[placement].comment_; - return ""; -} - -void Value::setOffsetStart(ptrdiff_t start) { start_ = start; } - -void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; } - -ptrdiff_t Value::getOffsetStart() const { return start_; } - -ptrdiff_t Value::getOffsetLimit() const { return limit_; } - -String Value::toStyledString() const { - StreamWriterBuilder builder; - - String out = this->hasComment(commentBefore) ? "\n" : ""; - out += Json::writeString(builder, *this); - out += '\n'; - - return out; -} - -Value::const_iterator Value::begin() const { - switch (type()) { - case arrayValue: - case objectValue: - if (value_.map_) - return const_iterator(value_.map_->begin()); - break; - default: - break; - } - return {}; -} - -Value::const_iterator Value::end() const { - switch (type()) { - case arrayValue: - case objectValue: - if (value_.map_) - return const_iterator(value_.map_->end()); - break; - default: - break; - } - return {}; -} - -Value::iterator Value::begin() { - switch (type()) { - case arrayValue: - case objectValue: - if (value_.map_) - return iterator(value_.map_->begin()); - break; - default: - break; - } - return iterator(); -} - -Value::iterator Value::end() { - switch (type()) { - case arrayValue: - case objectValue: - if (value_.map_) - return iterator(value_.map_->end()); - break; - default: - break; - } - return iterator(); -} - -// class PathArgument -// ////////////////////////////////////////////////////////////////// - -PathArgument::PathArgument() : key_() {} - -PathArgument::PathArgument(ArrayIndex index) - : key_(), index_(index), kind_(kindIndex) {} - -PathArgument::PathArgument(const char* key) - : key_(key), index_(), kind_(kindKey) {} - -PathArgument::PathArgument(const String& key) - : key_(key.c_str()), index_(), kind_(kindKey) {} - -// class Path -// ////////////////////////////////////////////////////////////////// - -Path::Path(const String& path, - const PathArgument& a1, - const PathArgument& a2, - const PathArgument& a3, - const PathArgument& a4, - const PathArgument& a5) { - InArgs in; - in.reserve(5); - in.push_back(&a1); - in.push_back(&a2); - in.push_back(&a3); - in.push_back(&a4); - in.push_back(&a5); - makePath(path, in); -} - -void Path::makePath(const String& path, const InArgs& in) { - const char* current = path.c_str(); - const char* end = current + path.length(); - auto itInArg = in.begin(); - while (current != end) { - if (*current == '[') { - ++current; - if (*current == '%') - addPathInArg(path, in, itInArg, PathArgument::kindIndex); - else { - ArrayIndex index = 0; - for (; current != end && *current >= '0' && *current <= '9'; ++current) - index = index * 10 + ArrayIndex(*current - '0'); - args_.push_back(index); - } - if (current == end || *++current != ']') - invalidPath(path, int(current - path.c_str())); - } else if (*current == '%') { - addPathInArg(path, in, itInArg, PathArgument::kindKey); - ++current; - } else if (*current == '.' || *current == ']') { - ++current; - } else { - const char* beginName = current; - while (current != end && !strchr("[.", *current)) - ++current; - args_.push_back(String(beginName, current)); - } - } -} - -void Path::addPathInArg(const String& /*path*/, - const InArgs& in, - InArgs::const_iterator& itInArg, - PathArgument::Kind kind) { - if (itInArg == in.end()) { - // Error: missing argument %d - } else if ((*itInArg)->kind_ != kind) { - // Error: bad argument type - } else { - args_.push_back(**itInArg++); - } -} - -void Path::invalidPath(const String& /*path*/, int /*location*/) { - // Error: invalid path. -} - -const Value& Path::resolve(const Value& root) const { - const Value* node = &root; - for (const auto& arg : args_) { - if (arg.kind_ == PathArgument::kindIndex) { - if (!node->isArray() || !node->isValidIndex(arg.index_)) { - // Error: unable to resolve path (array value expected at position... - return Value::null; - } - node = &((*node)[arg.index_]); - } else if (arg.kind_ == PathArgument::kindKey) { - if (!node->isObject()) { - // Error: unable to resolve path (object value expected at position...) - return Value::null; - } - node = &((*node)[arg.key_]); - if (node == &Value::nullSingleton()) { - // Error: unable to resolve path (object has no member named '' at - // position...) - return Value::null; - } - } - } - return *node; -} - -Value Path::resolve(const Value& root, const Value& defaultValue) const { - const Value* node = &root; - for (const auto& arg : args_) { - if (arg.kind_ == PathArgument::kindIndex) { - if (!node->isArray() || !node->isValidIndex(arg.index_)) - return defaultValue; - node = &((*node)[arg.index_]); - } else if (arg.kind_ == PathArgument::kindKey) { - if (!node->isObject()) - return defaultValue; - node = &((*node)[arg.key_]); - if (node == &Value::nullSingleton()) - return defaultValue; - } - } - return *node; -} - -Value& Path::make(Value& root) const { - Value* node = &root; - for (const auto& arg : args_) { - if (arg.kind_ == PathArgument::kindIndex) { - if (!node->isArray()) { - // Error: node is not an array at position ... - } - node = &((*node)[arg.index_]); - } else if (arg.kind_ == PathArgument::kindKey) { - if (!node->isObject()) { - // Error: node is not an object at position... - } - node = &((*node)[arg.key_]); - } - } - return *node; -} - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_value.cpp -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_writer.cpp -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#if !defined(JSON_IS_AMALGAMATION) -#include "json_tool.h" -#include <json/writer.h> -#endif // if !defined(JSON_IS_AMALGAMATION) -#include <cassert> -#include <cstring> -#include <iomanip> -#include <memory> -#include <set> -#include <sstream> -#include <utility> - -#if __cplusplus >= 201103L -#include <cmath> -#include <cstdio> - -#if !defined(isnan) -#define isnan std::isnan -#endif - -#if !defined(isfinite) -#define isfinite std::isfinite -#endif - -#else -#include <cmath> -#include <cstdio> - -#if defined(_MSC_VER) -#if !defined(isnan) -#include <float.h> -#define isnan _isnan -#endif - -#if !defined(isfinite) -#include <float.h> -#define isfinite _finite -#endif - -#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES) -#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 -#endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES - -#endif //_MSC_VER - -#if defined(__sun) && defined(__SVR4) // Solaris -#if !defined(isfinite) -#include <ieeefp.h> -#define isfinite finite -#endif -#endif - -#if defined(__hpux) -#if !defined(isfinite) -#if defined(__ia64) && !defined(finite) -#define isfinite(x) \ - ((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _IsFinite(x))) -#endif -#endif -#endif - -#if !defined(isnan) -// IEEE standard states that NaN values will not compare to themselves -#define isnan(x) (x != x) -#endif - -#if !defined(__APPLE__) -#if !defined(isfinite) -#define isfinite finite -#endif -#endif -#endif - -#if defined(_MSC_VER) -// Disable warning about strdup being deprecated. -#pragma warning(disable : 4996) -#endif - -namespace Json { - -#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) -typedef std::unique_ptr<StreamWriter> StreamWriterPtr; -#else -typedef std::unique_ptr<StreamWriter> StreamWriterPtr; -#endif - -String valueToString(LargestInt value) { - UIntToStringBuffer buffer; - char* current = buffer + sizeof(buffer); - if (value == Value::minLargestInt) { - uintToString(LargestUInt(Value::maxLargestInt) + 1, current); - *--current = '-'; - } else if (value < 0) { - uintToString(LargestUInt(-value), current); - *--current = '-'; - } else { - uintToString(LargestUInt(value), current); - } - assert(current >= buffer); - return current; -} - -String valueToString(LargestUInt value) { - UIntToStringBuffer buffer; - char* current = buffer + sizeof(buffer); - uintToString(value, current); - assert(current >= buffer); - return current; -} - -#if defined(JSON_HAS_INT64) - -String valueToString(Int value) { return valueToString(LargestInt(value)); } - -String valueToString(UInt value) { return valueToString(LargestUInt(value)); } - -#endif // # if defined(JSON_HAS_INT64) - -namespace { -String valueToString(double value, - bool useSpecialFloats, - unsigned int precision, - PrecisionType precisionType) { - // Print into the buffer. We need not request the alternative representation - // that always has a decimal point because JSON doesn't distinguish the - // concepts of reals and integers. - if (!isfinite(value)) { - static const char* const reps[2][3] = {{"NaN", "-Infinity", "Infinity"}, - {"null", "-1e+9999", "1e+9999"}}; - return reps[useSpecialFloats ? 0 : 1] - [isnan(value) ? 0 : (value < 0) ? 1 : 2]; - } - - String buffer(size_t(36), '\0'); - while (true) { - int len = jsoncpp_snprintf( - &*buffer.begin(), buffer.size(), - (precisionType == PrecisionType::significantDigits) ? "%.*g" : "%.*f", - precision, value); - assert(len >= 0); - auto wouldPrint = static_cast<size_t>(len); - if (wouldPrint >= buffer.size()) { - buffer.resize(wouldPrint + 1); - continue; - } - buffer.resize(wouldPrint); - break; - } - - buffer.erase(fixNumericLocale(buffer.begin(), buffer.end()), buffer.end()); - - // strip the zero padding from the right - if (precisionType == PrecisionType::decimalPlaces) { - buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end()), buffer.end()); - } - - // try to ensure we preserve the fact that this was given to us as a double on - // input - if (buffer.find('.') == buffer.npos && buffer.find('e') == buffer.npos) { - buffer += ".0"; - } - return buffer; -} -} // namespace - -String valueToString(double value, - unsigned int precision, - PrecisionType precisionType) { - return valueToString(value, false, precision, precisionType); -} - -String valueToString(bool value) { return value ? "true" : "false"; } - -static bool isAnyCharRequiredQuoting(char const* s, size_t n) { - assert(s || !n); - - char const* const end = s + n; - for (char const* cur = s; cur < end; ++cur) { - if (*cur == '\\' || *cur == '\"' || *cur < ' ' || - static_cast<unsigned char>(*cur) < 0x80) - return true; - } - return false; -} - -static unsigned int utf8ToCodepoint(const char*& s, const char* e) { - const unsigned int REPLACEMENT_CHARACTER = 0xFFFD; - - unsigned int firstByte = static_cast<unsigned char>(*s); - - if (firstByte < 0x80) - return firstByte; - - if (firstByte < 0xE0) { - if (e - s < 2) - return REPLACEMENT_CHARACTER; - - unsigned int calculated = - ((firstByte & 0x1F) << 6) | (static_cast<unsigned int>(s[1]) & 0x3F); - s += 1; - // oversized encoded characters are invalid - return calculated < 0x80 ? REPLACEMENT_CHARACTER : calculated; - } - - if (firstByte < 0xF0) { - if (e - s < 3) - return REPLACEMENT_CHARACTER; - - unsigned int calculated = ((firstByte & 0x0F) << 12) | - ((static_cast<unsigned int>(s[1]) & 0x3F) << 6) | - (static_cast<unsigned int>(s[2]) & 0x3F); - s += 2; - // surrogates aren't valid codepoints itself - // shouldn't be UTF-8 encoded - if (calculated >= 0xD800 && calculated <= 0xDFFF) - return REPLACEMENT_CHARACTER; - // oversized encoded characters are invalid - return calculated < 0x800 ? REPLACEMENT_CHARACTER : calculated; - } - - if (firstByte < 0xF8) { - if (e - s < 4) - return REPLACEMENT_CHARACTER; - - unsigned int calculated = ((firstByte & 0x07) << 18) | - ((static_cast<unsigned int>(s[1]) & 0x3F) << 12) | - ((static_cast<unsigned int>(s[2]) & 0x3F) << 6) | - (static_cast<unsigned int>(s[3]) & 0x3F); - s += 3; - // oversized encoded characters are invalid - return calculated < 0x10000 ? REPLACEMENT_CHARACTER : calculated; - } - - return REPLACEMENT_CHARACTER; -} - -static const char hex2[] = "000102030405060708090a0b0c0d0e0f" - "101112131415161718191a1b1c1d1e1f" - "202122232425262728292a2b2c2d2e2f" - "303132333435363738393a3b3c3d3e3f" - "404142434445464748494a4b4c4d4e4f" - "505152535455565758595a5b5c5d5e5f" - "606162636465666768696a6b6c6d6e6f" - "707172737475767778797a7b7c7d7e7f" - "808182838485868788898a8b8c8d8e8f" - "909192939495969798999a9b9c9d9e9f" - "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" - "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" - "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" - "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" - "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" - "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; - -static String toHex16Bit(unsigned int x) { - const unsigned int hi = (x >> 8) & 0xff; - const unsigned int lo = x & 0xff; - String result(4, ' '); - result[0] = hex2[2 * hi]; - result[1] = hex2[2 * hi + 1]; - result[2] = hex2[2 * lo]; - result[3] = hex2[2 * lo + 1]; - return result; -} - -static String valueToQuotedStringN(const char* value, unsigned length) { - if (value == nullptr) - return ""; - - if (!isAnyCharRequiredQuoting(value, length)) - return String("\"") + value + "\""; - // We have to walk value and escape any special characters. - // Appending to String is not efficient, but this should be rare. - // (Note: forward slashes are *not* rare, but I am not escaping them.) - String::size_type maxsize = length * 2 + 3; // allescaped+quotes+NULL - String result; - result.reserve(maxsize); // to avoid lots of mallocs - result += "\""; - char const* end = value + length; - for (const char* c = value; c != end; ++c) { - switch (*c) { - case '\"': - result += "\\\""; - break; - case '\\': - result += "\\\\"; - break; - case '\b': - result += "\\b"; - break; - case '\f': - result += "\\f"; - break; - case '\n': - result += "\\n"; - break; - case '\r': - result += "\\r"; - break; - case '\t': - result += "\\t"; - break; - // case '/': - // Even though \/ is considered a legal escape in JSON, a bare - // slash is also legal, so I see no reason to escape it. - // (I hope I am not misunderstanding something.) - // blep notes: actually escaping \/ may be useful in javascript to avoid </ - // sequence. - // Should add a flag to allow this compatibility mode and prevent this - // sequence from occurring. - default: { - unsigned int cp = utf8ToCodepoint(c, end); - // don't escape non-control characters - // (short escape sequence are applied above) - if (cp < 0x80 && cp >= 0x20) - result += static_cast<char>(cp); - else if (cp < 0x10000) { // codepoint is in Basic Multilingual Plane - result += "\\u"; - result += toHex16Bit(cp); - } else { // codepoint is not in Basic Multilingual Plane - // convert to surrogate pair first - cp -= 0x10000; - result += "\\u"; - result += toHex16Bit((cp >> 10) + 0xD800); - result += "\\u"; - result += toHex16Bit((cp & 0x3FF) + 0xDC00); - } - } break; - } - } - result += "\""; - return result; -} - -String valueToQuotedString(const char* value) { - return valueToQuotedStringN(value, static_cast<unsigned int>(strlen(value))); -} - -// Class Writer -// ////////////////////////////////////////////////////////////////// -Writer::~Writer() = default; - -// Class FastWriter -// ////////////////////////////////////////////////////////////////// - -FastWriter::FastWriter() - - = default; - -void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = true; } - -void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; } - -void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; } - -String FastWriter::write(const Value& root) { - document_.clear(); - writeValue(root); - if (!omitEndingLineFeed_) - document_ += '\n'; - return document_; -} - -void FastWriter::writeValue(const Value& value) { - switch (value.type()) { - case nullValue: - if (!dropNullPlaceholders_) - document_ += "null"; - break; - case intValue: - document_ += valueToString(value.asLargestInt()); - break; - case uintValue: - document_ += valueToString(value.asLargestUInt()); - break; - case realValue: - document_ += valueToString(value.asDouble()); - break; - case stringValue: { - // Is NULL possible for value.string_? No. - char const* str; - char const* end; - bool ok = value.getString(&str, &end); - if (ok) - document_ += valueToQuotedStringN(str, static_cast<unsigned>(end - str)); - break; - } - case booleanValue: - document_ += valueToString(value.asBool()); - break; - case arrayValue: { - document_ += '['; - ArrayIndex size = value.size(); - for (ArrayIndex index = 0; index < size; ++index) { - if (index > 0) - document_ += ','; - writeValue(value[index]); - } - document_ += ']'; - } break; - case objectValue: { - Value::Members members(value.getMemberNames()); - document_ += '{'; - for (auto it = members.begin(); it != members.end(); ++it) { - const String& name = *it; - if (it != members.begin()) - document_ += ','; - document_ += valueToQuotedStringN(name.data(), - static_cast<unsigned>(name.length())); - document_ += yamlCompatibilityEnabled_ ? ": " : ":"; - writeValue(value[name]); - } - document_ += '}'; - } break; - } -} - -// Class StyledWriter -// ////////////////////////////////////////////////////////////////// - -StyledWriter::StyledWriter() = default; - -String StyledWriter::write(const Value& root) { - document_.clear(); - addChildValues_ = false; - indentString_.clear(); - writeCommentBeforeValue(root); - writeValue(root); - writeCommentAfterValueOnSameLine(root); - document_ += '\n'; - return document_; -} - -void StyledWriter::writeValue(const Value& value) { - switch (value.type()) { - case nullValue: - pushValue("null"); - break; - case intValue: - pushValue(valueToString(value.asLargestInt())); - break; - case uintValue: - pushValue(valueToString(value.asLargestUInt())); - break; - case realValue: - pushValue(valueToString(value.asDouble())); - break; - case stringValue: { - // Is NULL possible for value.string_? No. - char const* str; - char const* end; - bool ok = value.getString(&str, &end); - if (ok) - pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str))); - else - pushValue(""); - break; - } - case booleanValue: - pushValue(valueToString(value.asBool())); - break; - case arrayValue: - writeArrayValue(value); - break; - case objectValue: { - Value::Members members(value.getMemberNames()); - if (members.empty()) - pushValue("{}"); - else { - writeWithIndent("{"); - indent(); - auto it = members.begin(); - for (;;) { - const String& name = *it; - const Value& childValue = value[name]; - writeCommentBeforeValue(childValue); - writeWithIndent(valueToQuotedString(name.c_str())); - document_ += " : "; - writeValue(childValue); - if (++it == members.end()) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - document_ += ','; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("}"); - } - } break; - } -} - -void StyledWriter::writeArrayValue(const Value& value) { - unsigned size = value.size(); - if (size == 0) - pushValue("[]"); - else { - bool isArrayMultiLine = isMultilineArray(value); - if (isArrayMultiLine) { - writeWithIndent("["); - indent(); - bool hasChildValue = !childValues_.empty(); - unsigned index = 0; - for (;;) { - const Value& childValue = value[index]; - writeCommentBeforeValue(childValue); - if (hasChildValue) - writeWithIndent(childValues_[index]); - else { - writeIndent(); - writeValue(childValue); - } - if (++index == size) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - document_ += ','; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("]"); - } else // output on a single line - { - assert(childValues_.size() == size); - document_ += "[ "; - for (unsigned index = 0; index < size; ++index) { - if (index > 0) - document_ += ", "; - document_ += childValues_[index]; - } - document_ += " ]"; - } - } -} - -bool StyledWriter::isMultilineArray(const Value& value) { - ArrayIndex const size = value.size(); - bool isMultiLine = size * 3 >= rightMargin_; - childValues_.clear(); - for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { - const Value& childValue = value[index]; - isMultiLine = ((childValue.isArray() || childValue.isObject()) && - !childValue.empty()); - } - if (!isMultiLine) // check if line length > max line length - { - childValues_.reserve(size); - addChildValues_ = true; - ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' - for (ArrayIndex index = 0; index < size; ++index) { - if (hasCommentForValue(value[index])) { - isMultiLine = true; - } - writeValue(value[index]); - lineLength += static_cast<ArrayIndex>(childValues_[index].length()); - } - addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= rightMargin_; - } - return isMultiLine; -} - -void StyledWriter::pushValue(const String& value) { - if (addChildValues_) - childValues_.push_back(value); - else - document_ += value; -} - -void StyledWriter::writeIndent() { - if (!document_.empty()) { - char last = document_[document_.length() - 1]; - if (last == ' ') // already indented - return; - if (last != '\n') // Comments may add new-line - document_ += '\n'; - } - document_ += indentString_; -} - -void StyledWriter::writeWithIndent(const String& value) { - writeIndent(); - document_ += value; -} - -void StyledWriter::indent() { indentString_ += String(indentSize_, ' '); } - -void StyledWriter::unindent() { - assert(indentString_.size() >= indentSize_); - indentString_.resize(indentString_.size() - indentSize_); -} - -void StyledWriter::writeCommentBeforeValue(const Value& root) { - if (!root.hasComment(commentBefore)) - return; - - document_ += '\n'; - writeIndent(); - const String& comment = root.getComment(commentBefore); - String::const_iterator iter = comment.begin(); - while (iter != comment.end()) { - document_ += *iter; - if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/')) - writeIndent(); - ++iter; - } - - // Comments are stripped of trailing newlines, so add one here - document_ += '\n'; -} - -void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) { - if (root.hasComment(commentAfterOnSameLine)) - document_ += " " + root.getComment(commentAfterOnSameLine); - - if (root.hasComment(commentAfter)) { - document_ += '\n'; - document_ += root.getComment(commentAfter); - document_ += '\n'; - } -} - -bool StyledWriter::hasCommentForValue(const Value& value) { - return value.hasComment(commentBefore) || - value.hasComment(commentAfterOnSameLine) || - value.hasComment(commentAfter); -} - -// Class StyledStreamWriter -// ////////////////////////////////////////////////////////////////// - -StyledStreamWriter::StyledStreamWriter(String indentation) - : document_(nullptr), indentation_(std::move(indentation)), - addChildValues_(), indented_(false) {} - -void StyledStreamWriter::write(OStream& out, const Value& root) { - document_ = &out; - addChildValues_ = false; - indentString_.clear(); - indented_ = true; - writeCommentBeforeValue(root); - if (!indented_) - writeIndent(); - indented_ = true; - writeValue(root); - writeCommentAfterValueOnSameLine(root); - *document_ << "\n"; - document_ = nullptr; // Forget the stream, for safety. -} - -void StyledStreamWriter::writeValue(const Value& value) { - switch (value.type()) { - case nullValue: - pushValue("null"); - break; - case intValue: - pushValue(valueToString(value.asLargestInt())); - break; - case uintValue: - pushValue(valueToString(value.asLargestUInt())); - break; - case realValue: - pushValue(valueToString(value.asDouble())); - break; - case stringValue: { - // Is NULL possible for value.string_? No. - char const* str; - char const* end; - bool ok = value.getString(&str, &end); - if (ok) - pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str))); - else - pushValue(""); - break; - } - case booleanValue: - pushValue(valueToString(value.asBool())); - break; - case arrayValue: - writeArrayValue(value); - break; - case objectValue: { - Value::Members members(value.getMemberNames()); - if (members.empty()) - pushValue("{}"); - else { - writeWithIndent("{"); - indent(); - auto it = members.begin(); - for (;;) { - const String& name = *it; - const Value& childValue = value[name]; - writeCommentBeforeValue(childValue); - writeWithIndent(valueToQuotedString(name.c_str())); - *document_ << " : "; - writeValue(childValue); - if (++it == members.end()) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - *document_ << ","; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("}"); - } - } break; - } -} - -void StyledStreamWriter::writeArrayValue(const Value& value) { - unsigned size = value.size(); - if (size == 0) - pushValue("[]"); - else { - bool isArrayMultiLine = isMultilineArray(value); - if (isArrayMultiLine) { - writeWithIndent("["); - indent(); - bool hasChildValue = !childValues_.empty(); - unsigned index = 0; - for (;;) { - const Value& childValue = value[index]; - writeCommentBeforeValue(childValue); - if (hasChildValue) - writeWithIndent(childValues_[index]); - else { - if (!indented_) - writeIndent(); - indented_ = true; - writeValue(childValue); - indented_ = false; - } - if (++index == size) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - *document_ << ","; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("]"); - } else // output on a single line - { - assert(childValues_.size() == size); - *document_ << "[ "; - for (unsigned index = 0; index < size; ++index) { - if (index > 0) - *document_ << ", "; - *document_ << childValues_[index]; - } - *document_ << " ]"; - } - } -} - -bool StyledStreamWriter::isMultilineArray(const Value& value) { - ArrayIndex const size = value.size(); - bool isMultiLine = size * 3 >= rightMargin_; - childValues_.clear(); - for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { - const Value& childValue = value[index]; - isMultiLine = ((childValue.isArray() || childValue.isObject()) && - !childValue.empty()); - } - if (!isMultiLine) // check if line length > max line length - { - childValues_.reserve(size); - addChildValues_ = true; - ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' - for (ArrayIndex index = 0; index < size; ++index) { - if (hasCommentForValue(value[index])) { - isMultiLine = true; - } - writeValue(value[index]); - lineLength += static_cast<ArrayIndex>(childValues_[index].length()); - } - addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= rightMargin_; - } - return isMultiLine; -} - -void StyledStreamWriter::pushValue(const String& value) { - if (addChildValues_) - childValues_.push_back(value); - else - *document_ << value; -} - -void StyledStreamWriter::writeIndent() { - // blep intended this to look at the so-far-written string - // to determine whether we are already indented, but - // with a stream we cannot do that. So we rely on some saved state. - // The caller checks indented_. - *document_ << '\n' << indentString_; -} - -void StyledStreamWriter::writeWithIndent(const String& value) { - if (!indented_) - writeIndent(); - *document_ << value; - indented_ = false; -} - -void StyledStreamWriter::indent() { indentString_ += indentation_; } - -void StyledStreamWriter::unindent() { - assert(indentString_.size() >= indentation_.size()); - indentString_.resize(indentString_.size() - indentation_.size()); -} - -void StyledStreamWriter::writeCommentBeforeValue(const Value& root) { - if (!root.hasComment(commentBefore)) - return; - - if (!indented_) - writeIndent(); - const String& comment = root.getComment(commentBefore); - String::const_iterator iter = comment.begin(); - while (iter != comment.end()) { - *document_ << *iter; - if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/')) - // writeIndent(); // would include newline - *document_ << indentString_; - ++iter; - } - indented_ = false; -} - -void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) { - if (root.hasComment(commentAfterOnSameLine)) - *document_ << ' ' << root.getComment(commentAfterOnSameLine); - - if (root.hasComment(commentAfter)) { - writeIndent(); - *document_ << root.getComment(commentAfter); - } - indented_ = false; -} - -bool StyledStreamWriter::hasCommentForValue(const Value& value) { - return value.hasComment(commentBefore) || - value.hasComment(commentAfterOnSameLine) || - value.hasComment(commentAfter); -} - -////////////////////////// -// BuiltStyledStreamWriter - -/// Scoped enums are not available until C++11. -struct CommentStyle { - /// Decide whether to write comments. - enum Enum { - None, ///< Drop all comments. - Most, ///< Recover odd behavior of previous versions (not implemented yet). - All ///< Keep all comments. - }; -}; - -struct BuiltStyledStreamWriter : public StreamWriter { - BuiltStyledStreamWriter(String indentation, - CommentStyle::Enum cs, - String colonSymbol, - String nullSymbol, - String endingLineFeedSymbol, - bool useSpecialFloats, - unsigned int precision, - PrecisionType precisionType); - int write(Value const& root, OStream* sout) override; - -private: - void writeValue(Value const& value); - void writeArrayValue(Value const& value); - bool isMultilineArray(Value const& value); - void pushValue(String const& value); - void writeIndent(); - void writeWithIndent(String const& value); - void indent(); - void unindent(); - void writeCommentBeforeValue(Value const& root); - void writeCommentAfterValueOnSameLine(Value const& root); - static bool hasCommentForValue(const Value& value); - - typedef std::vector<String> ChildValues; - - ChildValues childValues_; - String indentString_; - unsigned int rightMargin_; - String indentation_; - CommentStyle::Enum cs_; - String colonSymbol_; - String nullSymbol_; - String endingLineFeedSymbol_; - bool addChildValues_ : 1; - bool indented_ : 1; - bool useSpecialFloats_ : 1; - unsigned int precision_; - PrecisionType precisionType_; -}; -BuiltStyledStreamWriter::BuiltStyledStreamWriter(String indentation, - CommentStyle::Enum cs, - String colonSymbol, - String nullSymbol, - String endingLineFeedSymbol, - bool useSpecialFloats, - unsigned int precision, - PrecisionType precisionType) - : rightMargin_(74), indentation_(std::move(indentation)), cs_(cs), - colonSymbol_(std::move(colonSymbol)), nullSymbol_(std::move(nullSymbol)), - endingLineFeedSymbol_(std::move(endingLineFeedSymbol)), - addChildValues_(false), indented_(false), - useSpecialFloats_(useSpecialFloats), precision_(precision), - precisionType_(precisionType) {} -int BuiltStyledStreamWriter::write(Value const& root, OStream* sout) { - sout_ = sout; - addChildValues_ = false; - indented_ = true; - indentString_.clear(); - writeCommentBeforeValue(root); - if (!indented_) - writeIndent(); - indented_ = true; - writeValue(root); - writeCommentAfterValueOnSameLine(root); - *sout_ << endingLineFeedSymbol_; - sout_ = nullptr; - return 0; -} -void BuiltStyledStreamWriter::writeValue(Value const& value) { - switch (value.type()) { - case nullValue: - pushValue(nullSymbol_); - break; - case intValue: - pushValue(valueToString(value.asLargestInt())); - break; - case uintValue: - pushValue(valueToString(value.asLargestUInt())); - break; - case realValue: - pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_, - precisionType_)); - break; - case stringValue: { - // Is NULL is possible for value.string_? No. - char const* str; - char const* end; - bool ok = value.getString(&str, &end); - if (ok) - pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str))); - else - pushValue(""); - break; - } - case booleanValue: - pushValue(valueToString(value.asBool())); - break; - case arrayValue: - writeArrayValue(value); - break; - case objectValue: { - Value::Members members(value.getMemberNames()); - if (members.empty()) - pushValue("{}"); - else { - writeWithIndent("{"); - indent(); - auto it = members.begin(); - for (;;) { - String const& name = *it; - Value const& childValue = value[name]; - writeCommentBeforeValue(childValue); - writeWithIndent(valueToQuotedStringN( - name.data(), static_cast<unsigned>(name.length()))); - *sout_ << colonSymbol_; - writeValue(childValue); - if (++it == members.end()) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - *sout_ << ","; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("}"); - } - } break; - } -} - -void BuiltStyledStreamWriter::writeArrayValue(Value const& value) { - unsigned size = value.size(); - if (size == 0) - pushValue("[]"); - else { - bool isMultiLine = (cs_ == CommentStyle::All) || isMultilineArray(value); - if (isMultiLine) { - writeWithIndent("["); - indent(); - bool hasChildValue = !childValues_.empty(); - unsigned index = 0; - for (;;) { - Value const& childValue = value[index]; - writeCommentBeforeValue(childValue); - if (hasChildValue) - writeWithIndent(childValues_[index]); - else { - if (!indented_) - writeIndent(); - indented_ = true; - writeValue(childValue); - indented_ = false; - } - if (++index == size) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - *sout_ << ","; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("]"); - } else // output on a single line - { - assert(childValues_.size() == size); - *sout_ << "["; - if (!indentation_.empty()) - *sout_ << " "; - for (unsigned index = 0; index < size; ++index) { - if (index > 0) - *sout_ << ((!indentation_.empty()) ? ", " : ","); - *sout_ << childValues_[index]; - } - if (!indentation_.empty()) - *sout_ << " "; - *sout_ << "]"; - } - } -} - -bool BuiltStyledStreamWriter::isMultilineArray(Value const& value) { - ArrayIndex const size = value.size(); - bool isMultiLine = size * 3 >= rightMargin_; - childValues_.clear(); - for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { - Value const& childValue = value[index]; - isMultiLine = ((childValue.isArray() || childValue.isObject()) && - !childValue.empty()); - } - if (!isMultiLine) // check if line length > max line length - { - childValues_.reserve(size); - addChildValues_ = true; - ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' - for (ArrayIndex index = 0; index < size; ++index) { - if (hasCommentForValue(value[index])) { - isMultiLine = true; - } - writeValue(value[index]); - lineLength += static_cast<ArrayIndex>(childValues_[index].length()); - } - addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= rightMargin_; - } - return isMultiLine; -} - -void BuiltStyledStreamWriter::pushValue(String const& value) { - if (addChildValues_) - childValues_.push_back(value); - else - *sout_ << value; -} - -void BuiltStyledStreamWriter::writeIndent() { - // blep intended this to look at the so-far-written string - // to determine whether we are already indented, but - // with a stream we cannot do that. So we rely on some saved state. - // The caller checks indented_. - - if (!indentation_.empty()) { - // In this case, drop newlines too. - *sout_ << '\n' << indentString_; - } -} - -void BuiltStyledStreamWriter::writeWithIndent(String const& value) { - if (!indented_) - writeIndent(); - *sout_ << value; - indented_ = false; -} - -void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; } - -void BuiltStyledStreamWriter::unindent() { - assert(indentString_.size() >= indentation_.size()); - indentString_.resize(indentString_.size() - indentation_.size()); -} - -void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) { - if (cs_ == CommentStyle::None) - return; - if (!root.hasComment(commentBefore)) - return; - - if (!indented_) - writeIndent(); - const String& comment = root.getComment(commentBefore); - String::const_iterator iter = comment.begin(); - while (iter != comment.end()) { - *sout_ << *iter; - if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/')) - // writeIndent(); // would write extra newline - *sout_ << indentString_; - ++iter; - } - indented_ = false; -} - -void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine( - Value const& root) { - if (cs_ == CommentStyle::None) - return; - if (root.hasComment(commentAfterOnSameLine)) - *sout_ << " " + root.getComment(commentAfterOnSameLine); - - if (root.hasComment(commentAfter)) { - writeIndent(); - *sout_ << root.getComment(commentAfter); - } -} - -// static -bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) { - return value.hasComment(commentBefore) || - value.hasComment(commentAfterOnSameLine) || - value.hasComment(commentAfter); -} - -/////////////// -// StreamWriter - -StreamWriter::StreamWriter() : sout_(nullptr) {} -StreamWriter::~StreamWriter() = default; -StreamWriter::Factory::~Factory() = default; -StreamWriterBuilder::StreamWriterBuilder() { setDefaults(&settings_); } -StreamWriterBuilder::~StreamWriterBuilder() = default; -StreamWriter* StreamWriterBuilder::newStreamWriter() const { - String indentation = settings_["indentation"].asString(); - String cs_str = settings_["commentStyle"].asString(); - String pt_str = settings_["precisionType"].asString(); - bool eyc = settings_["enableYAMLCompatibility"].asBool(); - bool dnp = settings_["dropNullPlaceholders"].asBool(); - bool usf = settings_["useSpecialFloats"].asBool(); - unsigned int pre = settings_["precision"].asUInt(); - CommentStyle::Enum cs = CommentStyle::All; - if (cs_str == "All") { - cs = CommentStyle::All; - } else if (cs_str == "None") { - cs = CommentStyle::None; - } else { - throwRuntimeError("commentStyle must be 'All' or 'None'"); - } - PrecisionType precisionType(significantDigits); - if (pt_str == "significant") { - precisionType = PrecisionType::significantDigits; - } else if (pt_str == "decimal") { - precisionType = PrecisionType::decimalPlaces; - } else { - throwRuntimeError("precisionType must be 'significant' or 'decimal'"); - } - String colonSymbol = " : "; - if (eyc) { - colonSymbol = ": "; - } else if (indentation.empty()) { - colonSymbol = ":"; - } - String nullSymbol = "null"; - if (dnp) { - nullSymbol.clear(); - } - if (pre > 17) - pre = 17; - String endingLineFeedSymbol; - return new BuiltStyledStreamWriter(indentation, cs, colonSymbol, nullSymbol, - endingLineFeedSymbol, usf, pre, - precisionType); -} -static void getValidWriterKeys(std::set<String>* valid_keys) { - valid_keys->clear(); - valid_keys->insert("indentation"); - valid_keys->insert("commentStyle"); - valid_keys->insert("enableYAMLCompatibility"); - valid_keys->insert("dropNullPlaceholders"); - valid_keys->insert("useSpecialFloats"); - valid_keys->insert("precision"); - valid_keys->insert("precisionType"); -} -bool StreamWriterBuilder::validate(Json::Value* invalid) const { - Json::Value my_invalid; - if (!invalid) - invalid = &my_invalid; // so we do not need to test for NULL - Json::Value& inv = *invalid; - std::set<String> valid_keys; - getValidWriterKeys(&valid_keys); - Value::Members keys = settings_.getMemberNames(); - size_t n = keys.size(); - for (size_t i = 0; i < n; ++i) { - String const& key = keys[i]; - if (valid_keys.find(key) == valid_keys.end()) { - inv[key] = settings_[key]; - } - } - return inv.empty(); -} -Value& StreamWriterBuilder::operator[](const String& key) { - return settings_[key]; -} -// static -void StreamWriterBuilder::setDefaults(Json::Value* settings) { - //! [StreamWriterBuilderDefaults] - (*settings)["commentStyle"] = "All"; - (*settings)["indentation"] = "\t"; - (*settings)["enableYAMLCompatibility"] = false; - (*settings)["dropNullPlaceholders"] = false; - (*settings)["useSpecialFloats"] = false; - (*settings)["precision"] = 17; - (*settings)["precisionType"] = "significant"; - //! [StreamWriterBuilderDefaults] -} - -String writeString(StreamWriter::Factory const& factory, Value const& root) { - OStringStream sout; - StreamWriterPtr const writer(factory.newStreamWriter()); - writer->write(root, &sout); - return sout.str(); -} - -OStream& operator<<(OStream& sout, Value const& root) { - StreamWriterBuilder builder; - StreamWriterPtr const writer(builder.newStreamWriter()); - writer->write(root, &sout); - return sout; -} - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_writer.cpp -// ////////////////////////////////////////////////////////////////////// - - - - -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/main.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,207 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include <iostream> -#include <sstream> -#include <emscripten/emscripten.h> -#include "TestStoneCodeGen_generated.hpp" - -using std::stringstream; - -int main() -{ - std::cout << "Hello world from testWasmIntegrated! (this is sent from C++)" << std::endl; - try - { - const char* jsonData = R"bgo({"definition": - { - "val" : [ "berk", 42 ], - "zozo" : { "23": "zloutch", "lalala": 42} - } - })bgo"; - std::string strValue(jsonData); - - Json::Value readValue; - - Json::CharReaderBuilder builder; - Json::CharReader* reader = builder.newCharReader(); - - StoneSmartPtr<Json::CharReader> ptr(reader); - - std::string errors; - - bool ok = reader->parse( - strValue.c_str(), - strValue.c_str() + strValue.size(), - &readValue, - &errors - ); - if (!ok) - { - std::stringstream ss; - ss << "Jsoncpp parsing error: " << errors; - throw std::runtime_error(ss.str()); - } - std::cout << "Json parsing OK" << std::endl; - std::cout << readValue << std::endl; - } - catch(std::exception& e) - { - std::cout << "Json parsing THROW" << std::endl; - std::cout << "e.what() = " << e.what() << std::endl; - } -} - -extern "C" void SendMessageFromCppJS(const char* message); -extern "C" void SendFreeTextFromCppJS(const char* message); - -#define HANDLE_MESSAGE(Type,value) \ - stringstream ss; \ - ss << "Received an instance of:\n" #Type "\n. Here's the dump:\n"; \ - TestStoneCodeGen::StoneDumpValue(ss, value, 0); \ - SendFreeTextFromCppJS(ss.str().c_str()); \ - return true; - -#define ECHO_MESSAGE(Type,value) \ - stringstream ss; \ - ss << "Received an instance of:\n" #Type "\n. Here's the dump:\n"; \ - TestStoneCodeGen::StoneDumpValue(ss, value, 0); \ - SendFreeTextFromCppJS(ss.str().c_str()); \ - std::string serializedInCpp = StoneSerialize(value); \ - SendMessageFromCppJS(serializedInCpp.c_str()); \ - return true; - -class MyHandler : public TestStoneCodeGen::IHandler -{ - public: - virtual bool Handle(const TestStoneCodeGen::A& value) override - { - HANDLE_MESSAGE(TestStoneCodeGen::A,value) - } - virtual bool Handle(const TestStoneCodeGen::B& value) override - { - HANDLE_MESSAGE(TestStoneCodeGen::B,value) - } - - virtual bool Handle(const TestStoneCodeGen::Message1& value) override - { - HANDLE_MESSAGE(TestStoneCodeGen::Message1,value) - } - - virtual bool Handle(const TestStoneCodeGen::Message2& value) override - { - HANDLE_MESSAGE(TestStoneCodeGen::Message2,value) - } - - virtual bool Handle(const TestStoneCodeGen::C& value) override - { - HANDLE_MESSAGE(TestStoneCodeGen::C,value) - } -}; - -class MyEchoHandler : public TestStoneCodeGen::IHandler -{ - public: - virtual bool Handle(const TestStoneCodeGen::A& value) override - { - ECHO_MESSAGE(TestStoneCodeGen::A,value) - } - virtual bool Handle(const TestStoneCodeGen::B& value) override - { - ECHO_MESSAGE(TestStoneCodeGen::B,value) - } - - virtual bool Handle(const TestStoneCodeGen::Message1& value) override - { - ECHO_MESSAGE(TestStoneCodeGen::Message1,value) - } - - virtual bool Handle(const TestStoneCodeGen::Message2& value) override - { - ECHO_MESSAGE(TestStoneCodeGen::Message2,value) - } - - virtual bool Handle(const TestStoneCodeGen::C& value) override - { - ECHO_MESSAGE(TestStoneCodeGen::C,value) - } -}; - -extern "C" void EMSCRIPTEN_KEEPALIVE SendMessageToCpp(const char* message) -{ - MyHandler handler; - try - { - bool handled = TestStoneCodeGen::StoneDispatchToHandler(message,&handler); - if(!handled) - { - SendFreeTextFromCppJS("This message is valid JSON, but was not handled!"); - } - } - catch(std::exception& e) - { - stringstream ss; - ss << "Error while parsing message: " << e.what() << "\n"; - SendFreeTextFromCppJS(ss.str().c_str()); - } -} - -extern "C" void EMSCRIPTEN_KEEPALIVE SendMessageToCppForEcho(const char* message) -{ - MyEchoHandler echoHandler; - try - { - bool handled = TestStoneCodeGen::StoneDispatchToHandler(message,&echoHandler); - if(!handled) - { - SendFreeTextFromCppJS("This message is valid JSON, but was not handled by the echo handler!"); - } - } - catch(std::exception& e) - { - stringstream ss; - ss << "Error while parsing message: " << e.what() << "\n"; - SendFreeTextFromCppJS(ss.str().c_str()); - } -} - -void EMSCRIPTEN_KEEPALIVE StartWasmApplication(const char* baseUri) -{ - printf("Hello! (this is sent from C++)\n"); - -// // recreate a command line from uri arguments and parse it -// boost::program_options::variables_map parameters; -// boost::program_options::options_description options; -// application->DeclareStartupOptions(options); -// startupParametersBuilder.GetStartupParameters(parameters, options); - -// context.reset(new OrthancStone::StoneApplicationContext(broker)); -// context->SetOrthancBaseUrl(baseUri); -// printf("Base URL to Orthanc API: [%s]\n", baseUri); -// context->SetWebService(OrthancStone::WasmWebService::GetInstance()); -// context->SetDelayedCallExecutor(OrthancStone::WasmDelayedCallExecutor::GetInstance()); -// application->Initialize(context.get(), statusBar_, parameters); -// application->InitializeWasm(); - -// // viewport->SetSize(width_, height_); -// printf("StartWasmApplication - completed\n"); - SendFreeTextFromCppJS("Hello world from C++!"); -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/serve.py Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- -# tested on python 3.4 ,python of lower version has different module organization. -# from https://gist.github.com/HaiyangXu/ec88cbdce3cdbac7b8d5 -import http.server -from http.server import HTTPServer, BaseHTTPRequestHandler -import socketserver - -PORT = 8080 - -Handler = http.server.SimpleHTTPRequestHandler - -Handler.extensions_map = { - '.manifest': 'text/cache-manifest', - '.html': 'text/html', - '.png': 'image/png', - '.jpg': 'image/jpg', - '.svg': 'image/svg+xml', - '.wasm': 'application/wasm', - '.css': 'text/css', - '.js': 'application/x-javascript', - '': 'application/octet-stream', # Default -} - -httpd = socketserver.TCPServer(("", PORT), Handler) - -print("serving at port", PORT) -httpd.serve_forever()
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/styles.css Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -.TestWasm-grid-container { - display: grid; - grid-template-columns: 0.55fr 0.55fr 0.55fr 0.55fr 0.6fr 1.1fr 1.1fr; - grid-template-rows: 1.1fr 0.9fr 0.2fr 0.3fr 0.1fr 0.3fr 0.1fr; - grid-template-areas: - "SerializedInput SerializedInput SerializedInput SerializedInput ButtonContainer CppOutput CppOutput" - "SerializedInput SerializedInput SerializedInput SerializedInput ButtonContainer CppOutput CppOutput" - ". . . . . . ." - "Test1 Test2 Test3 Test4 . . ." - ". . . . . . ." - "Test5 Test6 Test7 Test8 . . ." - "TestTsCppTs . . . . . ." - ". . . . . . ." - ; - height: 480px; - } - - .TestWasm-ButtonContainer { - display: grid; - grid-template-columns: 0.2fr 0.8fr 0.2fr; - grid-template-rows: 0.2fr 0.5fr 0.2fr 0.5fr 0.2fr 0.5fr 0.2fr; - grid-template-areas: - ". . ." - ". TriggerButton ." - ". . ." - ". ClearButton ." - ". . ." - ". ShowSchemaButton ." - ". . ." - ; - } - - .TestWasm-TriggerButton { grid-area: TriggerButton; } - - .TestWasm-ClearButton { grid-area: ClearButton; } - - .TestWasm-ShowSchemaButton { grid-area: ShowSchemaButton; } - - -.TestWasm-SerializedInput { grid-area: SerializedInput; } - -.TestWasm-CppOutput { grid-area: CppOutput; } - -.TestWasm-ButtonContainer { grid-area: ButtonContainer; } - -.TestWasm-Test1 { grid-area: Test1; } - -.TestWasm-Test2 { grid-area: Test2; } - -.TestWasm-Test3 { grid-area: Test3; } - -.TestWasm-Test4 { grid-area: Test4; } - -.TestWasm-Test5 { grid-area: Test5; } - -.TestWasm-Test6 { grid-area: Test6; } - -.TestWasm-Test7 { grid-area: Test7; } - -.TestWasm-Test8 { grid-area: Test8; } - -.TestWasm-ts-cpp-ts { grid-area: TestTsCppTs; } - -.TestWasm-button { - width:80px; -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/testWasmIntegrated.html Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -<!doctype html> - -<html lang="us"> - <head> - <meta charset="utf-8" /> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> - - <title>Javascript to WASM message passing</title> - <link href="styles.css" rel="stylesheet" /> - <!-- <link href="styles2.css" rel="stylesheet" /> --> - <!-- - <link href="testwasm_bootstrap.css" rel="stylesheet" /> - --> - <body> - <div class="TestWasm-grid-container"> - <textarea id="TestWasm-SerializedInput" class="TestWasm-SerializedInput">Serialized data should be put here.</textarea> - <textarea id="TestWasm-CppOutput" class="TestWasm-CppOutput">Free text and messages from C++ will appear here.</textarea> - <div class="TestWasm-ButtonContainer"> - <div class="TestWasm-TriggerButton"> - <button class="TestWasm-button" tool-selector="Trigger">Send message</button> - </div> - <div class="TestWasm-ClearButton"> - <button class="TestWasm-button" tool-selector="Clear">Clear</button> - </div> - <div class="TestWasm-ShowSchemaButton"> - <button class="TestWasm-button" tool-selector="ShowSchema">Show schema</button> - </div> - <!-- <button class="TestWasm-button TestWasm-hvcenter" tool-selector="Trigger">Send message</button> - <button class="TestWasm-button TestWasm-hvcenter" tool-selector="Clear">Clear</button> - <button class="TestWasm-button TestWasm-hvcenter" tool-selector="Show schema">Show schema</button> --> - </div> - - <div class="TestWasm-Test1"> - <button class="TestWasm-button" tool-selector="Test CppHandler message2">Test CppHandler message2</button> - </div> - <div class="TestWasm-Test2"> - <button class="TestWasm-button" tool-selector="Test 2">Test 2</button> - </div> - <div class="TestWasm-Test3"> - <button class="TestWasm-button" tool-selector="Test 3">Test 3</button> - </div> - <div class="TestWasm-Test4"> - <button class="TestWasm-button" tool-selector="Test 4">Test 4</button> - </div> - <div class="TestWasm-Test5"> - <button class="TestWasm-button" tool-selector="Test 5">Test 5</button> - </div> - <div class="TestWasm-Test6"> - <button class="TestWasm-button" tool-selector="Test 6">Test 6</button> - </div> - <div class="TestWasm-Test7"> - <button class="TestWasm-button" tool-selector="Test 7">Test 7</button> - </div> - <div class="TestWasm-Test8"> - <button class="TestWasm-button" tool-selector="Test 8">Test 8</button> - </div> - <div class="TestWasm-ts-cpp-ts"> - <button class="TestWasm-button" tool-selector="Test-ts-cpp-ts">Test ts-cpp-ts</button> - </div> - - <!-- <button class="TestWasm-button" class="TestWasm-Test1" tool-selector="Test 1">Test 1</button> - <button class="TestWasm-button" class="TestWasm-Test2" tool-selector="Test 2">Test 2</button> - <button class="TestWasm-button" class="TestWasm-Test3" tool-selector="Test 3">Test 3</button> - <button class="TestWasm-button" class="TestWasm-Test4" tool-selector="Test 4">Test 4</button> --> - - - - <!-- <div class="Trigger"></div> - <div class="Test1"></div> - <div class="Test2"></div> - <div class="Test3"></div> - <div class="Test4"></div> --> - </div> - - <!-- <div id="toolbox" style="height: 50px"> - <button tool-selector="line-measure" class="tool-selector">line</button> - </div> --> - <script type="text/javascript" src="testWasmIntegratedCpp.js"></script> - <script type="text/javascript" src="testWasmIntegratedApp.js"></script> -</body> - -</html>
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/testWasmIntegrated/testWasmIntegrated.ts Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,210 +0,0 @@ -var SendMessageToCpp: Function = null; -export var TestWasmIntegratedModule : any; - -import * as TestStoneCodeGen from './build-wasm/TestStoneCodeGen_generated' - -/* -+--------------------------------------------------+ -| install emscripten handlers | -+--------------------------------------------------+ -*/ - -// (<any> window).Module = { -// preRun: [ -// function() { -// console.log('Loading the Stone Framework using WebAssembly'); -// } -// ], -// postRun: [ -// function() { -// // This function is called by ".js" wrapper once the ".wasm" -// // WebAssembly module has been loaded and compiled by the -// // browser -// console.log('WebAssembly is ready'); -// // window.SendMessageToCpp = (<any> window).Module.cwrap('SendMessageToCpp', 'string', ['string']); -// // window.SendFreeTextToCpp = (<any> window).Module.cwrap('SendFreeTextToCpp', 'string', ['string']); -// } -// ], -// print: function(text : string) { -// console.log(text); -// }, -// printErr: function(text : string) { -// console.error(text); -// }, -// totalDependencies: 0 -// }; - -/* -+--------------------------------------------------+ -| install handlers | -+--------------------------------------------------+ -*/ -document.querySelectorAll(".TestWasm-button").forEach((e) => { - (e as HTMLButtonElement).addEventListener("click", () => { - ButtonClick(e.attributes["tool-selector"].value); - }); -}); - -/* -+--------------------------------------------------+ -| define stock messages | -+--------------------------------------------------+ -*/ -let schemaText: string = null; -fetch("testTestStoneCodeGen.yaml").then(function(res) {return res.text();}).then(function(text) {schemaText = text;}); - -let stockSerializedMessages = new Map<string,string>(); -stockSerializedMessages["Test CppHandler message2"] = null; -fetch("cppHandler_test_Message2.json").then(function(res) {return res.text();}).then(function(text) {stockSerializedMessages["Test CppHandler message2"] = text;}); - -stockSerializedMessages["Test 2"] = ` { - "type" : "TestStoneCodeGen.Message1", - "value" : { - "memberInt32" : -987, - "memberString" : "Salomé", - "memberEnumMonth" : "March", - "memberBool" : true, - "memberFloat32" : 0.1, - "memberFloat64" : -0.2, - "extraMember" : "don't care" - } -}`; -stockSerializedMessages["Test 3"] = "Test 3 stock message sdfsfsdfsdf"; -stockSerializedMessages["Test 4"] = "Test 4 stock message 355345345"; -stockSerializedMessages["Test 5"] = "Test 5 stock message 34535"; -stockSerializedMessages["Test 6"] = "Test 6 stock message xcvcxvx"; -stockSerializedMessages["Test 7"] = "Test 7 stock message fgwqewqdgg"; -stockSerializedMessages["Test 8"] = "Test 8 stock message fgfsdfsdgg"; - -/* -+--------------------------------------------------+ -| define handler | -+--------------------------------------------------+ -*/ - -function setSerializedInputValue(text: string) { - let e : HTMLTextAreaElement = document.getElementById('TestWasm-SerializedInput') as HTMLTextAreaElement; - e.value = text; -} - -function getSerializedInputValue(): string { - let e : HTMLTextAreaElement = document.getElementById('TestWasm-SerializedInput') as HTMLTextAreaElement; - return e.value; -} - -function setCppOutputValue(text: string) { - let e : HTMLTextAreaElement = document.getElementById('TestWasm-CppOutput') as HTMLTextAreaElement; - e.value = text; -} - -function getCppOutputValue(): string { - let e : HTMLTextAreaElement = document.getElementById('TestWasm-CppOutput') as HTMLTextAreaElement; - return e.value; -} - -function SendFreeTextFromCpp(txt: string):string -{ - setCppOutputValue(getCppOutputValue() + "\n" + txt); - return ""; -} -(<any> window).SendFreeTextFromCpp = SendFreeTextFromCpp; - -var referenceMessages = Array<any>(); - -function testTsCppTs() { - var r = new TestStoneCodeGen.Message2(); - r.memberEnumMovieType = TestStoneCodeGen.MovieType.RomCom; - r.memberStringWithDefault = "overriden"; - r.memberMapEnumFloat[TestStoneCodeGen.CrispType.CreamAndChives] = 0.5; - r.memberString = "reference-messsage2-test1"; - - referenceMessages[r.memberString] = r; - var strMsg2 = r.StoneSerialize(); - let SendMessageToCppForEchoLocal = (<any> window).Module.cwrap('SendMessageToCppForEcho', 'string', ['string']); - SendMessageToCppForEchoLocal(strMsg2); -} - -class MyEchoHandler implements TestStoneCodeGen.IHandler -{ - public HandleMessage2(value: TestStoneCodeGen.Message2): boolean - { - if (value.memberString in referenceMessages) { - let r = referenceMessages[value.memberString]; - let equals = (value.memberStringWithDefault == r.memberStringWithDefault); - if (TestStoneCodeGen.CrispType.CreamAndChives in r.memberMapEnumFloat) { - equals == equals && r.memberMapEnumFloat[TestStoneCodeGen.CrispType.CreamAndChives] == value.memberMapEnumFloat[TestStoneCodeGen.CrispType.CreamAndChives]; - } - // TODO continue comparison - - if (equals) { - console.log("objects are equals after round trip"); - return true; - } - } - console.log("problem after round trip"); - return true; - } -} - -function SendMessageFromCpp(txt: string):string -{ - setCppOutputValue(getCppOutputValue() + "\n" + txt); - TestStoneCodeGen.StoneDispatchToHandler(txt, new MyEchoHandler()); - return ""; -} -(<any> window).SendMessageFromCpp = SendMessageFromCpp; - - - -function ButtonClick(buttonName: string) { - if (buttonName.startsWith('Test ')) { - setSerializedInputValue(stockSerializedMessages[buttonName]); - } - else if (buttonName == "Test-ts-cpp-ts") { - testTsCppTs(); - } - else if(buttonName == 'Trigger') - { - let serializedInputValue:string = getSerializedInputValue(); - - let SendMessageToCppLocal = (<any> window).Module.cwrap('SendMessageToCpp', 'string', ['string']); - SendMessageToCppLocal(serializedInputValue); - } - else if(buttonName == 'Clear') - { - setCppOutputValue(""); - } - else if(buttonName == 'ShowSchema') - { - setCppOutputValue(schemaText); - } - else - { - throw new Error("Internal error!"); - } -} - - - -// this method is called "from the C++ code" when the StoneApplication is updated. -// it can be used to update the UI of the application -function UpdateWebApplicationWithString(statusUpdateMessageString: string) { - console.log("updating web application (string): ", statusUpdateMessageString); - let statusUpdateMessage = JSON.parse(statusUpdateMessageString); - - if ("event" in statusUpdateMessage) - { - let eventName = statusUpdateMessage["event"]; - if (eventName == "appStatusUpdated") - { - //ui.onAppStatusUpdated(statusUpdateMessage["data"]); - } - } -} - - -function UpdateWebApplicationWithSerializedMessage(statusUpdateMessageString: string) { - console.log("updating web application (serialized message): ", statusUpdateMessageString); - console.log("<not supported!>"); -} - \ No newline at end of file
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/test_data/test2.yaml Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -enum EnumMonth0: - - January - - February - - Month - -struct Message1: - a: int32 - b: string - c: EnumMonth0 - d: bool - -struct Message2: - toto: string - tata: vector<Message1> - tutu: vector<string> - titi: map<string, string> - lulu: map<string, Message1>
--- a/OrthancStone/Resources/Graveyard/Deprecated/Resources/CodeGeneration/test_data/testTestStoneCodeGen.yaml Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -# -# 1 2 3 4 5 6 7 8 -# 345678901234567890123456789012345678901234567890123456789012345678901234567890 -# -rootName: TestStoneCodeGen - -struct B: - __handler: cpp - - someAs: vector<A> - someInts: vector<int32> - -struct C: - __handler: cpp - - someBs: vector<B> - ddd: vector<string> - -struct A: - __handler: cpp - - someStrings: vector<string> - someInts2: vector<int32> - movies: vector<MovieType> - -struct Message1: - __handler: cpp - - memberInt32: int32 - memberString: string - memberEnumMonth: EnumMonth0 - memberBool: bool - memberFloat32: float32 - memberFloat64: float64 - -struct Message2: - __handler: [cpp, ts] - - memberString: string - memberStringWithDefault: string = "my-default-value" - memberVectorOfMessage1: vector<Message1> - memberVectorOfString: vector<string> - memberMapStringString: map<string, string> - memberMapStringStruct: map<string, Message1> - memberMapEnumFloat: map<CrispType, float32> - memberEnumMovieType: MovieType - memberJson: json - -enum MovieType: - - RomCom - - Horror - - ScienceFiction - - Vegetables - -enum CrispType: - - SaltAndPepper - - CreamAndChives - - Paprika - - Barbecue - -enum EnumMonth0: - - January - - February - - March
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/MultiPlatform/BasicScene/BasicScene.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,275 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#include "BasicScene.h" - -// From Stone -#include "Framework/Scene2D/Scene2D.h" -#include "Framework/Scene2D/ColorTextureSceneLayer.h" -#include "Framework/Scene2D/PolylineSceneLayer.h" -#include "Framework/Scene2D/TextSceneLayer.h" - -#include "Framework/Scene2D/PanSceneTracker.h" -#include "Framework/Scene2D/ZoomSceneTracker.h" -#include "Framework/Scene2D/RotateSceneTracker.h" - -#include "Framework/Scene2D/CairoCompositor.h" - -// From Orthanc framework -#include <Core/Images/Image.h> -#include <Core/Images/ImageProcessing.h> -#include <Core/Images/PngWriter.h> - -using namespace OrthancStone; - -const unsigned int BASIC_SCENE_FONT_SIZE = 32; -const int BASIC_SCENE_LAYER_POSITION = 150; - -void PrepareScene(Scene2D& scene) -{ - //Scene2D& scene(*controller->GetScene()); - // Texture of 2x2 size - { - Orthanc::Image i(Orthanc::PixelFormat_RGB24, 2, 2, false); - - uint8_t *p = reinterpret_cast<uint8_t*>(i.GetRow(0)); - p[0] = 255; - p[1] = 0; - p[2] = 0; - - p[3] = 0; - p[4] = 255; - p[5] = 0; - - p = reinterpret_cast<uint8_t*>(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::unique_ptr<ColorTextureSceneLayer> l(new ColorTextureSceneLayer(i)); - l->SetOrigin(-3, 2); - l->SetPixelSpacing(1.5, 1); - l->SetAngle(20.0 / 180.0 * 3.14); - scene.SetLayer(14, l.release()); - } - - // Texture of 1x1 size - { - Orthanc::Image i(Orthanc::PixelFormat_RGB24, 1, 1, false); - - uint8_t *p = reinterpret_cast<uint8_t*>(i.GetRow(0)); - p[0] = 255; - p[1] = 0; - p[2] = 0; - - std::unique_ptr<ColorTextureSceneLayer> l(new ColorTextureSceneLayer(i)); - l->SetOrigin(-2, 1); - l->SetAngle(20.0 / 180.0 * 3.14); - scene.SetLayer(13, l.release()); - } - - // Some lines - { - std::unique_ptr<PolylineSceneLayer> 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); - - // layer->SetColor(0,255, 255); - scene.SetLayer(50, layer.release()); - } - - // Some text - { - std::unique_ptr<TextSceneLayer> layer(new TextSceneLayer); - layer->SetText("Hello"); - scene.SetLayer(100, layer.release()); - } -} - -#if ORTHANC_SANDBOXED == 0 -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, BASIC_SCENE_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); -} -#endif - -void ShowCursorInfo(Scene2D& scene, const PointerEvent& pointerEvent) -{ - ScenePoint2D p = pointerEvent.GetMainPosition().Apply(scene.GetCanvasToSceneTransform()); - - char buf[64]; - sprintf(buf, "(%0.02f,%0.02f)", p.GetX(), p.GetY()); - - if (scene.HasLayer(BASIC_SCENE_LAYER_POSITION)) - { - TextSceneLayer& layer = - dynamic_cast<TextSceneLayer&>(scene.GetLayer(BASIC_SCENE_LAYER_POSITION)); - layer.SetText(buf); - layer.SetPosition(p.GetX(), p.GetY()); - } - else - { - std::unique_ptr<TextSceneLayer> - 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(BASIC_SCENE_LAYER_POSITION, layer.release()); - } -} - - - -bool BasicScene2DInteractor::OnMouseEvent(const GuiAdapterMouseEvent& event, const PointerEvent& pointerEvent) -{ - if (currentTracker_.get() != NULL) - { - switch (event.type) - { - case GUIADAPTER_EVENT_MOUSEUP: - { - currentTracker_->PointerUp(pointerEvent); - if (!currentTracker_->IsAlive()) - { - currentTracker_.reset(); - } - };break; - case GUIADAPTER_EVENT_MOUSEMOVE: - { - currentTracker_->PointerMove(pointerEvent); - };break; - default: - return false; - } - return true; - } - else if (event.type == GUIADAPTER_EVENT_MOUSEDOWN) - { - if (event.button == GUIADAPTER_MOUSEBUTTON_LEFT) - { - currentTracker_.reset(new RotateSceneTracker(viewportController_, pointerEvent)); - } - else if (event.button == GUIADAPTER_MOUSEBUTTON_MIDDLE) - { - currentTracker_.reset(new PanSceneTracker(viewportController_, pointerEvent)); - } - else if (event.button == GUIADAPTER_MOUSEBUTTON_RIGHT) - { - currentTracker_.reset(new ZoomSceneTracker(viewportController_, pointerEvent, viewportController_->GetViewport().GetCanvasHeight())); - } - } - else if (event.type == GUIADAPTER_EVENT_MOUSEMOVE) - { - if (showCursorInfo_) - { - Scene2D& scene(viewportController_->GetScene()); - ShowCursorInfo(scene, pointerEvent); - } - return true; - } - return false; -} - -bool BasicScene2DInteractor::OnKeyboardEvent(const GuiAdapterKeyboardEvent& guiEvent) -{ - if (guiEvent.type == GUIADAPTER_EVENT_KEYDOWN) - { - switch (guiEvent.sym[0]) - { - case 's': - { - //viewportController_->FitContent(viewportController_->GetViewport().GetCanvasWidth(), viewportController_->GetViewport().GetCanvasHeight()); - viewportController_->FitContent(); - return true; - }; -#if ORTHANC_SANDBOXED == 0 - case 'c': - { - Scene2D& scene(viewportController_->GetScene()); - TakeScreenshot("screenshot.png", scene, viewportController_->GetViewport().GetCanvasWidth(), viewportController_->GetViewport().GetCanvasHeight()); - return true; - } -#endif - case 'd': - { - showCursorInfo_ = !showCursorInfo_; - if (!showCursorInfo_) - { - Scene2D& scene(viewportController_->GetScene()); - scene.DeleteLayer(BASIC_SCENE_LAYER_POSITION); - } - - return true; - } - } - } - return false; -} - -bool BasicScene2DInteractor::OnWheelEvent(const GuiAdapterWheelEvent& guiEvent) -{ - return false; -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/MultiPlatform/BasicScene/BasicScene.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#pragma once - -#include <boost/shared_ptr.hpp> -#include "Framework/Scene2DViewport/ViewportController.h" -#include "Framework/Scene2D/Scene2D.h" - -extern const unsigned int BASIC_SCENE_FONT_SIZE; -extern const int BASIC_SCENE_LAYER_POSITION; - -extern void PrepareScene(OrthancStone::Scene2D& scene); -extern void TakeScreenshot(const std::string& target, - const OrthancStone::Scene2D& scene, - unsigned int canvasWidth, - unsigned int canvasHeight); - - -#include "Applications/Generic/Scene2DInteractor.h" -#include "Framework/Scene2DViewport/IFlexiblePointerTracker.h" - - -class BasicScene2DInteractor : public OrthancStone::Scene2DInteractor -{ - boost::shared_ptr<OrthancStone::IFlexiblePointerTracker> currentTracker_; - bool showCursorInfo_; -public: - BasicScene2DInteractor(boost::shared_ptr<OrthancStone::ViewportController> viewportController) : - Scene2DInteractor(viewportController), - showCursorInfo_(false) - {} - - virtual bool OnMouseEvent(const OrthancStone::GuiAdapterMouseEvent& event, const OrthancStone::PointerEvent& pointerEvent) override; - virtual bool OnKeyboardEvent(const OrthancStone::GuiAdapterKeyboardEvent& guiEvent) override; - virtual bool OnWheelEvent(const OrthancStone::GuiAdapterWheelEvent& guiEvent) override; -}; -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/MultiPlatform/BasicScene/mainQt.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#define GLEW_STATIC 1 -// From Stone -#include "../../Framework/OpenGL/OpenGLIncludes.h" -#include "../../Applications/Sdl/SdlWindow.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/Scene2D.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 <Core/Logging.h> -#include <Core/OrthancException.h> -#include <Core/Images/Image.h> -#include <Core/Images/ImageProcessing.h> -#include <Core/Images/PngWriter.h> - -#include <boost/make_shared.hpp> -#include <boost/ref.hpp> -#include "EmbeddedResources.h" - -#include <stdio.h> -#include <QDebug> -#include <QWindow> - -#include "BasicScene.h" - - -using namespace OrthancStone; - - - -static void GLAPIENTRY OpenGLMessageCallback(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar* message, - const void* userParam ) -{ - if (severity != GL_DEBUG_SEVERITY_NOTIFICATION) - { - fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", - ( type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "" ), - type, severity, message ); - } -} - -extern void InitGL(); - -#include <QApplication> -#include "BasicSceneWindow.h" - -int main(int argc, char* argv[]) -{ - QApplication a(argc, argv); - - OrthancStone::Samples::BasicSceneWindow window; - window.show(); - window.GetOpenGlWidget().Init(); - - MessageBroker broker; - boost::shared_ptr<UndoStack> undoStack(new UndoStack); - boost::shared_ptr<ViewportController> controller = boost::make_shared<ViewportController>(undoStack, boost::ref(broker), window.GetOpenGlWidget()); - PrepareScene(controller->GetScene()); - - window.GetOpenGlWidget().GetCompositor().SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, - BASIC_SCENE_FONT_SIZE, Orthanc::Encoding_Latin1); - - boost::shared_ptr<OrthancStone::Scene2DInteractor> interactor(new BasicScene2DInteractor(controller)); - window.GetOpenGlWidget().SetInteractor(interactor); - - controller->FitContent(); - - return a.exec(); -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/MultiPlatform/BasicScene/mainSdl.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,199 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -// From Stone -#include "Framework/Viewport/SdlViewport.h" -#include "Framework/Scene2D/OpenGLCompositor.h" -#include "Framework/Scene2DViewport/UndoStack.h" -#include "Framework/StoneInitialization.h" -#include "Framework/Messages/MessageBroker.h" - -// From Orthanc framework -#include <Core/Logging.h> -#include <Core/OrthancException.h> - -#include <boost/make_shared.hpp> -#include <boost/ref.hpp> - -#include <SDL.h> -#include <stdio.h> - - -#include "BasicScene.h" - -using namespace OrthancStone; - -boost::shared_ptr<BasicScene2DInteractor> interactor; - -void HandleApplicationEvent(boost::shared_ptr<OrthancStone::ViewportController> controller, - const SDL_Event& event) -{ - using namespace OrthancStone; - Scene2D& scene(controller->GetScene()); - if (event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP || event.type == SDL_MOUSEMOTION) - { - // TODO: this code is copy/pasted from GuiAdapter::Run() -> find the right place - int scancodeCount = 0; - const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount); - bool ctrlPressed(false); - bool shiftPressed(false); - bool altPressed(false); - - 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; - - GuiAdapterMouseEvent guiEvent; - ConvertFromPlatform(guiEvent, ctrlPressed, shiftPressed, altPressed, event); - PointerEvent pointerEvent; - pointerEvent.AddPosition(controller->GetViewport().GetPixelCenterCoordinates(event.button.x, event.button.y)); - - interactor->OnMouseEvent(guiEvent, pointerEvent); - return; - } - else if ((event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) && event.key.repeat == 0 /* Ignore key bounce */) - { - GuiAdapterKeyboardEvent guiEvent; - ConvertFromPlatform(guiEvent, event); - - interactor->OnKeyboardEvent(guiEvent); - } - -} - - -static void GLAPIENTRY -OpenGLMessageCallback(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar* message, - const void* userParam ) -{ - if (severity != GL_DEBUG_SEVERITY_NOTIFICATION) - { - fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", - ( type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "" ), - type, severity, message ); - } -} - - -void Run(boost::shared_ptr<OrthancStone::ViewportController> controller) -{ - SdlViewport& sdlViewport = dynamic_cast<SdlViewport&>(controller->GetViewport()); - - glEnable(GL_DEBUG_OUTPUT); - glDebugMessageCallback(OpenGLMessageCallback, 0); - - controller->GetViewport().GetCompositor().SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, - BASIC_SCENE_FONT_SIZE, Orthanc::Encoding_Latin1); - - controller->GetViewport().Refresh(); - controller->FitContent(); - - - bool stop = false; - while (!stop) - { - controller->GetViewport().Refresh(); - - SDL_Event event; - while (!stop && - SDL_PollEvent(&event)) - { - if (event.type == SDL_QUIT) - { - stop = true; - break; - } - else if (event.type == SDL_WINDOWEVENT && - event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) - { - sdlViewport.UpdateSize(event.window.data1, event.window.data2); - } - else if (event.type == SDL_KEYDOWN && - event.key.repeat == 0 /* Ignore key bounce */) - { - switch (event.key.keysym.sym) - { - case SDLK_f: - sdlViewport.GetWindow().ToggleMaximize(); - break; - - case SDLK_q: - stop = true; - break; - - default: - break; - } - } - - HandleApplicationEvent(controller, event); - } - - SDL_Delay(1); - } - interactor.reset(); -} - - - - -/** - * IMPORTANT: The full arguments to "main()" are needed for SDL on - * Windows. Otherwise, one gets the linking error "undefined reference - * to `SDL_main'". https://wiki.libsdl.org/FAQWindows - **/ -int main(int argc, char* argv[]) -{ - using namespace OrthancStone; - StoneInitialize(); - Orthanc::Logging::EnableInfoLevel(true); - - try - { - SdlOpenGLViewport viewport("Hello", 1024, 768); - MessageBroker broker; - boost::shared_ptr<UndoStack> undoStack(new UndoStack); - boost::shared_ptr<ViewportController> controller = boost::make_shared<ViewportController>(undoStack, boost::ref(broker), boost::ref(viewport)); - interactor.reset(new BasicScene2DInteractor(controller)); - PrepareScene(controller->GetScene()); - Run(controller); - } - catch (Orthanc::OrthancException& e) - { - LOG(ERROR) << "EXCEPTION: " << e.What(); - } - - StoneFinalize(); - - return 0; -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/Qt/BasicSceneWindow.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "../../Framework/OpenGL/OpenGLIncludes.h" -#include "BasicSceneWindow.h" - -/** - * Don't use "ui_MainWindow.h" instead of <ui_MainWindow.h> below, as - * this makes CMake unable to detect when the UI file changes. - **/ -#include <ui_BasicSceneWindow.h> -#include "../../Applications/Samples/SampleApplicationBase.h" - -namespace OrthancStone -{ - namespace Samples - { - - BasicSceneWindow::BasicSceneWindow( - QWidget *parent) : - ui_(new Ui::BasicSceneWindow) - { - ui_->setupUi(this); - } - - BasicSceneWindow::~BasicSceneWindow() - { - delete ui_; - } - - QStoneOpenGlWidget& BasicSceneWindow::GetOpenGlWidget() - { - return *(ui_->centralWidget); - } - - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/Qt/BasicSceneWindow.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once -#include <QMainWindow> -#include <QStoneOpenGlWidget.h> -// #include "../../Qt/QCairoWidget.h" -// #include "../../Qt/QStoneMainWindow.h" - -namespace Ui -{ - class BasicSceneWindow; -} - -namespace OrthancStone -{ - namespace Samples - { - - //class SampleSingleCanvasApplicationBase; - - class BasicSceneWindow : public QMainWindow - { - Q_OBJECT - - private: - Ui::BasicSceneWindow* ui_; - //SampleSingleCanvasApplicationBase& stoneSampleApplication_; - - public: - explicit BasicSceneWindow(QWidget *parent = 0); - ~BasicSceneWindow(); - - QStoneOpenGlWidget& GetOpenGlWidget(); - }; - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/Qt/BasicSceneWindow.ui Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>BasicSceneWindow</class> - <widget class="QMainWindow" name="BasicSceneWindow"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>903</width> - <height>634</height> - </rect> - </property> - <property name="minimumSize"> - <size> - <width>500</width> - <height>300</height> - </size> - </property> - <property name="baseSize"> - <size> - <width>500</width> - <height>300</height> - </size> - </property> - <property name="windowTitle"> - <string>Stone of Orthanc</string> - </property> - <property name="layoutDirection"> - <enum>Qt::LeftToRight</enum> - </property> - <widget class="QWidget" name="mainWidget"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="layoutDirection"> - <enum>Qt::LeftToRight</enum> - </property> - <layout class="QVBoxLayout" name="verticalLayout_2" stretch="0"> - <property name="sizeConstraint"> - <enum>QLayout::SetDefaultConstraint</enum> - </property> - <item> - <widget class="OrthancStone::QStoneOpenGlWidget" name="centralWidget" native="true"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>500</height> - </size> - </property> - </widget> - </item> - </layout> - </widget> - <widget class="QMenuBar" name="menubar"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>903</width> - <height>21</height> - </rect> - </property> - <widget class="QMenu" name="menuTest"> - <property name="title"> - <string>Test</string> - </property> - </widget> - <addaction name="menuTest"/> - </widget> - <widget class="QStatusBar" name="statusbar"/> - </widget> - <customwidgets> - <customwidget> - <class>QStoneOpenGlWidget</class> - <extends>QWidget</extends> - <header location="global">QStoneOpenGlWidget.h</header> - </customwidget> - </customwidgets> - <resources/> - <connections/> -</ui>
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/Qt/CMakeLists.txt Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -cmake_minimum_required(VERSION 2.8.3) - -##################################################################### -## Configuration of the Orthanc framework -##################################################################### - -# This CMake file defines the "ORTHANC_STONE_VERSION" macro, so it -# must be the first inclusion -include(${CMAKE_SOURCE_DIR}/../../Resources/CMake/Version.cmake) - -if (ORTHANC_STONE_VERSION STREQUAL "mainline") - set(ORTHANC_FRAMEWORK_VERSION "mainline") - set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "hg") -else() - set(ORTHANC_FRAMEWORK_VERSION "1.5.7") - set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "web") -endif() - -set(ORTHANC_FRAMEWORK_SOURCE "${ORTHANC_FRAMEWORK_DEFAULT_SOURCE}" CACHE STRING "Source of the Orthanc source code (can be \"hg\", \"archive\", \"web\" or \"path\")") -set(ORTHANC_FRAMEWORK_ARCHIVE "" CACHE STRING "Path to the Orthanc archive, if ORTHANC_FRAMEWORK_SOURCE is \"archive\"") -set(ORTHANC_FRAMEWORK_ROOT "" CACHE STRING "Path to the Orthanc source directory, if ORTHANC_FRAMEWORK_SOURCE is \"path\"") - - -##################################################################### -## Configuration of the Stone framework -##################################################################### - -include(${CMAKE_SOURCE_DIR}/../../Resources/CMake/OrthancStoneParameters.cmake) -include(${ORTHANC_ROOT}/Resources/CMake/DownloadPackage.cmake) - -DownloadPackage( - "a24b8136b8f3bb93f166baf97d9328de" - "http://orthanc.osimis.io/ThirdPartyDownloads/ubuntu-font-family-0.83.zip" - "${CMAKE_BINARY_DIR}/ubuntu-font-family-0.83") - -set(ORTHANC_STONE_APPLICATION_RESOURCES - UBUNTU_FONT ${CMAKE_BINARY_DIR}/ubuntu-font-family-0.83/Ubuntu-R.ttf - ) - -SET(ENABLE_GOOGLE_TEST OFF) -SET(ENABLE_LOCALE ON) -SET(ENABLE_QT ON) -SET(ENABLE_SDL OFF) -SET(ENABLE_WEB_CLIENT ON) -SET(ORTHANC_SANDBOXED OFF) -LIST(APPEND ORTHANC_BOOST_COMPONENTS program_options) - -include(${CMAKE_SOURCE_DIR}/../../Resources/CMake/OrthancStoneConfiguration.cmake) - -add_definitions( - -DORTHANC_ENABLE_LOGGING_PLUGIN=0 - ) -##################################################################### -## Build the samples -##################################################################### - -add_library(OrthancStone STATIC - ${ORTHANC_STONE_SOURCES} - ) - -list(APPEND BASIC_SCENE_APPLICATIONS_SOURCES - BasicSceneWindow.cpp - ) - -ORTHANC_QT_WRAP_UI(BASIC_SCENE_APPLICATIONS_SOURCES - BasicSceneWindow.ui - ) - -ORTHANC_QT_WRAP_CPP(BASIC_SCENE_APPLICATIONS_SOURCES - BasicSceneWindow.h - QStoneOpenGlWidget.h - ) - -add_executable(MpBasicScene - ${CMAKE_CURRENT_LIST_DIR}/../MultiPlatform/BasicScene/BasicScene.h - ${CMAKE_CURRENT_LIST_DIR}/../MultiPlatform/BasicScene/BasicScene.cpp - ${CMAKE_CURRENT_LIST_DIR}/../MultiPlatform/BasicScene/mainQt.cpp - QStoneOpenGlWidget.cpp - ${BASIC_SCENE_APPLICATIONS_SOURCES} - ) - -target_include_directories(MpBasicScene PUBLIC ${CMAKE_SOURCE_DIR} ${ORTHANC_STONE_ROOT}) -target_link_libraries(MpBasicScene OrthancStone)
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/Qt/QStoneOpenGlWidget.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,192 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "../../Framework/OpenGL/OpenGLIncludes.h" -#include "QStoneOpenGlWidget.h" - -#include <QMouseEvent> - -using namespace OrthancStone; - -void QStoneOpenGlWidget::initializeGL() -{ - glewInit(); -} - -void QStoneOpenGlWidget::MakeCurrent() -{ - this->makeCurrent(); -} - -void QStoneOpenGlWidget::resizeGL(int w, int h) -{ - -} - -void QStoneOpenGlWidget::paintGL() -{ - if (compositor_) - { - compositor_->Refresh(); - } - doneCurrent(); -} - -void ConvertFromPlatform( - OrthancStone::GuiAdapterMouseEvent& guiEvent, - PointerEvent& pointerEvent, - const QMouseEvent& qtEvent, - const IViewport& viewport) -{ - guiEvent.targetX = qtEvent.x(); - guiEvent.targetY = qtEvent.y(); - pointerEvent.AddPosition(viewport.GetPixelCenterCoordinates(guiEvent.targetX, guiEvent.targetY)); - - switch (qtEvent.button()) - { - case Qt::LeftButton: guiEvent.button = OrthancStone::GUIADAPTER_MOUSEBUTTON_LEFT; break; - case Qt::MiddleButton: guiEvent.button = OrthancStone::GUIADAPTER_MOUSEBUTTON_MIDDLE; break; - case Qt::RightButton: guiEvent.button = OrthancStone::GUIADAPTER_MOUSEBUTTON_RIGHT; break; - default: - guiEvent.button = OrthancStone::GUIADAPTER_MOUSEBUTTON_LEFT; - } - - if (qtEvent.modifiers().testFlag(Qt::ShiftModifier)) - { - guiEvent.shiftKey = true; - } - if (qtEvent.modifiers().testFlag(Qt::ControlModifier)) - { - guiEvent.ctrlKey = true; - } - if (qtEvent.modifiers().testFlag(Qt::AltModifier)) - { - guiEvent.altKey = true; - } -} - -void QStoneOpenGlWidget::mouseEvent(QMouseEvent* qtEvent, OrthancStone::GuiAdapterHidEventType guiEventType) -{ - OrthancStone::GuiAdapterMouseEvent guiEvent; - PointerEvent pointerEvent; - ConvertFromPlatform(guiEvent, pointerEvent, *qtEvent, *this); - guiEvent.type = guiEventType; - - if (sceneInteractor_.get() != NULL && compositor_.get() != NULL) - { - sceneInteractor_->OnMouseEvent(guiEvent, pointerEvent); - } - - // force redraw of the OpenGL widget - update(); -} - -void QStoneOpenGlWidget::mousePressEvent(QMouseEvent* qtEvent) -{ - mouseEvent(qtEvent, GUIADAPTER_EVENT_MOUSEDOWN); -} - -void QStoneOpenGlWidget::mouseMoveEvent(QMouseEvent* qtEvent) -{ - mouseEvent(qtEvent, GUIADAPTER_EVENT_MOUSEMOVE); -} - -void QStoneOpenGlWidget::mouseReleaseEvent(QMouseEvent* qtEvent) -{ - mouseEvent(qtEvent, GUIADAPTER_EVENT_MOUSEUP); -} - -void ConvertFromPlatform( - OrthancStone::GuiAdapterKeyboardEvent& guiEvent, - const QKeyEvent& qtEvent) -{ - if (qtEvent.text().length() > 0) - { - guiEvent.sym[0] = qtEvent.text()[0].cell(); - } - else - { - guiEvent.sym[0] = 0; - } - guiEvent.sym[1] = 0; - - if (qtEvent.modifiers().testFlag(Qt::ShiftModifier)) - { - guiEvent.shiftKey = true; - } - if (qtEvent.modifiers().testFlag(Qt::ControlModifier)) - { - guiEvent.ctrlKey = true; - } - if (qtEvent.modifiers().testFlag(Qt::AltModifier)) - { - guiEvent.altKey = true; - } - -} - - -bool QStoneOpenGlWidget::keyEvent(QKeyEvent* qtEvent, OrthancStone::GuiAdapterHidEventType guiEventType) -{ - bool handled = false; - OrthancStone::GuiAdapterKeyboardEvent guiEvent; - ConvertFromPlatform(guiEvent, *qtEvent); - guiEvent.type = guiEventType; - - if (sceneInteractor_.get() != NULL && compositor_.get() != NULL) - { - handled = sceneInteractor_->OnKeyboardEvent(guiEvent); - - if (handled) - { - // force redraw of the OpenGL widget - update(); - } - } - return handled; -} - -void QStoneOpenGlWidget::keyPressEvent(QKeyEvent *qtEvent) -{ - bool handled = keyEvent(qtEvent, GUIADAPTER_EVENT_KEYDOWN); - if (!handled) - { - QOpenGLWidget::keyPressEvent(qtEvent); - } -} - -void QStoneOpenGlWidget::keyReleaseEvent(QKeyEvent *qtEvent) -{ - bool handled = keyEvent(qtEvent, GUIADAPTER_EVENT_KEYUP); - if (!handled) - { - QOpenGLWidget::keyPressEvent(qtEvent); - } -} - -void QStoneOpenGlWidget::wheelEvent(QWheelEvent *qtEvent) -{ - OrthancStone::GuiAdapterWheelEvent guiEvent; - throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); - - // force redraw of the OpenGL widget - update(); -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/Qt/QStoneOpenGlWidget.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once -#include "../../Framework/OpenGL/OpenGLIncludes.h" -#include <QOpenGLWidget> -#include <QOpenGLFunctions> -#include <QOpenGLContext> - -#include <boost/shared_ptr.hpp> -#include "../../Framework/OpenGL/IOpenGLContext.h" -#include "../../Framework/Scene2D/OpenGLCompositor.h" -#include "../../Framework/Viewport/ViewportBase.h" -#include "../../Applications/Generic/Scene2DInteractor.h" - -namespace OrthancStone -{ - class QStoneOpenGlWidget : - public QOpenGLWidget, - public OpenGL::IOpenGLContext, - public ViewportBase - { - std::unique_ptr<OrthancStone::OpenGLCompositor> compositor_; - boost::shared_ptr<Scene2DInteractor> sceneInteractor_; - QOpenGLContext openGlContext_; - - public: - QStoneOpenGlWidget(QWidget *parent) : - QOpenGLWidget(parent), - ViewportBase("QtStoneOpenGlWidget") // TODO: we shall be able to define a name but construction time is too early ! - { - setFocusPolicy(Qt::StrongFocus); // to enable keyPressEvent - setMouseTracking(true); // to enable mouseMoveEvent event when no button is pressed - } - - void Init() - { - QSurfaceFormat requestedFormat; - requestedFormat.setVersion( 2, 0 ); - openGlContext_.setFormat( requestedFormat ); - openGlContext_.create(); - openGlContext_.makeCurrent(context()->surface()); - - compositor_.reset(new OpenGLCompositor(*this, GetScene())); - } - - protected: - - //**** QWidget overrides - void initializeGL() override; - void resizeGL(int w, int h) override; - void paintGL() override; - - void mousePressEvent(QMouseEvent* event) override; - void mouseMoveEvent(QMouseEvent* event) override; - void mouseReleaseEvent(QMouseEvent* event) override; - void keyPressEvent(QKeyEvent* event) override; - void keyReleaseEvent(QKeyEvent *event) override; - void wheelEvent(QWheelEvent* event) override; - - //**** IOpenGLContext overrides - - virtual void MakeCurrent() override; - virtual void SwapBuffer() override {} - - virtual unsigned int GetCanvasWidth() const override - { - return this->width(); - } - - virtual unsigned int GetCanvasHeight() const override - { - return this->height(); - } - - public: - - void SetInteractor(boost::shared_ptr<Scene2DInteractor> sceneInteractor) - { - sceneInteractor_ = sceneInteractor; - } - - virtual ICompositor& GetCompositor() - { - return *compositor_; - } - - protected: - void mouseEvent(QMouseEvent* qtEvent, OrthancStone::GuiAdapterHidEventType guiEventType); - bool keyEvent(QKeyEvent* qtEvent, OrthancStone::GuiAdapterHidEventType guiEventType); - - }; -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/Qt/Scene2DInteractor.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "Scene2DInteractor.h" - -#include "../../Framework/Scene2D/PanSceneTracker.h" -#include "../../Framework/Scene2D/ZoomSceneTracker.h" -#include "../../Framework/Scene2D/RotateSceneTracker.h" - - -namespace OrthancStone -{ - -} - -using namespace OrthancStone; - - -bool BasicScene2DInteractor::OnMouseEvent(const GuiAdapterMouseEvent& event, const PointerEvent& pointerEvent) -{ - if (currentTracker_.get() != NULL) - { - switch (event.type) - { - case GUIADAPTER_EVENT_MOUSEUP: - { - currentTracker_->PointerUp(pointerEvent); - if (!currentTracker_->IsAlive()) - { - currentTracker_.reset(); - } - };break; - case GUIADAPTER_EVENT_MOUSEMOVE: - { - currentTracker_->PointerMove(pointerEvent); - };break; - } - return true; - } - else - { - if (event.button == GUIADAPTER_MOUSEBUTTON_LEFT) - { - currentTracker_.reset(new RotateSceneTracker(viewportController_, pointerEvent)); - } - else if (event.button == GUIADAPTER_MOUSEBUTTON_MIDDLE) - { - currentTracker_.reset(new PanSceneTracker(viewportController_, pointerEvent)); - } - else if (event.button == GUIADAPTER_MOUSEBUTTON_RIGHT && compositor_.get() != NULL) - { - currentTracker_.reset(new ZoomSceneTracker(viewportController_, pointerEvent, compositor_->GetHeight())); - } - return true; - } - return false; -} - -bool BasicScene2DInteractor::OnKeyboardEvent(const GuiAdapterKeyboardEvent& guiEvent) -{ - switch (guiEvent.sym[0]) - { - case 's': - { - viewportController_->FitContent(compositor_->GetWidth(), compositor_->GetHeight()); - return true; - }; - } - return false; -} - -bool BasicScene2DInteractor::OnWheelEvent(const GuiAdapterWheelEvent& guiEvent) -{ - return false; -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/Qt/Scene2DInteractor.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../Applications/Generic/Scene2DInteractor.h" -#include "../../Framework/Scene2DViewport/IFlexiblePointerTracker.h" - - -class BasicScene2DInteractor : public OrthancStone::Scene2DInteractor -{ - boost::shared_ptr<OrthancStone::IFlexiblePointerTracker> currentTracker_; -public: - BasicScene2DInteractor(boost::shared_ptr<OrthancStone::ViewportController> viewportController) : - Scene2DInteractor(viewportController) - {} - - virtual bool OnMouseEvent(const OrthancStone::GuiAdapterMouseEvent& event, const OrthancStone::PointerEvent& pointerEvent) override; - virtual bool OnKeyboardEvent(const OrthancStone::GuiAdapterKeyboardEvent& guiEvent); - virtual bool OnWheelEvent(const OrthancStone::GuiAdapterWheelEvent& guiEvent); -}; -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/README.md Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,195 +0,0 @@ - -**These samples are deprecated and not guaranteed to work. A migration to a -new version of the Stone API is underway.** - -Please read orthanc-stone/OrthancStone/Samples/README.md first for general requirements. - - - -Deprecated -- to be sorted -=========================== - -The following assumes that the source code to be downloaded in -`~/orthanc-stone` and Orthanc source code to be checked out in -`~/orthanc`. - -Building the WASM samples -------------------------------------- - -``` -cd ~/orthanc-stone/Applications/Samples -./build-wasm.sh -``` - -Serving the WASM samples ------------------------------------- -``` -# launch an Orthanc listening on 8042 port: -Orthanc - -# launch an nginx that will serve the WASM static files and reverse -# proxy -sudo nginx -p $(pwd) -c nginx.local.conf -``` - -You can now open the samples in http://localhost:9977 - -Building the SDL native samples (SimpleViewer only) ---------------------------------------------------- - -The following also assumes that you have checked out the Orthanc -source code in an `orthanc` folder next to the Stone of Orthanc -repository, please enter the following: - -**Simple make generator with dynamic build** - -``` -# Please set $currentDir to the current folder -mkdir -p ~/builds/orthanc-stone-build -cd ~/builds/orthanc-stone-build -cmake -DORTHANC_FRAMEWORK_SOURCE=path \ - -DORTHANC_FRAMEWORK_ROOT=$currentDir/../../../orthanc \ - -DALLOW_DOWNLOADS=ON -DENABLE_SDL=ON \ - ~/orthanc-stone/Applications/Samples/ -``` - -**Ninja generator with static SDL build (pwsh script)** - -``` -# Please yourself one level above the orthanc-stone and orthanc folders -if( -not (test-path stone_build_sdl)) { mkdir stone_build_sdl } -cd stone_build_sdl -cmake -G Ninja -DSTATIC_BUILD=ON -DOPENSSL_NO_CAPIENG=ON -DORTHANC_FRAMEWORK_SOURCE=path -DORTHANC_FRAMEWORK_ROOT="$($pwd)\..\orthanc" -DALLOW_DOWNLOADS=ON -DENABLE_SDL=ON ../orthanc-stone/Applications/Samples/ -``` - -**Ninja generator with static SDL build (bash/zsh script)** - -``` -# Please yourself one level above the orthanc-stone and orthanc folders -if( -not (test-path stone_build_sdl)) { mkdir stone_build_sdl } -cd stone_build_sdl -cmake -G Ninja -DSTATIC_BUILD=ON -DOPENSSL_NO_CAPIENG=ON -DORTHANC_FRAMEWORK_SOURCE=path -DORTHANC_FRAMEWORK_ROOT="`pwd`/../orthanc" -DALLOW_DOWNLOADS=ON -DENABLE_SDL=ON ../orthanc-stone/Applications/Samples/ -``` - -**Visual Studio 2017 generator with static SDL build (pwsh script)** - -``` -# The following will use Visual Studio 2017 to build the SDL samples -# in debug mode (with multiple compilers in parallel). NOTE: place -# yourself one level above the `orthanc-stone` and `orthanc` folders - -if( -not (test-path stone_build_sdl)) { mkdir stone_build_sdl } -cd stone_build_sdl -cmake -G "Visual Studio 15 2017 Win64" -DMSVC_MULTIPLE_PROCESSES=ON -DSTATIC_BUILD=ON -DOPENSSL_NO_CAPIENG=ON -DORTHANC_FRAMEWORK_SOURCE=path -DORTHANC_FRAMEWORK_ROOT="$($pwd)\..\orthanc" -DALLOW_DOWNLOADS=ON -DENABLE_SDL=ON ../orthanc-stone/Applications/Samples/ -cmake --build . --config Debug -``` - -If you are working on Windows, add the correct generator option to -cmake to, for instance, generate msbuild files for Visual Studio. - -Then, under Linux: -``` -cmake --build . --target OrthancStoneSimpleViewer -- -j 5 -``` - -Note: replace `$($pwd)` with the current directory when not using Powershell - -Building the Qt native samples (SimpleViewer only) under Windows: ------------------------------------------------------------------- - -**Visual Studio 2017 generator with static Qt build (pwsh script)** - -For instance, if Qt is installed in `C:\Qt\5.12.0\msvc2017_64` - -``` -# The following will use Visual Studio 2017 to build the SDL samples -# in debug mode (with multiple compilers in parallel). NOTE: place -# yourself one level above the `orthanc-stone` and `orthanc` folders - -if( -not (test-path stone_build_qt)) { mkdir stone_build_qt } -cd stone_build_qt -cmake -G "Visual Studio 15 2017 Win64" -DMSVC_MULTIPLE_PROCESSES=ON -DSTATIC_BUILD=ON -DOPENSSL_NO_CAPIENG=ON -DCMAKE_PREFIX_PATH=C:\Qt\5.12.0\msvc2017_64 -DORTHANC_FRAMEWORK_SOURCE=path -DORTHANC_FRAMEWORK_ROOT="$($pwd)\..\orthanc" -DALLOW_DOWNLOADS=ON -DENABLE_QT=ON ../orthanc-stone/Applications/Samples/ -cmake --build . --config Debug -``` - -Note: replace `$($pwd)` with the current directory when not using Powershell - - - - - - -Building the SDL native samples (SimpleViewer only) under Windows: ------------------------------------------------------------------- -`cmake -DSTATIC_BUILD=ON -DORTHANC_FRAMEWORK_SOURCE=path -DORTHANC_FRAMEWORK_ROOT="$($pwd)\..\orthanc" -DALLOW_DOWNLOADS=ON -DENABLE_SDL=ON -G "Visual Studio 15 2017 Win64" ../orthanc-stone/Applications/Samples/` - -Note: replace `$($pwd)` with the current directory when not using Powershell - -Executing the native samples: --------------------------------- -``` -# launch an Orthanc listening on 8042 port: -Orthanc - -# launch the sample -./OrthancStoneSimpleViewer --studyId=XX -``` - -Build the Application Samples ------------------------------ - -**Visual Studio 2008 (v90) ** - -``` -cmake -G "Visual Studio 9 2008" -DUSE_LEGACY_JSONCPP=ON -DENABLE_OPENGL=ON -DSTATIC_BUILD=ON -DOPENSSL_NO_CAPIENG=ON -DORTHANC_FRAMEWORK_SOURCE=path -DORTHANC_FRAMEWORK_ROOT="$($pwd)\..\orthanc" -DALLOW_DOWNLOADS=ON -DENABLE_SDL=ON ../orthanc-stone/Applications/Samples -``` - -**Visual Studio 2019 (v142) ** - -``` -cmake -G "Visual Studio 16 2019" -A x64 -DMSVC_MULTIPLE_PROCESSES=ON -DENABLE_OPENGL=ON -DSTATIC_BUILD=ON -DOPENSSL_NO_CAPIENG=ON -DORTHANC_FRAMEWORK_SOURCE=path -DORTHANC_FRAMEWORK_ROOT="$($pwd)\..\orthanc" -DALLOW_DOWNLOADS=ON -DENABLE_SDL=ON ../orthanc-stone/Applications/Samples -``` - -**Visual Studio 2017 (v140) ** - -``` -cmake -G "Visual Studio 15 2017 Win64" -DMSVC_MULTIPLE_PROCESSES=ON -DENABLE_OPENGL=ON -DSTATIC_BUILD=ON -DOPENSSL_NO_CAPIENG=ON -DORTHANC_FRAMEWORK_SOURCE=path -DORTHANC_FRAMEWORK_ROOT="$($pwd)\..\orthanc" -DALLOW_DOWNLOADS=ON -DENABLE_SDL=ON ../orthanc-stone/Applications/Samples -``` - - -Build the core Samples ---------------------------- -How to build the newest (2019-04-29) SDL samples under Windows, *inside* a -folder that is sibling to the orthanc-stone folder: - -**Visual Studio 2019 (v142) ** - -``` -cmake -G "Visual Studio 16 2019" -A x64 -DMSVC_MULTIPLE_PROCESSES=ON -DENABLE_OPENGL=ON -DSTATIC_BUILD=ON -DOPENSSL_NO_CAPIENG=ON -DORTHANC_FRAMEWORK_SOURCE=path -DORTHANC_FRAMEWORK_ROOT="$($pwd)\..\orthanc" -DALLOW_DOWNLOADS=ON -DENABLE_SDL=ON ../orthanc-stone/OrthancStone/Samples/Sdl -``` - -**Visual Studio 2017 (v140) ** - -``` -cmake -G "Visual Studio 15 2017 Win64" -DMSVC_MULTIPLE_PROCESSES=ON -DENABLE_OPENGL=ON -DSTATIC_BUILD=ON -DOPENSSL_NO_CAPIENG=ON -DORTHANC_FRAMEWORK_SOURCE=path -DORTHANC_FRAMEWORK_ROOT="$($pwd)\..\orthanc" -DALLOW_DOWNLOADS=ON -DENABLE_SDL=ON ../orthanc-stone/OrthancStone/Samples/Sdl -``` - -**Visual Studio 2008 (v90) ** - -``` -cmake -G "Visual Studio 9 2008" -DUSE_LEGACY_JSONCPP=ON -DENABLE_OPENGL=ON -DSTATIC_BUILD=ON -DOPENSSL_NO_CAPIENG=ON -DORTHANC_FRAMEWORK_SOURCE=path -DORTHANC_FRAMEWORK_ROOT="$($pwd)\..\orthanc" -DALLOW_DOWNLOADS=ON -DENABLE_SDL=ON ../orthanc-stone/OrthancStone/Samples/Sdl -``` - -And under Ubuntu (note the /mnt/c/osi/dev/orthanc folder): -``` -cmake -G "Ninja" -DENABLE_OPENGL=ON -DSTATIC_BUILD=OFF -DOPENSSL_NO_CAPIENG=ON -DORTHANC_FRAMEWORK_SOURCE=path -DORTHANC_FRAMEWORK_ROOT="/mnt/c/osi/dev/orthanc" -DALLOW_DOWNLOADS=ON -DENABLE_SDL=ON ../orthanc-stone/OrthancStone/Samples/Sdl -``` - -TODO trackers: -- CANCELLED (using outlined text now) text overlay 50% --> ColorTextureLayer 50% -- DONE angle tracker: draw arcs -- Handles on arc -- Select measure tool with hit test --> Delete command - - -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/Sdl/BasicScene.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,418 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -// From Stone -#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 <Core/Logging.h> -#include <Core/OrthancException.h> -#include <Core/Images/Image.h> -#include <Core/Images/ImageProcessing.h> -#include <Core/Images/PngWriter.h> - -#include <boost/make_shared.hpp> - -#include <SDL.h> -#include <stdio.h> - -static const unsigned int FONT_SIZE = 32; -static const int LAYER_POSITION = 150; - -#define OPENGL_ENABLED 0 - -void PrepareScene(OrthancStone::Scene2D& scene) -{ - using namespace OrthancStone; - - // Texture of 2x2 size - { - Orthanc::Image i(Orthanc::PixelFormat_RGB24, 2, 2, false); - - uint8_t *p = reinterpret_cast<uint8_t*>(i.GetRow(0)); - p[0] = 255; - p[1] = 0; - p[2] = 0; - - p[3] = 0; - p[4] = 255; - p[5] = 0; - - p = reinterpret_cast<uint8_t*>(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::unique_ptr<ColorTextureSceneLayer> 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<uint8_t*>(i.GetRow(0)); - p[0] = 255; - p[1] = 0; - p[2] = 0; - - std::unique_ptr<ColorTextureSceneLayer> l(new ColorTextureSceneLayer(i)); - l->SetOrigin(-2, 1); - l->SetAngle(20.0 / 180.0 * M_PI); - scene.SetLayer(13, l.release()); - } - - // Some lines - { - std::unique_ptr<PolylineSceneLayer> 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::unique_ptr<TextSceneLayer> 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<OrthancStone::ViewportController>& controller, - boost::shared_ptr<OrthancStone::IFlexiblePointerTracker>& 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); - - if (activeTracker.get() == NULL && - SDL_SCANCODE_LCTRL < scancodeCount && - keyboardState[SDL_SCANCODE_LCTRL]) - { - // The "left-ctrl" key is down, while no tracker is present - - 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()); - - if (scene.HasLayer(LAYER_POSITION)) - { - TextSceneLayer& layer = - dynamic_cast<TextSceneLayer&>(scene.GetLayer(LAYER_POSITION)); - layer.SetText(buf); - layer.SetPosition(p.GetX(), p.GetY()); - } - else - { - std::unique_ptr<TextSceneLayer> - 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_MOUSEBUTTONDOWN) - { - PointerEvent e; - e.AddPosition(viewport.GetPixelCenterCoordinates(event.button.x, event.button.y)); - - switch (event.button.button) - { - case SDL_BUTTON_MIDDLE: - activeTracker = boost::make_shared<PanSceneTracker>(controller, e); - break; - - case SDL_BUTTON_RIGHT: - activeTracker = boost::make_shared<ZoomSceneTracker> - (controller, e, viewport.GetCanvasHeight()); - break; - - case SDL_BUTTON_LEFT: - activeTracker = boost::make_shared<RotateSceneTracker>(controller, e); - break; - - 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; - } - } -} - -#if OPENGL_ENABLED==1 -static void GLAPIENTRY -OpenGLMessageCallback(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar* message, - const void* userParam ) -{ - if (severity != GL_DEBUG_SEVERITY_NOTIFICATION) - { - fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", - ( type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "" ), - type, severity, message ); - } -} -#endif - -void Run(OrthancStone::MessageBroker& broker, - OrthancStone::SdlViewport& viewport) -{ - using namespace OrthancStone; - - boost::shared_ptr<ViewportController> controller( - new ViewportController(boost::make_shared<UndoStack>(), broker, viewport)); - -#if OPENGL_ENABLED==1 - glEnable(GL_DEBUG_OUTPUT); - glDebugMessageCallback(OpenGLMessageCallback, 0); -#endif - - boost::shared_ptr<IFlexiblePointerTracker> tracker; - - bool firstShown = true; - bool stop = false; - while (!stop) - { - viewport.Refresh(); - - SDL_Event event; - while (!stop && - SDL_PollEvent(&event)) - { - if (event.type == SDL_QUIT) - { - stop = true; - break; - } - 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) - { - 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(); - viewport.UpdateSize(event.window.data1, event.window.data2); - 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 */) - { - switch (event.key.keysym.sym) - { - case SDLK_f: - viewport.GetWindow().ToggleMaximize(); - break; - - case SDLK_q: - stop = true; - break; - - default: - break; - } - } - - HandleApplicationEvent(event, controller, tracker); - } - - SDL_Delay(1); - } -} - - - - -/** - * IMPORTANT: The full arguments to "main()" are needed for SDL on - * Windows. Otherwise, one gets the linking error "undefined reference - * to `SDL_main'". https://wiki.libsdl.org/FAQWindows - **/ -int main(int argc, char* argv[]) -{ - OrthancStone::StoneInitialize(); - Orthanc::Logging::EnableInfoLevel(true); - - try - { -#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, - FONT_SIZE, Orthanc::Encoding_Latin1); - - OrthancStone::MessageBroker broker; - Run(broker, viewport); - } - catch (Orthanc::OrthancException& e) - { - LOG(ERROR) << "EXCEPTION: " << e.What(); - } - - OrthancStone::StoneFinalize(); - - return 0; -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/Sdl/CMakeLists.txt Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,129 +0,0 @@ -cmake_minimum_required(VERSION 2.8.3) - -##################################################################### -## Configuration of the Orthanc framework -##################################################################### - -# This CMake file defines the "ORTHANC_STONE_VERSION" macro, so it -# must be the first inclusion -include(${CMAKE_SOURCE_DIR}/../../Resources/CMake/Version.cmake) - -if (ORTHANC_STONE_VERSION STREQUAL "mainline") - set(ORTHANC_FRAMEWORK_VERSION "mainline") - set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "hg") -else() - set(ORTHANC_FRAMEWORK_VERSION "1.5.7") - set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "web") -endif() - -set(ORTHANC_FRAMEWORK_SOURCE "${ORTHANC_FRAMEWORK_DEFAULT_SOURCE}" CACHE STRING "Source of the Orthanc source code (can be \"hg\", \"archive\", \"web\" or \"path\")") -set(ORTHANC_FRAMEWORK_ARCHIVE "" CACHE STRING "Path to the Orthanc archive, if ORTHANC_FRAMEWORK_SOURCE is \"archive\"") -set(ORTHANC_FRAMEWORK_ROOT "" CACHE STRING "Path to the Orthanc source directory, if ORTHANC_FRAMEWORK_SOURCE is \"path\"") - - -##################################################################### -## Configuration of the Stone framework -##################################################################### - -include(${CMAKE_SOURCE_DIR}/../../Resources/CMake/OrthancStoneParameters.cmake) -include(${ORTHANC_ROOT}/Resources/CMake/DownloadPackage.cmake) - -DownloadPackage( - "a24b8136b8f3bb93f166baf97d9328de" - "http://orthanc.osimis.io/ThirdPartyDownloads/ubuntu-font-family-0.83.zip" - "${CMAKE_BINARY_DIR}/ubuntu-font-family-0.83") - -set(ORTHANC_STONE_APPLICATION_RESOURCES - UBUNTU_FONT ${CMAKE_BINARY_DIR}/ubuntu-font-family-0.83/Ubuntu-R.ttf - ) - -SET(ENABLE_SDL_CONSOLE OFF CACHE BOOL "Enable the use of the MIT-licensed SDL_Console") -SET(ENABLE_GOOGLE_TEST OFF) -SET(ENABLE_LOCALE ON) -SET(ENABLE_SDL ON) -SET(ENABLE_WEB_CLIENT ON) -SET(ORTHANC_SANDBOXED OFF) -LIST(APPEND ORTHANC_BOOST_COMPONENTS program_options) - -include(${CMAKE_SOURCE_DIR}/../../Resources/CMake/OrthancStoneConfiguration.cmake) - -add_definitions( - -DORTHANC_ENABLE_LOGGING_PLUGIN=0 - ) - - -##################################################################### -## Build the samples -##################################################################### - -add_library(OrthancStone STATIC - ${ORTHANC_STONE_SOURCES} - ) - -# -# BasicScene -# - -add_executable(BasicScene - BasicScene.cpp - ) - -target_link_libraries(BasicScene OrthancStone) - -# -# TrackerSample -# - -LIST(APPEND TRACKERSAMPLE_SOURCE "TrackerSample.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "TrackerSampleApp.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "TrackerSampleApp.h") - -if (MSVC AND MSVC_VERSION GREATER 1700) - LIST(APPEND TRACKERSAMPLE_SOURCE "cpp.hint") -endif() - -add_executable(TrackerSample - ${TRACKERSAMPLE_SOURCE} - ) - -target_link_libraries(TrackerSample OrthancStone) - -# -# Loader -# - -add_executable(Loader - Loader.cpp - ) - -target_link_libraries(Loader OrthancStone) - -# -# FusionMprSdl -# - -add_executable(FusionMprSdl - FusionMprSdl.cpp - FusionMprSdl.h -) - -target_link_libraries(FusionMprSdl OrthancStone) - -# -# Multiplatform Basic Scene -# - -LIST(APPEND MP_BASIC_SCENE_SOURCE "../MultiPlatform/BasicScene/BasicScene.cpp") -LIST(APPEND MP_BASIC_SCENE_SOURCE "../MultiPlatform/BasicScene/BasicScene.h") -LIST(APPEND MP_BASIC_SCENE_SOURCE "../MultiPlatform/BasicScene/mainSdl.cpp") - -if (MSVC AND MSVC_VERSION GREATER 1700) - LIST(APPEND MP_BASIC_SCENE_SOURCE "cpp.hint") -endif() - -add_executable(MpBasicScene - ${MP_BASIC_SCENE_SOURCE} - ) - -target_include_directories(MpBasicScene PUBLIC ${ORTHANC_STONE_ROOT}) -target_link_libraries(MpBasicScene OrthancStone)
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/Sdl/FusionMprSdl.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,805 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#include "FusionMprSdl.h" - -#include "../../Framework/OpenGL/SdlOpenGLContext.h" - -#include "../../Framework/StoneInitialization.h" - -#include "../../Framework/Scene2D/CairoCompositor.h" -#include "../../Framework/Scene2D/ColorTextureSceneLayer.h" -#include "../../Framework/Scene2D/OpenGLCompositor.h" -#include "../../Framework/Scene2D/PanSceneTracker.h" -#include "../../Framework/Scene2D/ZoomSceneTracker.h" -#include "../../Framework/Scene2D/RotateSceneTracker.h" - -#include "../../Framework/Scene2DViewport/UndoStack.h" -#include "../../Framework/Scene2DViewport/CreateLineMeasureTracker.h" -#include "../../Framework/Scene2DViewport/CreateAngleMeasureTracker.h" -#include "../../Framework/Scene2DViewport/IFlexiblePointerTracker.h" -#include "../../Framework/Scene2DViewport/MeasureTool.h" -#include "../../Framework/Scene2DViewport/PredeclaredTypes.h" - -#include "../../Framework/Volumes/VolumeSceneLayerSource.h" - -#include <Core/Images/Image.h> -#include <Core/Images/ImageProcessing.h> -#include <Core/Images/PngWriter.h> -#include <Core/Logging.h> -#include <Core/OrthancException.h> - -#include <boost/shared_ptr.hpp> -#include <boost/weak_ptr.hpp> -#include <boost/make_shared.hpp> - -#include <stdio.h> -#include "../../Framework/Oracle/GetOrthancWebViewerJpegCommand.h" -#include "../../Framework/Oracle/ThreadedOracle.h" -#include "../../Framework/Loaders/OrthancSeriesVolumeProgressiveLoader.h" -#include "../../Framework/Loaders/OrthancMultiframeVolumeLoader.h" -#include "../../Framework/Loaders/DicomStructureSetLoader.h" -#include "../../Framework/Scene2D/GrayscaleStyleConfigurator.h" -#include "../../Framework/Scene2D/LookupTableStyleConfigurator.h" -#include "../../Framework/Volumes/DicomVolumeImageMPRSlicer.h" -#include "Core/SystemToolbox.h" - -namespace OrthancStone -{ - const char* FusionMprMeasureToolToString(size_t i) - { - static const char* descs[] = { - "FusionMprGuiTool_Rotate", - "FusionMprGuiTool_Pan", - "FusionMprGuiTool_Zoom", - "FusionMprGuiTool_LineMeasure", - "FusionMprGuiTool_CircleMeasure", - "FusionMprGuiTool_AngleMeasure", - "FusionMprGuiTool_EllipseMeasure", - "FusionMprGuiTool_LAST" - }; - if (i >= FusionMprGuiTool_LAST) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, "Wrong tool index"); - } - return descs[i]; - } - - Scene2D& FusionMprSdlApp::GetScene() - { - return controller_->GetScene(); - } - - const Scene2D& FusionMprSdlApp::GetScene() const - { - return controller_->GetScene(); - } - - void FusionMprSdlApp::SelectNextTool() - { - currentTool_ = static_cast<FusionMprGuiTool>(currentTool_ + 1); - if (currentTool_ == FusionMprGuiTool_LAST) - currentTool_ = static_cast<FusionMprGuiTool>(0);; - printf("Current tool is now: %s\n", FusionMprMeasureToolToString(currentTool_)); - } - - void FusionMprSdlApp::DisplayInfoText() - { - // do not try to use stuff too early! - ICompositor* pCompositor = &(viewport_.GetCompositor()); - if (pCompositor == NULL) - return; - - std::stringstream msg; - - for (std::map<std::string, std::string>::const_iterator kv = infoTextMap_.begin(); - kv != infoTextMap_.end(); ++kv) - { - msg << kv->first << " : " << kv->second << std::endl; - } - std::string msgS = msg.str(); - - TextSceneLayer* layerP = NULL; - if (GetScene().HasLayer(FIXED_INFOTEXT_LAYER_ZINDEX)) - { - TextSceneLayer& layer = dynamic_cast<TextSceneLayer&>( - GetScene().GetLayer(FIXED_INFOTEXT_LAYER_ZINDEX)); - layerP = &layer; - } - else - { - std::unique_ptr<TextSceneLayer> layer(new TextSceneLayer); - layerP = layer.get(); - layer->SetColor(0, 255, 0); - layer->SetFontIndex(1); - layer->SetBorder(20); - layer->SetAnchor(BitmapAnchor_TopLeft); - //layer->SetPosition(0,0); - 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 = viewport_.GetCompositor().GetCanvasWidth() * (-0.5); - double cY = viewport_.GetCompositor().GetCanvasHeight() * (-0.5); - GetScene().GetCanvasToSceneTransform().Apply(cX,cY); - layerP->SetPosition(cX, cY); - } - - void FusionMprSdlApp::DisplayFloatingCtrlInfoText(const PointerEvent& e) - { - ScenePoint2D p = e.GetMainPosition().Apply(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)) - { - TextSceneLayer& layer = - dynamic_cast<TextSceneLayer&>(GetScene().GetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)); - layer.SetText(buf); - layer.SetPosition(p.GetX(), p.GetY()); - } - else - { - std::unique_ptr<TextSceneLayer> layer(new TextSceneLayer); - layer->SetColor(0, 255, 0); - layer->SetText(buf); - layer->SetBorder(20); - layer->SetAnchor(BitmapAnchor_BottomCenter); - layer->SetPosition(p.GetX(), p.GetY()); - GetScene().SetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX, layer.release()); - } - } - - void FusionMprSdlApp::HideInfoText() - { - GetScene().DeleteLayer(FLOATING_INFOTEXT_LAYER_ZINDEX); - } - - void FusionMprSdlApp::HandleApplicationEvent( - const SDL_Event & event) - { - DisplayInfoText(); - - if (event.type == SDL_MOUSEMOTION) - { - int scancodeCount = 0; - const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount); - - if (activeTracker_.get() == NULL && - SDL_SCANCODE_LALT < scancodeCount && - keyboardState[SDL_SCANCODE_LALT]) - { - // The "left-ctrl" key is down, while no tracker is present - // Let's display the info text - PointerEvent e; - e.AddPosition(controller_->GetViewport().GetPixelCenterCoordinates( - event.button.x, event.button.y)); - - DisplayFloatingCtrlInfoText(e); - } - else - { - HideInfoText(); - //LOG(TRACE) << "(event.type == SDL_MOUSEMOTION)"; - if (activeTracker_.get() != NULL) - { - //LOG(TRACE) << "(activeTracker_.get() != NULL)"; - PointerEvent e; - e.AddPosition(controller_->GetViewport().GetPixelCenterCoordinates( - event.button.x, event.button.y)); - - //LOG(TRACE) << "event.button.x = " << event.button.x << " " << - // "event.button.y = " << event.button.y; - LOG(TRACE) << "activeTracker_->PointerMove(e); " << - e.GetMainPosition().GetX() << " " << e.GetMainPosition().GetY(); - - activeTracker_->PointerMove(e); - if (!activeTracker_->IsAlive()) - activeTracker_.reset(); - } - } - } - else if (event.type == SDL_MOUSEBUTTONUP) - { - if (activeTracker_) - { - PointerEvent e; - e.AddPosition(controller_->GetViewport().GetPixelCenterCoordinates(event.button.x, event.button.y)); - activeTracker_->PointerUp(e); - if (!activeTracker_->IsAlive()) - activeTracker_.reset(); - } - } - else if (event.type == SDL_MOUSEBUTTONDOWN) - { - PointerEvent e; - e.AddPosition(controller_->GetViewport().GetPixelCenterCoordinates( - event.button.x, event.button.y)); - if (activeTracker_) - { - activeTracker_->PointerDown(e); - if (!activeTracker_->IsAlive()) - activeTracker_.reset(); - } - else - { - // we ATTEMPT to create a tracker if need be - activeTracker_ = CreateSuitableTracker(event, e); - } - } - else if (event.type == SDL_KEYDOWN && - event.key.repeat == 0 /* Ignore key bounce */) - { - switch (event.key.keysym.sym) - { - case SDLK_ESCAPE: - if (activeTracker_) - { - activeTracker_->Cancel(); - if (!activeTracker_->IsAlive()) - activeTracker_.reset(); - } - break; - - case SDLK_t: - if (!activeTracker_) - SelectNextTool(); - else - { - LOG(WARNING) << "You cannot change the active tool when an interaction" - " is taking place"; - } - break; - case SDLK_s: - controller_->FitContent(viewport_.GetCompositor().GetCanvasWidth(), - viewport_.GetCompositor().GetCanvasHeight()); - break; - - case SDLK_z: - LOG(TRACE) << "SDLK_z has been pressed. event.key.keysym.mod == " << event.key.keysym.mod; - if (event.key.keysym.mod & KMOD_CTRL) - { - if (controller_->CanUndo()) - { - LOG(TRACE) << "Undoing..."; - controller_->Undo(); - } - else - { - LOG(WARNING) << "Nothing to undo!!!"; - } - } - break; - - case SDLK_y: - LOG(TRACE) << "SDLK_y has been pressed. event.key.keysym.mod == " << event.key.keysym.mod; - if (event.key.keysym.mod & KMOD_CTRL) - { - if (controller_->CanRedo()) - { - LOG(TRACE) << "Redoing..."; - controller_->Redo(); - } - else - { - LOG(WARNING) << "Nothing to redo!!!"; - } - } - break; - - case SDLK_c: - TakeScreenshot( - "screenshot.png", - viewport_.GetCompositor().GetCanvasWidth(), - viewport_.GetCompositor().GetCanvasHeight()); - break; - - default: - break; - } - } - } - - - void FusionMprSdlApp::OnSceneTransformChanged( - const ViewportController::SceneTransformChanged& message) - { - DisplayInfoText(); - } - - boost::shared_ptr<IFlexiblePointerTracker> FusionMprSdlApp::CreateSuitableTracker( - const SDL_Event & event, - const PointerEvent & e) - { - using namespace Orthanc; - - switch (event.button.button) - { - case SDL_BUTTON_MIDDLE: - return boost::shared_ptr<IFlexiblePointerTracker>(new PanSceneTracker - (controller_, e)); - - case SDL_BUTTON_RIGHT: - return boost::shared_ptr<IFlexiblePointerTracker>(new ZoomSceneTracker - (controller_, e, viewport_.GetCompositor().GetCanvasHeight())); - - case SDL_BUTTON_LEFT: - { - //LOG(TRACE) << "CreateSuitableTracker: case SDL_BUTTON_LEFT:"; - // TODO: we need to iterate on the set of measuring tool and perform - // a hit test to check if a tracker needs to be created for edition. - // Otherwise, depending upon the active tool, we might want to create - // a "measuring tool creation" tracker - - // TODO: if there are conflicts, we should prefer a tracker that - // pertains to the type of measuring tool currently selected (TBD?) - boost::shared_ptr<IFlexiblePointerTracker> hitTestTracker = TrackerHitTest(e); - - if (hitTestTracker != NULL) - { - //LOG(TRACE) << "hitTestTracker != NULL"; - return hitTestTracker; - } - else - { - switch (currentTool_) - { - case FusionMprGuiTool_Rotate: - //LOG(TRACE) << "Creating RotateSceneTracker"; - return boost::shared_ptr<IFlexiblePointerTracker>(new RotateSceneTracker( - controller_, e)); - case FusionMprGuiTool_Pan: - return boost::shared_ptr<IFlexiblePointerTracker>(new PanSceneTracker( - controller_, e)); - case FusionMprGuiTool_Zoom: - return boost::shared_ptr<IFlexiblePointerTracker>(new ZoomSceneTracker( - controller_, e, viewport_.GetCompositor().GetCanvasHeight())); - //case GuiTool_AngleMeasure: - // return new AngleMeasureTracker(GetScene(), e); - //case GuiTool_CircleMeasure: - // return new CircleMeasureTracker(GetScene(), e); - //case GuiTool_EllipseMeasure: - // return new EllipseMeasureTracker(GetScene(), e); - case FusionMprGuiTool_LineMeasure: - return boost::shared_ptr<IFlexiblePointerTracker>(new CreateLineMeasureTracker( - IObserver::GetBroker(), controller_, e)); - case FusionMprGuiTool_AngleMeasure: - return boost::shared_ptr<IFlexiblePointerTracker>(new CreateAngleMeasureTracker( - IObserver::GetBroker(), controller_, e)); - case FusionMprGuiTool_CircleMeasure: - LOG(ERROR) << "Not implemented yet!"; - return boost::shared_ptr<IFlexiblePointerTracker>(); - case FusionMprGuiTool_EllipseMeasure: - LOG(ERROR) << "Not implemented yet!"; - return boost::shared_ptr<IFlexiblePointerTracker>(); - default: - throw OrthancException(ErrorCode_InternalError, "Wrong tool!"); - } - } - } - default: - return boost::shared_ptr<IFlexiblePointerTracker>(); - } - } - - - FusionMprSdlApp::FusionMprSdlApp(MessageBroker& broker) - : IObserver(broker) - , broker_(broker) - , oracleObservable_(broker) - , oracle_(*this) - , currentTool_(FusionMprGuiTool_Rotate) - , undoStack_(new UndoStack) - , viewport_("Hello", 1024, 1024, false) // False means we do NOT let Windows treat this as a legacy application that needs to be scaled - { - //oracleObservable.RegisterObserverCallback - //(new Callable - // <FusionMprSdlApp, SleepOracleCommand::TimeoutMessage>(*this, &FusionMprSdlApp::Handle)); - - //oracleObservable.RegisterObserverCallback - //(new Callable - // <Toto, GetOrthancImageCommand::SuccessMessage>(*this, &FusionMprSdlApp::Handle)); - - //oracleObservable.RegisterObserverCallback - //(new Callable - // <FusionMprSdlApp, GetOrthancWebViewerJpegCommand::SuccessMessage>(*this, &ToFusionMprSdlAppto::Handle)); - - oracleObservable_.RegisterObserverCallback - (new Callable - <FusionMprSdlApp, OracleCommandExceptionMessage>(*this, &FusionMprSdlApp::Handle)); - - controller_ = boost::shared_ptr<ViewportController>( - new ViewportController(undoStack_, broker_, viewport_)); - - controller_->RegisterObserverCallback( - new Callable<FusionMprSdlApp, ViewportController::SceneTransformChanged> - (*this, &FusionMprSdlApp::OnSceneTransformChanged)); - - TEXTURE_2x2_1_ZINDEX = 1; - TEXTURE_1x1_ZINDEX = 2; - TEXTURE_2x2_2_ZINDEX = 3; - LINESET_1_ZINDEX = 4; - LINESET_2_ZINDEX = 5; - FLOATING_INFOTEXT_LAYER_ZINDEX = 6; - FIXED_INFOTEXT_LAYER_ZINDEX = 7; - } - - void FusionMprSdlApp::PrepareScene() - { - // Texture of 2x2 size - { - Orthanc::Image i(Orthanc::PixelFormat_RGB24, 2, 2, false); - - uint8_t* p = reinterpret_cast<uint8_t*>(i.GetRow(0)); - p[0] = 255; - p[1] = 0; - p[2] = 0; - - p[3] = 0; - p[4] = 255; - p[5] = 0; - - p = reinterpret_cast<uint8_t*>(i.GetRow(1)); - p[0] = 0; - p[1] = 0; - p[2] = 255; - - p[3] = 255; - p[4] = 0; - p[5] = 0; - - GetScene().SetLayer(TEXTURE_2x2_1_ZINDEX, new ColorTextureSceneLayer(i)); - } - } - - void FusionMprSdlApp::DisableTracker() - { - if (activeTracker_) - { - activeTracker_->Cancel(); - activeTracker_.reset(); - } - } - - void FusionMprSdlApp::TakeScreenshot(const std::string& target, - unsigned int canvasWidth, - unsigned int canvasHeight) - { - CairoCompositor compositor(GetScene(), canvasWidth, canvasHeight); - compositor.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, FONT_SIZE_0, 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); - } - - - boost::shared_ptr<IFlexiblePointerTracker> FusionMprSdlApp::TrackerHitTest(const PointerEvent & e) - { - // std::vector<boost::shared_ptr<MeasureTool>> measureTools_; - return boost::shared_ptr<IFlexiblePointerTracker>(); - } - - static void GLAPIENTRY - OpenGLMessageCallback(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar* message, - const void* userParam) - { - if (severity != GL_DEBUG_SEVERITY_NOTIFICATION) - { - fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", - (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), - type, severity, message); - } - } - - static bool g_stopApplication = false; - - - void FusionMprSdlApp::Handle(const DicomVolumeImage::GeometryReadyMessage& message) - { - printf("Geometry ready\n"); - - //plane_ = message.GetOrigin().GetGeometry().GetSagittalGeometry(); - //plane_ = message.GetOrigin().GetGeometry().GetAxialGeometry(); - plane_ = message.GetOrigin().GetGeometry().GetCoronalGeometry(); - plane_.SetOrigin(message.GetOrigin().GetGeometry().GetCoordinates(0.5f, 0.5f, 0.5f)); - - //Refresh(); - } - - - void FusionMprSdlApp::Handle(const OracleCommandExceptionMessage& message) - { - printf("EXCEPTION: [%s] on command type %d\n", message.GetException().What(), message.GetCommand().GetType()); - - switch (message.GetCommand().GetType()) - { - case IOracleCommand::Type_GetOrthancWebViewerJpeg: - printf("URI: [%s]\n", dynamic_cast<const GetOrthancWebViewerJpegCommand&> - (message.GetCommand()).GetUri().c_str()); - break; - - default: - break; - } - } - - void FusionMprSdlApp::SetVolume1(int depth, - const boost::shared_ptr<OrthancStone::IVolumeSlicer>& volume, - OrthancStone::ILayerStyleConfigurator* style) - { - source1_.reset(new OrthancStone::VolumeSceneLayerSource(controller_->GetScene(), depth, volume)); - - if (style != NULL) - { - source1_->SetConfigurator(style); - } - } - - void FusionMprSdlApp::SetVolume2(int depth, - const boost::shared_ptr<OrthancStone::IVolumeSlicer>& volume, - OrthancStone::ILayerStyleConfigurator* style) - { - source2_.reset(new OrthancStone::VolumeSceneLayerSource(controller_->GetScene(), depth, volume)); - - if (style != NULL) - { - source2_->SetConfigurator(style); - } - } - - void FusionMprSdlApp::SetStructureSet(int depth, - const boost::shared_ptr<OrthancStone::DicomStructureSetLoader>& volume) - { - source3_.reset(new OrthancStone::VolumeSceneLayerSource(controller_->GetScene(), depth, volume)); - } - - void FusionMprSdlApp::Run() - { - // False means we do NOT let Windows treat this as a legacy application - // that needs to be scaled - controller_->FitContent(viewport_.GetCanvasWidth(), viewport_.GetCanvasHeight()); - - glEnable(GL_DEBUG_OUTPUT); - glDebugMessageCallback(OpenGLMessageCallback, 0); - - viewport_.GetCompositor().SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, - FONT_SIZE_0, Orthanc::Encoding_Latin1); - viewport_.GetCompositor().SetFont(1, Orthanc::EmbeddedResources::UBUNTU_FONT, - FONT_SIZE_1, Orthanc::Encoding_Latin1); - - - //////// from loader - { - Orthanc::WebServiceParameters p; - //p.SetUrl("http://localhost:8043/"); - p.SetCredentials("orthanc", "orthanc"); - oracle_.SetOrthancParameters(p); - } - - //////// from Run - - boost::shared_ptr<DicomVolumeImage> ct(new DicomVolumeImage); - boost::shared_ptr<DicomVolumeImage> dose(new DicomVolumeImage); - - - boost::shared_ptr<OrthancSeriesVolumeProgressiveLoader> ctLoader; - boost::shared_ptr<OrthancMultiframeVolumeLoader> doseLoader; - boost::shared_ptr<DicomStructureSetLoader> rtstructLoader; - - { - ctLoader.reset(new OrthancSeriesVolumeProgressiveLoader(ct, oracle_, oracleObservable_)); - doseLoader.reset(new OrthancMultiframeVolumeLoader(dose, oracle_, oracleObservable_)); - rtstructLoader.reset(new DicomStructureSetLoader(oracle_, oracleObservable_)); - } - - //toto->SetReferenceLoader(*ctLoader); - //doseLoader->RegisterObserverCallback - //(new Callable - // <FusionMprSdlApp, DicomVolumeImage::GeometryReadyMessage>(*this, &FusionMprSdlApp::Handle)); - ctLoader->RegisterObserverCallback - (new Callable - <FusionMprSdlApp, DicomVolumeImage::GeometryReadyMessage>(*this, &FusionMprSdlApp::Handle)); - - this->SetVolume1(0, ctLoader, new GrayscaleStyleConfigurator); - - { - std::unique_ptr<LookupTableStyleConfigurator> config(new LookupTableStyleConfigurator); - config->SetLookupTable(Orthanc::EmbeddedResources::COLORMAP_HOT); - - boost::shared_ptr<DicomVolumeImageMPRSlicer> tmp(new DicomVolumeImageMPRSlicer(dose)); - this->SetVolume2(1, tmp, config.release()); - } - - this->SetStructureSet(2, rtstructLoader); - -#if 1 - /* - BGO data - http://localhost:8042/twiga-orthanc-viewer-demo/twiga-orthanc-viewer-demo.html?ct-series=a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa - & - dose-instance=830a69ff-8e4b5ee3-b7f966c8-bccc20fb-d322dceb - & - struct-instance=54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9 - */ - ctLoader->LoadSeries("a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa"); // CT - doseLoader->LoadInstance("830a69ff-8e4b5ee3-b7f966c8-bccc20fb-d322dceb"); // RT-DOSE - rtstructLoader->LoadInstance("54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9"); // RT-STRUCT -#else - //ctLoader->LoadSeries("cb3ea4d1-d08f3856-ad7b6314-74d88d77-60b05618"); // CT - //doseLoader->LoadInstance("41029085-71718346-811efac4-420e2c15-d39f99b6"); // RT-DOSE - //rtstructLoader->LoadInstance("83d9c0c3-913a7fee-610097d7-cbf0522d-fd75bee6"); // RT-STRUCT - - // 2017-05-16 - ctLoader->LoadSeries("a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa"); // CT - doseLoader->LoadInstance("eac822ef-a395f94e-e8121fe0-8411fef8-1f7bffad"); // RT-DOSE - rtstructLoader->LoadInstance("54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9"); // RT-STRUCT -#endif - - oracle_.Start(); - -//// END from loader - - while (!g_stopApplication) - { - viewport_.GetCompositor().Refresh(); - -//////// from loader - if (source1_.get() != NULL) - { - source1_->Update(plane_); - } - - if (source2_.get() != NULL) - { - source2_->Update(plane_); - } - - if (source3_.get() != NULL) - { - source3_->Update(plane_); - } -//// END from loader - - SDL_Event event; - while (!g_stopApplication && SDL_PollEvent(&event)) - { - if (event.type == SDL_QUIT) - { - g_stopApplication = true; - break; - } - else if (event.type == SDL_WINDOWEVENT && - event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) - { - DisableTracker(); // was: tracker.reset(NULL); - } - else if (event.type == SDL_KEYDOWN && - event.key.repeat == 0 /* Ignore key bounce */) - { - switch (event.key.keysym.sym) - { - case SDLK_f: - viewport_.GetWindow().ToggleMaximize(); - break; - - case SDLK_s: - controller_->FitContent(viewport_.GetCanvasWidth(), viewport_.GetCanvasHeight()); - break; - - case SDLK_q: - g_stopApplication = true; - break; - default: - break; - } - } - HandleApplicationEvent(event); - } - SDL_Delay(1); - } - - //// from loader - - //Orthanc::SystemToolbox::ServerBarrier(); - - /** - * WARNING => The oracle must be stopped BEFORE the objects using - * it are destroyed!!! This forces to wait for the completion of - * the running callback methods. Otherwise, the callbacks methods - * might still be running while their parent object is destroyed, - * resulting in crashes. This is very visible if adding a sleep(), - * as in (*). - **/ - - oracle_.Stop(); - //// END from loader - } - - void FusionMprSdlApp::SetInfoDisplayMessage( - std::string key, std::string value) - { - if (value == "") - infoTextMap_.erase(key); - else - infoTextMap_[key] = value; - DisplayInfoText(); - } - -} - - -boost::weak_ptr<OrthancStone::FusionMprSdlApp> g_app; - -void FusionMprSdl_SetInfoDisplayMessage(std::string key, std::string value) -{ - boost::shared_ptr<OrthancStone::FusionMprSdlApp> app = g_app.lock(); - if (app) - { - app->SetInfoDisplayMessage(key, value); - } -} - -/** - * IMPORTANT: The full arguments to "main()" are needed for SDL on - * Windows. Otherwise, one gets the linking error "undefined reference - * to `SDL_main'". https://wiki.libsdl.org/FAQWindows - **/ -int main(int argc, char* argv[]) -{ - using namespace OrthancStone; - - StoneInitialize(); - Orthanc::Logging::EnableInfoLevel(true); -// Orthanc::Logging::EnableTraceLevel(true); - - try - { - OrthancStone::MessageBroker broker; - boost::shared_ptr<FusionMprSdlApp> app(new FusionMprSdlApp(broker)); - g_app = app; - app->PrepareScene(); - app->Run(); - } - catch (Orthanc::OrthancException& e) - { - LOG(ERROR) << "EXCEPTION: " << e.What(); - } - - StoneFinalize(); - - return 0; -} - -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/Sdl/FusionMprSdl.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,209 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../Framework/Viewport/SdlViewport.h" - -#include "../../Framework/Messages/IObserver.h" -#include "../../Framework/Messages/IMessageEmitter.h" -#include "../../Framework/Oracle/OracleCommandExceptionMessage.h" -#include "../../Framework/Scene2DViewport/ViewportController.h" -#include "../../Framework/Volumes/DicomVolumeImage.h" -#include "../../Framework/Oracle/ThreadedOracle.h" - -#include <boost/enable_shared_from_this.hpp> -#include <boost/thread.hpp> -#include <boost/noncopyable.hpp> - -#include <SDL.h> - -namespace OrthancStone -{ - class OpenGLCompositor; - class IVolumeSlicer; - class ILayerStyleConfigurator; - class DicomStructureSetLoader; - class IOracle; - class ThreadedOracle; - class VolumeSceneLayerSource; - class NativeFusionMprApplicationContext; - class SdlOpenGLViewport; - - enum FusionMprGuiTool - { - FusionMprGuiTool_Rotate = 0, - FusionMprGuiTool_Pan, - FusionMprGuiTool_Zoom, - FusionMprGuiTool_LineMeasure, - FusionMprGuiTool_CircleMeasure, - FusionMprGuiTool_AngleMeasure, - FusionMprGuiTool_EllipseMeasure, - FusionMprGuiTool_LAST - }; - - const char* MeasureToolToString(size_t i); - - static const unsigned int FONT_SIZE_0 = 32; - static const unsigned int FONT_SIZE_1 = 24; - - class Scene2D; - class UndoStack; - - /** - This application subclasses IMessageEmitter to use a mutex before forwarding Oracle messages (that - can be sent from multiple threads) - */ - class FusionMprSdlApp : public IObserver - , public boost::enable_shared_from_this<FusionMprSdlApp> - , public IMessageEmitter - { - public: - // 12 because. - FusionMprSdlApp(MessageBroker& broker); - - void PrepareScene(); - void Run(); - void SetInfoDisplayMessage(std::string key, std::string value); - void DisableTracker(); - - Scene2D& GetScene(); - const Scene2D& GetScene() const; - - void HandleApplicationEvent(const SDL_Event& event); - - /** - This method is called when the scene transform changes. It allows to - recompute the visual elements whose content depend upon the scene transform - */ - void OnSceneTransformChanged( - const ViewportController::SceneTransformChanged& message); - - - virtual void EmitMessage(const IObserver& observer, - const IMessage& message) ORTHANC_OVERRIDE - { - try - { - boost::unique_lock<boost::shared_mutex> lock(mutex_); - oracleObservable_.EmitMessage(observer, message); - } - catch (Orthanc::OrthancException& e) - { - LOG(ERROR) << "Exception while emitting a message: " << e.What(); - throw; - } - } - - private: -#if 1 - // if threaded (not wasm) - MessageBroker& broker_; - IObservable oracleObservable_; - ThreadedOracle oracle_; - boost::shared_mutex mutex_; // to serialize messages from the ThreadedOracle -#endif - - void SelectNextTool(); - - /** - This returns a random point in the canvas part of the scene, but in - scene coordinates - */ - ScenePoint2D GetRandomPointInScene() const; - - boost::shared_ptr<IFlexiblePointerTracker> TrackerHitTest(const PointerEvent& e); - - boost::shared_ptr<IFlexiblePointerTracker> CreateSuitableTracker( - const SDL_Event& event, - const PointerEvent& e); - - void TakeScreenshot( - const std::string& target, - unsigned int canvasWidth, - unsigned int canvasHeight); - - /** - This adds the command at the top of the undo stack - */ - void Commit(boost::shared_ptr<TrackerCommand> cmd); - void Undo(); - void Redo(); - - - // TODO private - void Handle(const DicomVolumeImage::GeometryReadyMessage& message); - void Handle(const OracleCommandExceptionMessage& message); - - void SetVolume1( - int depth, - const boost::shared_ptr<IVolumeSlicer>& volume, - ILayerStyleConfigurator* style); - - void SetVolume2( - int depth, - const boost::shared_ptr<IVolumeSlicer>& volume, - ILayerStyleConfigurator* style); - - void SetStructureSet( - int depth, - const boost::shared_ptr<DicomStructureSetLoader>& volume); - - - - private: - void DisplayFloatingCtrlInfoText(const PointerEvent& e); - void DisplayInfoText(); - void HideInfoText(); - - private: - CoordinateSystem3D plane_; - - boost::shared_ptr<VolumeSceneLayerSource> source1_, source2_, source3_; - - /** - WARNING: the measuring tools do store a reference to the scene, and it - paramount that the scene gets destroyed AFTER the measurement tools. - */ - boost::shared_ptr<ViewportController> controller_; - - std::map<std::string, std::string> infoTextMap_; - boost::shared_ptr<IFlexiblePointerTracker> activeTracker_; - - //static const int LAYER_POSITION = 150; - - int TEXTURE_2x2_1_ZINDEX; - int TEXTURE_1x1_ZINDEX; - int TEXTURE_2x2_2_ZINDEX; - int LINESET_1_ZINDEX; - int LINESET_2_ZINDEX; - int FLOATING_INFOTEXT_LAYER_ZINDEX; - int FIXED_INFOTEXT_LAYER_ZINDEX; - - FusionMprGuiTool currentTool_; - boost::shared_ptr<UndoStack> undoStack_; - SdlOpenGLViewport viewport_; - }; - -} - - -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/Sdl/Loader.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,518 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "../../Framework/Loaders/DicomStructureSetLoader.h" -#include "../../Framework/Loaders/OrthancMultiframeVolumeLoader.h" -#include "../../Framework/Loaders/OrthancSeriesVolumeProgressiveLoader.h" -#include "../../Framework/Oracle/SleepOracleCommand.h" -#include "../../Framework/Oracle/ThreadedOracle.h" -#include "../../Framework/Scene2D/CairoCompositor.h" -#include "../../Framework/Scene2D/GrayscaleStyleConfigurator.h" -#include "../../Framework/Scene2D/LookupTableStyleConfigurator.h" -#include "../../Framework/StoneInitialization.h" -#include "../../Framework/Volumes/VolumeSceneLayerSource.h" -#include "../../Framework/Volumes/DicomVolumeImageMPRSlicer.h" -#include "../../Framework/Volumes/DicomVolumeImageReslicer.h" - -// From Orthanc framework -#include <Core/Images/ImageProcessing.h> -#include <Core/Images/PngWriter.h> -#include <Core/Logging.h> -#include <Core/OrthancException.h> -#include <Core/SystemToolbox.h> - - -namespace OrthancStone -{ - class NativeApplicationContext : public IMessageEmitter - { - private: - boost::shared_mutex mutex_; - MessageBroker broker_; - IObservable oracleObservable_; - - public: - NativeApplicationContext() : - oracleObservable_(broker_) - { - } - - - virtual void EmitMessage(const IObserver& observer, - const IMessage& message) ORTHANC_OVERRIDE - { - try - { - boost::unique_lock<boost::shared_mutex> lock(mutex_); - oracleObservable_.EmitMessage(observer, message); - } - catch (Orthanc::OrthancException& e) - { - LOG(ERROR) << "Exception while emitting a message: " << e.What(); - } - } - - - class ReaderLock : public boost::noncopyable - { - private: - NativeApplicationContext& that_; - boost::shared_lock<boost::shared_mutex> lock_; - - public: - ReaderLock(NativeApplicationContext& that) : - that_(that), - lock_(that.mutex_) - { - } - }; - - - class WriterLock : public boost::noncopyable - { - private: - NativeApplicationContext& that_; - boost::unique_lock<boost::shared_mutex> lock_; - - public: - WriterLock(NativeApplicationContext& that) : - that_(that), - lock_(that.mutex_) - { - } - - MessageBroker& GetBroker() - { - return that_.broker_; - } - - IObservable& GetOracleObservable() - { - return that_.oracleObservable_; - } - }; - }; -} - - - -class Toto : public OrthancStone::IObserver -{ -private: - OrthancStone::CoordinateSystem3D plane_; - OrthancStone::IOracle& oracle_; - OrthancStone::Scene2D scene_; - std::unique_ptr<OrthancStone::VolumeSceneLayerSource> source1_, source2_, source3_; - - - void Refresh() - { - if (source1_.get() != NULL) - { - source1_->Update(plane_); - } - - if (source2_.get() != NULL) - { - source2_->Update(plane_); - } - - if (source3_.get() != NULL) - { - source3_->Update(plane_); - } - - scene_.FitContent(1024, 768); - - { - OrthancStone::CairoCompositor compositor(scene_, 1024, 768); - compositor.Refresh(); - - Orthanc::ImageAccessor accessor; - compositor.GetCanvas().GetReadOnlyAccessor(accessor); - - Orthanc::Image tmp(Orthanc::PixelFormat_RGB24, accessor.GetWidth(), accessor.GetHeight(), false); - Orthanc::ImageProcessing::Convert(tmp, accessor); - - static unsigned int count = 0; - char buf[64]; - sprintf(buf, "scene-%06d.png", count++); - - Orthanc::PngWriter writer; - writer.WriteToFile(buf, tmp); - } - } - - - void Handle(const OrthancStone::DicomVolumeImage::GeometryReadyMessage& message) - { - printf("Geometry ready\n"); - - plane_ = message.GetOrigin().GetGeometry().GetSagittalGeometry(); - //plane_ = message.GetOrigin().GetGeometry().GetAxialGeometry(); - //plane_ = message.GetOrigin().GetGeometry().GetCoronalGeometry(); - plane_.SetOrigin(message.GetOrigin().GetGeometry().GetCoordinates(0.5f, 0.5f, 0.5f)); - - Refresh(); - } - - - void Handle(const OrthancStone::SleepOracleCommand::TimeoutMessage& message) - { - if (message.GetOrigin().HasPayload()) - { - printf("TIMEOUT! %d\n", dynamic_cast<const Orthanc::SingleValueObject<unsigned int>& >(message.GetOrigin().GetPayload()).GetValue()); - } - else - { - printf("TIMEOUT\n"); - - Refresh(); - - /** - * The sleep() leads to a crash if the oracle is still running, - * while this object is destroyed. Always stop the oracle before - * destroying active objects. (*) - **/ - // boost::this_thread::sleep(boost::posix_time::seconds(2)); - - oracle_.Schedule(*this, new OrthancStone::SleepOracleCommand(message.GetOrigin().GetDelay())); - } - } - - void Handle(const OrthancStone::OrthancRestApiCommand::SuccessMessage& message) - { - Json::Value v; - message.ParseJsonBody(v); - - printf("ICI [%s]\n", v.toStyledString().c_str()); - } - - void Handle(const OrthancStone::GetOrthancImageCommand::SuccessMessage& message) - { - printf("IMAGE %dx%d\n", message.GetImage().GetWidth(), message.GetImage().GetHeight()); - } - - void Handle(const OrthancStone::GetOrthancWebViewerJpegCommand::SuccessMessage& message) - { - printf("WebViewer %dx%d\n", message.GetImage().GetWidth(), message.GetImage().GetHeight()); - } - - void Handle(const OrthancStone::OracleCommandExceptionMessage& message) - { - printf("EXCEPTION: [%s] on command type %d\n", message.GetException().What(), message.GetCommand().GetType()); - - switch (message.GetCommand().GetType()) - { - case OrthancStone::IOracleCommand::Type_GetOrthancWebViewerJpeg: - printf("URI: [%s]\n", dynamic_cast<const OrthancStone::GetOrthancWebViewerJpegCommand&> - (message.GetCommand()).GetUri().c_str()); - break; - - default: - break; - } - } - -public: - Toto(OrthancStone::IOracle& oracle, - OrthancStone::IObservable& oracleObservable) : - IObserver(oracleObservable.GetBroker()), - oracle_(oracle) - { - oracleObservable.RegisterObserverCallback - (new OrthancStone::Callable - <Toto, OrthancStone::SleepOracleCommand::TimeoutMessage>(*this, &Toto::Handle)); - - oracleObservable.RegisterObserverCallback - (new OrthancStone::Callable - <Toto, OrthancStone::OrthancRestApiCommand::SuccessMessage>(*this, &Toto::Handle)); - - oracleObservable.RegisterObserverCallback - (new OrthancStone::Callable - <Toto, OrthancStone::GetOrthancImageCommand::SuccessMessage>(*this, &Toto::Handle)); - - oracleObservable.RegisterObserverCallback - (new OrthancStone::Callable - <Toto, OrthancStone::GetOrthancWebViewerJpegCommand::SuccessMessage>(*this, &Toto::Handle)); - - oracleObservable.RegisterObserverCallback - (new OrthancStone::Callable - <Toto, OrthancStone::OracleCommandExceptionMessage>(*this, &Toto::Handle)); - } - - void SetReferenceLoader(OrthancStone::IObservable& loader) - { - loader.RegisterObserverCallback - (new OrthancStone::Callable - <Toto, OrthancStone::DicomVolumeImage::GeometryReadyMessage>(*this, &Toto::Handle)); - } - - void SetVolume1(int depth, - const boost::shared_ptr<OrthancStone::IVolumeSlicer>& volume, - OrthancStone::ILayerStyleConfigurator* style) - { - source1_.reset(new OrthancStone::VolumeSceneLayerSource(scene_, depth, volume)); - - if (style != NULL) - { - source1_->SetConfigurator(style); - } - } - - void SetVolume2(int depth, - const boost::shared_ptr<OrthancStone::IVolumeSlicer>& volume, - OrthancStone::ILayerStyleConfigurator* style) - { - source2_.reset(new OrthancStone::VolumeSceneLayerSource(scene_, depth, volume)); - - if (style != NULL) - { - source2_->SetConfigurator(style); - } - } - - void SetStructureSet(int depth, - const boost::shared_ptr<OrthancStone::DicomStructureSetLoader>& volume) - { - source3_.reset(new OrthancStone::VolumeSceneLayerSource(scene_, depth, volume)); - } - -}; - - -void Run(OrthancStone::NativeApplicationContext& context, - OrthancStone::ThreadedOracle& oracle) -{ - // the oracle has been supplied with the context (as an IEmitter) upon - // creation - boost::shared_ptr<OrthancStone::DicomVolumeImage> ct(new OrthancStone::DicomVolumeImage); - boost::shared_ptr<OrthancStone::DicomVolumeImage> dose(new OrthancStone::DicomVolumeImage); - - - boost::shared_ptr<Toto> toto; - boost::shared_ptr<OrthancStone::OrthancSeriesVolumeProgressiveLoader> ctLoader; - boost::shared_ptr<OrthancStone::OrthancMultiframeVolumeLoader> doseLoader; - boost::shared_ptr<OrthancStone::DicomStructureSetLoader> rtstructLoader; - - { - OrthancStone::NativeApplicationContext::WriterLock lock(context); - toto.reset(new Toto(oracle, lock.GetOracleObservable())); - - // the oracle is used to schedule commands - // the oracleObservable is used by the loaders to: - // - request the broker (lifetime mgmt) - // - register the loader callbacks (called indirectly by the oracle) - ctLoader.reset(new OrthancStone::OrthancSeriesVolumeProgressiveLoader(ct, oracle, lock.GetOracleObservable())); - doseLoader.reset(new OrthancStone::OrthancMultiframeVolumeLoader(dose, oracle, lock.GetOracleObservable())); - rtstructLoader.reset(new OrthancStone::DicomStructureSetLoader(oracle, lock.GetOracleObservable())); - } - - - //toto->SetReferenceLoader(*ctLoader); - toto->SetReferenceLoader(*doseLoader); - - -#if 1 - toto->SetVolume1(0, ctLoader, new OrthancStone::GrayscaleStyleConfigurator); -#else - { - boost::shared_ptr<OrthancStone::IVolumeSlicer> reslicer(new OrthancStone::DicomVolumeImageReslicer(ct)); - toto->SetVolume1(0, reslicer, new OrthancStone::GrayscaleStyleConfigurator); - } -#endif - - - { - std::unique_ptr<OrthancStone::LookupTableStyleConfigurator> config(new OrthancStone::LookupTableStyleConfigurator); - config->SetLookupTable(Orthanc::EmbeddedResources::COLORMAP_HOT); - - boost::shared_ptr<OrthancStone::DicomVolumeImageMPRSlicer> tmp(new OrthancStone::DicomVolumeImageMPRSlicer(dose)); - toto->SetVolume2(1, tmp, config.release()); - } - - toto->SetStructureSet(2, rtstructLoader); - - oracle.Schedule(*toto, new OrthancStone::SleepOracleCommand(100)); - - if (0) - { - Json::Value v = Json::objectValue; - v["Level"] = "Series"; - v["Query"] = Json::objectValue; - - std::unique_ptr<OrthancStone::OrthancRestApiCommand> command(new OrthancStone::OrthancRestApiCommand); - command->SetMethod(Orthanc::HttpMethod_Post); - command->SetUri("/tools/find"); - command->SetBody(v); - - oracle.Schedule(*toto, command.release()); - } - - if(0) - { - if (0) - { - std::unique_ptr<OrthancStone::GetOrthancImageCommand> command(new OrthancStone::GetOrthancImageCommand); - command->SetHttpHeader("Accept", std::string(Orthanc::EnumerationToString(Orthanc::MimeType_Jpeg))); - command->SetUri("/instances/6687cc73-07cae193-52ff29c8-f646cb16-0753ed92/preview"); - oracle.Schedule(*toto, command.release()); - } - - if (0) - { - std::unique_ptr<OrthancStone::GetOrthancImageCommand> command(new OrthancStone::GetOrthancImageCommand); - command->SetHttpHeader("Accept", std::string(Orthanc::EnumerationToString(Orthanc::MimeType_Png))); - command->SetUri("/instances/6687cc73-07cae193-52ff29c8-f646cb16-0753ed92/preview"); - oracle.Schedule(*toto, command.release()); - } - - if (0) - { - std::unique_ptr<OrthancStone::GetOrthancImageCommand> command(new OrthancStone::GetOrthancImageCommand); - command->SetHttpHeader("Accept", std::string(Orthanc::EnumerationToString(Orthanc::MimeType_Png))); - command->SetUri("/instances/6687cc73-07cae193-52ff29c8-f646cb16-0753ed92/image-uint16"); - oracle.Schedule(*toto, command.release()); - } - - if (0) - { - std::unique_ptr<OrthancStone::GetOrthancImageCommand> command(new OrthancStone::GetOrthancImageCommand); - command->SetHttpHeader("Accept-Encoding", "gzip"); - command->SetHttpHeader("Accept", std::string(Orthanc::EnumerationToString(Orthanc::MimeType_Pam))); - command->SetUri("/instances/6687cc73-07cae193-52ff29c8-f646cb16-0753ed92/image-uint16"); - oracle.Schedule(*toto, command.release()); - } - - if (0) - { - std::unique_ptr<OrthancStone::GetOrthancImageCommand> command(new OrthancStone::GetOrthancImageCommand); - command->SetHttpHeader("Accept", std::string(Orthanc::EnumerationToString(Orthanc::MimeType_Pam))); - command->SetUri("/instances/6687cc73-07cae193-52ff29c8-f646cb16-0753ed92/image-uint16"); - oracle.Schedule(*toto, command.release()); - } - - if (0) - { - std::unique_ptr<OrthancStone::GetOrthancWebViewerJpegCommand> command(new OrthancStone::GetOrthancWebViewerJpegCommand); - command->SetHttpHeader("Accept-Encoding", "gzip"); - command->SetInstance("e6c7c20b-c9f65d7e-0d76f2e2-830186f2-3e3c600e"); - command->SetQuality(90); - oracle.Schedule(*toto, command.release()); - } - - - if (0) - { - for (unsigned int i = 0; i < 10; i++) - { - std::unique_ptr<OrthancStone::SleepOracleCommand> command(new OrthancStone::SleepOracleCommand(i * 1000)); - command->SetPayload(new Orthanc::SingleValueObject<unsigned int>(42 * i)); - oracle.Schedule(*toto, command.release()); - } - } - } - - // 2017-11-17-Anonymized -#if 0 - // BGO data - ctLoader->LoadSeries("a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa"); // CT - doseLoader->LoadInstance("830a69ff-8e4b5ee3-b7f966c8-bccc20fb-d322dceb"); // RT-DOSE - //rtstructLoader->LoadInstance("54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9"); // RT-STRUCT -#else - //ctLoader->LoadSeries("cb3ea4d1-d08f3856-ad7b6314-74d88d77-60b05618"); // CT - //doseLoader->LoadInstance("41029085-71718346-811efac4-420e2c15-d39f99b6"); // RT-DOSE - //rtstructLoader->LoadInstance("83d9c0c3-913a7fee-610097d7-cbf0522d-fd75bee6"); // RT-STRUCT - - // 2017-05-16 - ctLoader->LoadSeries("a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa"); // CT - doseLoader->LoadInstance("eac822ef-a395f94e-e8121fe0-8411fef8-1f7bffad"); // RT-DOSE - rtstructLoader->LoadInstance("54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9"); // RT-STRUCT -#endif - // 2015-01-28-Multiframe - //doseLoader->LoadInstance("88f71e2a-5fad1c61-96ed14d6-5b3d3cf7-a5825279"); // Multiframe CT - - // Delphine - //ctLoader->LoadSeries("5990e39c-51e5f201-fe87a54c-31a55943-e59ef80e"); // CT - //ctLoader->LoadSeries("67f1b334-02c16752-45026e40-a5b60b6b-030ecab5"); // Lung 1/10mm - - - { - LOG(WARNING) << "...Waiting for Ctrl-C..."; - - oracle.Start(); - - Orthanc::SystemToolbox::ServerBarrier(); - - /** - * WARNING => The oracle must be stopped BEFORE the objects using - * it are destroyed!!! This forces to wait for the completion of - * the running callback methods. Otherwise, the callbacks methods - * might still be running while their parent object is destroyed, - * resulting in crashes. This is very visible if adding a sleep(), - * as in (*). - **/ - - oracle.Stop(); - } -} - - - -/** - * IMPORTANT: The full arguments to "main()" are needed for SDL on - * Windows. Otherwise, one gets the linking error "undefined reference - * to `SDL_main'". https://wiki.libsdl.org/FAQWindows - **/ -int main(int argc, char* argv[]) -{ - OrthancStone::StoneInitialize(); - //Orthanc::Logging::EnableInfoLevel(true); - - try - { - OrthancStone::NativeApplicationContext context; - - OrthancStone::ThreadedOracle oracle(context); - //oracle.SetThreadsCount(1); - - { - Orthanc::WebServiceParameters p; - //p.SetUrl("http://localhost:8043/"); - p.SetCredentials("orthanc", "orthanc"); - oracle.SetOrthancParameters(p); - } - - //oracle.Start(); - - Run(context, oracle); - - //oracle.Stop(); - } - catch (Orthanc::OrthancException& e) - { - LOG(ERROR) << "EXCEPTION: " << e.What(); - } - - OrthancStone::StoneFinalize(); - - return 0; -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/Sdl/RadiographyEditor.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,267 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#include "../Shared/RadiographyEditorApp.h" - -// From Stone -#include "../../Framework/Oracle/SleepOracleCommand.h" -#include "../../Framework/Oracle/ThreadedOracle.h" -#include "../../Applications/Sdl/SdlOpenGLWindow.h" -#include "../../Framework/Scene2D/OpenGLCompositor.h" -#include "../../Framework/Scene2D/CairoCompositor.h" -#include "../../Framework/Scene2D/ColorTextureSceneLayer.h" -#include "../../Framework/Scene2D/OpenGLCompositor.h" -#include "../../Framework/StoneInitialization.h" - -#include <Core/Logging.h> -#include <Core/OrthancException.h> - - -#include <boost/shared_ptr.hpp> -#include <boost/weak_ptr.hpp> - -#include <SDL.h> -#include <stdio.h> - -using namespace OrthancStone; - -namespace OrthancStone -{ - class NativeApplicationContext : public IMessageEmitter - { - private: - boost::shared_mutex mutex_; - MessageBroker broker_; - IObservable oracleObservable_; - - public: - NativeApplicationContext() : - oracleObservable_(broker_) - { - } - - - virtual void EmitMessage(const IObserver& observer, - const IMessage& message) ORTHANC_OVERRIDE - { - try - { - boost::unique_lock<boost::shared_mutex> lock(mutex_); - oracleObservable_.EmitMessage(observer, message); - } - catch (Orthanc::OrthancException& e) - { - LOG(ERROR) << "Exception while emitting a message: " << e.What(); - } - } - - - class ReaderLock : public boost::noncopyable - { - private: - NativeApplicationContext& that_; - boost::shared_lock<boost::shared_mutex> lock_; - - public: - ReaderLock(NativeApplicationContext& that) : - that_(that), - lock_(that.mutex_) - { - } - }; - - - class WriterLock : public boost::noncopyable - { - private: - NativeApplicationContext& that_; - boost::unique_lock<boost::shared_mutex> lock_; - - public: - WriterLock(NativeApplicationContext& that) : - that_(that), - lock_(that.mutex_) - { - } - - MessageBroker& GetBroker() - { - return that_.broker_; - } - - IObservable& GetOracleObservable() - { - return that_.oracleObservable_; - } - }; - }; -} - -class OpenGlSdlCompositorFactory : public ICompositorFactory -{ - OpenGL::IOpenGLContext& openGlContext_; - -public: - OpenGlSdlCompositorFactory(OpenGL::IOpenGLContext& openGlContext) : - openGlContext_(openGlContext) - {} - - ICompositor* GetCompositor(const Scene2D& scene) - { - - OpenGLCompositor* compositor = new OpenGLCompositor(openGlContext_, scene); - compositor->SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, - FONT_SIZE_0, Orthanc::Encoding_Latin1); - compositor->SetFont(1, Orthanc::EmbeddedResources::UBUNTU_FONT, - FONT_SIZE_1, Orthanc::Encoding_Latin1); - return compositor; - } -}; - -static void GLAPIENTRY -OpenGLMessageCallback(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar* message, - const void* userParam) -{ - if (severity != GL_DEBUG_SEVERITY_NOTIFICATION) - { - fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", - (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), - type, severity, message); - } -} - - -/** - * IMPORTANT: The full arguments to "main()" are needed for SDL on - * Windows. Otherwise, one gets the linking error "undefined reference - * to `SDL_main'". https://wiki.libsdl.org/FAQWindows - **/ -int main(int argc, char* argv[]) -{ - using namespace OrthancStone; - - StoneInitialize(); - Orthanc::Logging::EnableInfoLevel(true); - // Orthanc::Logging::EnableTraceLevel(true); - - try - { - OrthancStone::NativeApplicationContext context; - OrthancStone::NativeApplicationContext::WriterLock lock(context); - OrthancStone::ThreadedOracle oracle(context); - - // False means we do NOT let Windows treat this as a legacy application - // that needs to be scaled - SdlOpenGLWindow window("Hello", 1024, 1024, false); - - glEnable(GL_DEBUG_OUTPUT); - glDebugMessageCallback(OpenGLMessageCallback, 0); - - std::unique_ptr<OpenGlSdlCompositorFactory> compositorFactory(new OpenGlSdlCompositorFactory(window)); - boost::shared_ptr<RadiographyEditorApp> app(new RadiographyEditorApp(oracle, lock.GetOracleObservable(), compositorFactory.release())); - app->PrepareScene(); - app->FitContent(window.GetCanvasWidth(), window.GetCanvasHeight()); - - bool stopApplication = false; - - while (!stopApplication) - { - app->Refresh(); - - SDL_Event event; - while (!stopApplication && SDL_PollEvent(&event)) - { - OrthancStone::KeyboardModifiers modifiers = OrthancStone::KeyboardModifiers_None; - if (event.key.keysym.mod & KMOD_CTRL) - modifiers = static_cast<OrthancStone::KeyboardModifiers>(static_cast<int>(modifiers) | static_cast<int>(OrthancStone::KeyboardModifiers_Control)); - if (event.key.keysym.mod & KMOD_ALT) - modifiers = static_cast<OrthancStone::KeyboardModifiers>(static_cast<int>(modifiers) | static_cast<int>(OrthancStone::KeyboardModifiers_Alt)); - if (event.key.keysym.mod & KMOD_SHIFT) - modifiers = static_cast<OrthancStone::KeyboardModifiers>(static_cast<int>(modifiers) | static_cast<int>(OrthancStone::KeyboardModifiers_Shift)); - - OrthancStone::MouseButton button; - if (event.button.button == SDL_BUTTON_LEFT) - button = OrthancStone::MouseButton_Left; - else if (event.button.button == SDL_BUTTON_MIDDLE) - button = OrthancStone::MouseButton_Middle; - else if (event.button.button == SDL_BUTTON_RIGHT) - button = OrthancStone::MouseButton_Right; - - if (event.type == SDL_QUIT) - { - stopApplication = true; - break; - } - else if (event.type == SDL_WINDOWEVENT && - event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) - { - app->DisableTracker(); // was: tracker.reset(NULL); - app->UpdateSize(); - } - else if (event.type == SDL_KEYDOWN && - event.key.repeat == 0 /* Ignore key bounce */) - { - switch (event.key.keysym.sym) - { - case SDLK_f: - window.GetWindow().ToggleMaximize(); - break; - - case SDLK_q: - stopApplication = true; - break; - default: - { - app->OnKeyPressed(event.key.keysym.sym, modifiers); - } - } - } - else if (event.type == SDL_MOUSEBUTTONDOWN) - { - app->OnMouseDown(event.button.x, event.button.y, modifiers, button); - } - else if (event.type == SDL_MOUSEMOTION) - { - app->OnMouseMove(event.button.x, event.button.y, modifiers); - } - else if (event.type == SDL_MOUSEBUTTONUP) - { - app->OnMouseUp(event.button.x, event.button.y, modifiers, button); - } - } - SDL_Delay(1); - } - } - catch (Orthanc::OrthancException& e) - { - LOG(ERROR) << "EXCEPTION: " << e.What(); - } - - StoneFinalize(); - - return 0; -} - -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/Sdl/TrackerSample.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#include "TrackerSampleApp.h" - - // From Stone -#include "../../Framework/OpenGL/SdlOpenGLContext.h" -#include "../../Framework/Scene2D/CairoCompositor.h" -#include "../../Framework/Scene2D/ColorTextureSceneLayer.h" -#include "../../Framework/Scene2D/OpenGLCompositor.h" -#include "../../Framework/StoneInitialization.h" - -#include <Core/Logging.h> -#include <Core/OrthancException.h> - - -#include <boost/shared_ptr.hpp> -#include <boost/weak_ptr.hpp> - -#include <SDL.h> -#include <stdio.h> - -/* -TODO: - -- to decouple the trackers from the sample, we need to supply them with - the scene rather than the app - -- in order to do that, we need a GetNextFreeZIndex function (or something - along those lines) in the scene object - -*/ - -boost::weak_ptr<OrthancStone::TrackerSampleApp> g_app; - -void TrackerSample_SetInfoDisplayMessage(std::string key, std::string value) -{ - boost::shared_ptr<OrthancStone::TrackerSampleApp> app = g_app.lock(); - if (app) - { - app->SetInfoDisplayMessage(key, value); - } -} - -/** - * IMPORTANT: The full arguments to "main()" are needed for SDL on - * Windows. Otherwise, one gets the linking error "undefined reference - * to `SDL_main'". https://wiki.libsdl.org/FAQWindows - **/ -int main(int argc, char* argv[]) -{ - using namespace OrthancStone; - - StoneInitialize(); - Orthanc::Logging::EnableInfoLevel(true); -// Orthanc::Logging::EnableTraceLevel(true); - - try - { - MessageBroker broker; - boost::shared_ptr<TrackerSampleApp> app(new TrackerSampleApp(broker)); - g_app = app; - app->PrepareScene(); - app->Run(); - } - catch (Orthanc::OrthancException& e) - { - LOG(ERROR) << "EXCEPTION: " << e.What(); - } - - StoneFinalize(); - - return 0; -} - -
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/Sdl/TrackerSampleApp.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,733 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#include "TrackerSampleApp.h" - -#include "../../Framework/OpenGL/SdlOpenGLContext.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/Scene2D.h" -#include "../../Framework/Scene2D/ZoomSceneTracker.h" -#include "../../Framework/Scene2DViewport/UndoStack.h" -#include "../../Framework/Scene2DViewport/CreateAngleMeasureTracker.h" -#include "../../Framework/Scene2DViewport/CreateLineMeasureTracker.h" -#include "../../Framework/StoneInitialization.h" - -// From Orthanc framework -#include <Core/Logging.h> -#include <Core/OrthancException.h> -#include <Core/Images/Image.h> -#include <Core/Images/ImageProcessing.h> -#include <Core/Images/PngWriter.h> - -#include <boost/ref.hpp> -#include <boost/make_shared.hpp> -#include <SDL.h> - -#include <stdio.h> - -namespace OrthancStone -{ - const char* MeasureToolToString(size_t i) - { - static const char* descs[] = { - "GuiTool_Rotate", - "GuiTool_Pan", - "GuiTool_Zoom", - "GuiTool_LineMeasure", - "GuiTool_CircleMeasure", - "GuiTool_AngleMeasure", - "GuiTool_EllipseMeasure", - "GuiTool_LAST" - }; - if (i >= GuiTool_LAST) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, "Wrong tool index"); - } - return descs[i]; - } - - void TrackerSampleApp::SelectNextTool() - { - currentTool_ = static_cast<GuiTool>(currentTool_ + 1); - if (currentTool_ == GuiTool_LAST) - currentTool_ = static_cast<GuiTool>(0);; - printf("Current tool is now: %s\n", MeasureToolToString(currentTool_)); - } - - void TrackerSampleApp::DisplayInfoText() - { - // do not try to use stuff too early! - std::stringstream msg; - - for (std::map<std::string, std::string>::const_iterator kv = infoTextMap_.begin(); - kv != infoTextMap_.end(); ++kv) - { - msg << kv->first << " : " << kv->second << std::endl; - } - std::string msgS = msg.str(); - - TextSceneLayer* layerP = NULL; - if (controller_->GetScene().HasLayer(FIXED_INFOTEXT_LAYER_ZINDEX)) - { - TextSceneLayer& layer = dynamic_cast<TextSceneLayer&>( - controller_->GetScene().GetLayer(FIXED_INFOTEXT_LAYER_ZINDEX)); - layerP = &layer; - } - else - { - std::unique_ptr<TextSceneLayer> layer(new TextSceneLayer); - layerP = layer.get(); - layer->SetColor(0, 255, 0); - layer->SetFontIndex(1); - layer->SetBorder(20); - layer->SetAnchor(BitmapAnchor_TopLeft); - //layer->SetPosition(0,0); - 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 = GetCompositor().GetCanvasWidth() * (-0.5); - double cY = GetCompositor().GetCanvasHeight() * (-0.5); - controller_->GetScene().GetCanvasToSceneTransform().Apply(cX,cY); - layerP->SetPosition(cX, cY); - } - - void TrackerSampleApp::DisplayFloatingCtrlInfoText(const PointerEvent& e) - { - 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 (controller_->GetScene().HasLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)) - { - TextSceneLayer& layer = - dynamic_cast<TextSceneLayer&>(controller_->GetScene().GetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)); - layer.SetText(buf); - layer.SetPosition(p.GetX(), p.GetY()); - } - else - { - std::unique_ptr<TextSceneLayer> layer(new TextSceneLayer); - layer->SetColor(0, 255, 0); - layer->SetText(buf); - layer->SetBorder(20); - layer->SetAnchor(BitmapAnchor_BottomCenter); - layer->SetPosition(p.GetX(), p.GetY()); - controller_->GetScene().SetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX, layer.release()); - } - } - - void TrackerSampleApp::HideInfoText() - { - controller_->GetScene().DeleteLayer(FLOATING_INFOTEXT_LAYER_ZINDEX); - } - - ScenePoint2D TrackerSampleApp::GetRandomPointInScene() const - { - unsigned int w = GetCompositor().GetCanvasWidth(); - LOG(TRACE) << "GetCompositor().GetCanvasWidth() = " << - GetCompositor().GetCanvasWidth(); - unsigned int h = GetCompositor().GetCanvasHeight(); - LOG(TRACE) << "GetCompositor().GetCanvasHeight() = " << - GetCompositor().GetCanvasHeight(); - - if ((w >= RAND_MAX) || (h >= RAND_MAX)) - LOG(WARNING) << "Canvas is too big : tools will not be randomly placed"; - - int x = rand() % w; - int y = rand() % h; - LOG(TRACE) << "random x = " << x << "random y = " << y; - - ScenePoint2D p = controller_->GetViewport().GetPixelCenterCoordinates(x, y); - LOG(TRACE) << "--> p.GetX() = " << p.GetX() << " p.GetY() = " << p.GetY(); - - ScenePoint2D r = p.Apply(controller_->GetScene().GetCanvasToSceneTransform()); - LOG(TRACE) << "--> r.GetX() = " << r.GetX() << " r.GetY() = " << r.GetY(); - return r; - } - - void TrackerSampleApp::CreateRandomMeasureTool() - { - static bool srandCalled = false; - if (!srandCalled) - { - srand(42); - srandCalled = true; - } - - int i = rand() % 2; - LOG(TRACE) << "random i = " << i; - switch (i) - { - case 0: - // line measure - { - boost::shared_ptr<CreateLineMeasureCommand> cmd = - boost::make_shared<CreateLineMeasureCommand>( - boost::ref(IObserver::GetBroker()), - controller_, - GetRandomPointInScene()); - cmd->SetEnd(GetRandomPointInScene()); - controller_->PushCommand(cmd); - } - break; - case 1: - // angle measure - { - boost::shared_ptr<CreateAngleMeasureCommand> cmd = - boost::make_shared<CreateAngleMeasureCommand>( - boost::ref(IObserver::GetBroker()), - controller_, - GetRandomPointInScene()); - cmd->SetCenter(GetRandomPointInScene()); - cmd->SetSide2End(GetRandomPointInScene()); - controller_->PushCommand(cmd); - } - break; - } - } - - void TrackerSampleApp::HandleApplicationEvent( - const SDL_Event & event) - { - DisplayInfoText(); - - if (event.type == SDL_MOUSEMOTION) - { - int scancodeCount = 0; - const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount); - - if (activeTracker_.get() == NULL && - SDL_SCANCODE_LALT < scancodeCount && - keyboardState[SDL_SCANCODE_LALT]) - { - // The "left-ctrl" key is down, while no tracker is present - // Let's display the info text - PointerEvent e; - e.AddPosition(controller_->GetViewport().GetPixelCenterCoordinates( - event.button.x, event.button.y)); - - DisplayFloatingCtrlInfoText(e); - } - else if (activeTracker_.get() != NULL) - { - HideInfoText(); - //LOG(TRACE) << "(event.type == SDL_MOUSEMOTION)"; - if (activeTracker_.get() != NULL) - { - //LOG(TRACE) << "(activeTracker_.get() != NULL)"; - PointerEvent e; - e.AddPosition(controller_->GetViewport().GetPixelCenterCoordinates( - event.button.x, event.button.y)); - - //LOG(TRACE) << "event.button.x = " << event.button.x << " " << - // "event.button.y = " << event.button.y; - LOG(TRACE) << "activeTracker_->PointerMove(e); " << - e.GetMainPosition().GetX() << " " << e.GetMainPosition().GetY(); - - activeTracker_->PointerMove(e); - if (!activeTracker_->IsAlive()) - activeTracker_.reset(); - } - } - else - { - HideInfoText(); - - PointerEvent e; - e.AddPosition(controller_->GetViewport().GetPixelCenterCoordinates(event.button.x, event.button.y)); - - ScenePoint2D scenePos = e.GetMainPosition().Apply( - controller_->GetScene().GetCanvasToSceneTransform()); - //auto measureTools = GetController()->HitTestMeasureTools(scenePos); - //LOG(TRACE) << "# of hit tests: " << measureTools.size(); - - // this returns the collection of measuring tools where hit test is true - std::vector<boost::shared_ptr<MeasureTool> > measureTools = controller_->HitTestMeasureTools(scenePos); - - // let's refresh the measuring tools highlighted state - // first let's tag them as "unhighlighted" - controller_->ResetMeasuringToolsHighlight(); - - // then immediately take the first one and ask it to highlight the - // measuring tool UI part that is hot - if (measureTools.size() > 0) - { - measureTools[0]->Highlight(scenePos); - } - } - } - else if (event.type == SDL_MOUSEBUTTONUP) - { - if (activeTracker_) - { - PointerEvent e; - e.AddPosition(controller_->GetViewport().GetPixelCenterCoordinates(event.button.x, event.button.y)); - activeTracker_->PointerUp(e); - if (!activeTracker_->IsAlive()) - activeTracker_.reset(); - } - } - else if (event.type == SDL_MOUSEBUTTONDOWN) - { - PointerEvent e; - e.AddPosition(controller_->GetViewport().GetPixelCenterCoordinates( - event.button.x, event.button.y)); - if (activeTracker_) - { - activeTracker_->PointerDown(e); - if (!activeTracker_->IsAlive()) - activeTracker_.reset(); - } - else - { - // we ATTEMPT to create a tracker if need be - activeTracker_ = CreateSuitableTracker(event, e); - } - } - else if (event.type == SDL_KEYDOWN && - event.key.repeat == 0 /* Ignore key bounce */) - { - switch (event.key.keysym.sym) - { - case SDLK_ESCAPE: - if (activeTracker_) - { - activeTracker_->Cancel(); - if (!activeTracker_->IsAlive()) - activeTracker_.reset(); - } - break; - - case SDLK_t: - if (!activeTracker_) - SelectNextTool(); - else - { - LOG(WARNING) << "You cannot change the active tool when an interaction" - " is taking place"; - } - break; - - case SDLK_m: - CreateRandomMeasureTool(); - break; - case SDLK_s: - controller_->FitContent(GetCompositor().GetCanvasWidth(), - GetCompositor().GetCanvasHeight()); - break; - - case SDLK_z: - LOG(TRACE) << "SDLK_z has been pressed. event.key.keysym.mod == " << event.key.keysym.mod; - if (event.key.keysym.mod & KMOD_CTRL) - { - if (controller_->CanUndo()) - { - LOG(TRACE) << "Undoing..."; - controller_->Undo(); - } - else - { - LOG(WARNING) << "Nothing to undo!!!"; - } - } - break; - - case SDLK_y: - LOG(TRACE) << "SDLK_y has been pressed. event.key.keysym.mod == " << event.key.keysym.mod; - if (event.key.keysym.mod & KMOD_CTRL) - { - if (controller_->CanRedo()) - { - LOG(TRACE) << "Redoing..."; - controller_->Redo(); - } - else - { - LOG(WARNING) << "Nothing to redo!!!"; - } - } - break; - - case SDLK_c: - TakeScreenshot( - "screenshot.png", - GetCompositor().GetCanvasWidth(), - GetCompositor().GetCanvasHeight()); - break; - - default: - break; - } - } - } - - - void TrackerSampleApp::OnSceneTransformChanged( - const ViewportController::SceneTransformChanged& message) - { - DisplayInfoText(); - } - - boost::shared_ptr<IFlexiblePointerTracker> TrackerSampleApp::CreateSuitableTracker( - const SDL_Event & event, - const PointerEvent & e) - { - using namespace Orthanc; - - switch (event.button.button) - { - case SDL_BUTTON_MIDDLE: - return boost::shared_ptr<IFlexiblePointerTracker>(new PanSceneTracker - (controller_, e)); - - case SDL_BUTTON_RIGHT: - return boost::shared_ptr<IFlexiblePointerTracker>(new ZoomSceneTracker - (controller_, e, GetCompositor().GetCanvasHeight())); - - case SDL_BUTTON_LEFT: - { - //LOG(TRACE) << "CreateSuitableTracker: case SDL_BUTTON_LEFT:"; - // TODO: we need to iterate on the set of measuring tool and perform - // a hit test to check if a tracker needs to be created for edition. - // Otherwise, depending upon the active tool, we might want to create - // a "measuring tool creation" tracker - - // TODO: if there are conflicts, we should prefer a tracker that - // pertains to the type of measuring tool currently selected (TBD?) - boost::shared_ptr<IFlexiblePointerTracker> hitTestTracker = TrackerHitTest(e); - - if (hitTestTracker != NULL) - { - //LOG(TRACE) << "hitTestTracker != NULL"; - return hitTestTracker; - } - else - { - switch (currentTool_) - { - case GuiTool_Rotate: - //LOG(TRACE) << "Creating RotateSceneTracker"; - return boost::shared_ptr<IFlexiblePointerTracker>(new RotateSceneTracker( - controller_, e)); - case GuiTool_Pan: - return boost::shared_ptr<IFlexiblePointerTracker>(new PanSceneTracker( - controller_, e)); - case GuiTool_Zoom: - return boost::shared_ptr<IFlexiblePointerTracker>(new ZoomSceneTracker( - controller_, e, GetCompositor().GetCanvasHeight())); - //case GuiTool_AngleMeasure: - // return new AngleMeasureTracker(GetScene(), e); - //case GuiTool_CircleMeasure: - // return new CircleMeasureTracker(GetScene(), e); - //case GuiTool_EllipseMeasure: - // return new EllipseMeasureTracker(GetScene(), e); - case GuiTool_LineMeasure: - return boost::shared_ptr<IFlexiblePointerTracker>(new CreateLineMeasureTracker( - IObserver::GetBroker(), controller_, e)); - case GuiTool_AngleMeasure: - return boost::shared_ptr<IFlexiblePointerTracker>(new CreateAngleMeasureTracker( - IObserver::GetBroker(), controller_, e)); - case GuiTool_CircleMeasure: - LOG(ERROR) << "Not implemented yet!"; - return boost::shared_ptr<IFlexiblePointerTracker>(); - case GuiTool_EllipseMeasure: - LOG(ERROR) << "Not implemented yet!"; - return boost::shared_ptr<IFlexiblePointerTracker>(); - default: - throw OrthancException(ErrorCode_InternalError, "Wrong tool!"); - } - } - } - default: - return boost::shared_ptr<IFlexiblePointerTracker>(); - } - } - - - TrackerSampleApp::TrackerSampleApp(MessageBroker& broker) : IObserver(broker) - , currentTool_(GuiTool_Rotate) - , undoStack_(new UndoStack) - , viewport_("Hello", 1024, 1024, false) // False means we do NOT let Windows treat this as a legacy application that needs to be scaled - { - controller_ = boost::shared_ptr<ViewportController>( - new ViewportController(undoStack_, broker, viewport_)); - - controller_->RegisterObserverCallback( - new Callable<TrackerSampleApp, ViewportController::SceneTransformChanged> - (*this, &TrackerSampleApp::OnSceneTransformChanged)); - - TEXTURE_2x2_1_ZINDEX = 1; - TEXTURE_1x1_ZINDEX = 2; - TEXTURE_2x2_2_ZINDEX = 3; - LINESET_1_ZINDEX = 4; - LINESET_2_ZINDEX = 5; - FLOATING_INFOTEXT_LAYER_ZINDEX = 6; - FIXED_INFOTEXT_LAYER_ZINDEX = 7; - } - - void TrackerSampleApp::PrepareScene() - { - // Texture of 2x2 size - { - Orthanc::Image i(Orthanc::PixelFormat_RGB24, 2, 2, false); - - uint8_t* p = reinterpret_cast<uint8_t*>(i.GetRow(0)); - p[0] = 255; - p[1] = 0; - p[2] = 0; - - p[3] = 0; - p[4] = 255; - p[5] = 0; - - p = reinterpret_cast<uint8_t*>(i.GetRow(1)); - p[0] = 0; - p[1] = 0; - p[2] = 255; - - p[3] = 255; - p[4] = 0; - p[5] = 0; - - controller_->GetScene().SetLayer(TEXTURE_2x2_1_ZINDEX, new ColorTextureSceneLayer(i)); - - std::unique_ptr<ColorTextureSceneLayer> l(new ColorTextureSceneLayer(i)); - l->SetOrigin(-3, 2); - l->SetPixelSpacing(1.5, 1); - l->SetAngle(20.0 / 180.0 * M_PI); - controller_->GetScene().SetLayer(TEXTURE_2x2_2_ZINDEX, l.release()); - } - - // Texture of 1x1 size - { - Orthanc::Image i(Orthanc::PixelFormat_RGB24, 1, 1, false); - - uint8_t* p = reinterpret_cast<uint8_t*>(i.GetRow(0)); - p[0] = 255; - p[1] = 0; - p[2] = 0; - - std::unique_ptr<ColorTextureSceneLayer> l(new ColorTextureSceneLayer(i)); - l->SetOrigin(-2, 1); - l->SetAngle(20.0 / 180.0 * M_PI); - controller_->GetScene().SetLayer(TEXTURE_1x1_ZINDEX, l.release()); - } - - // Some lines - { - std::unique_ptr<PolylineSceneLayer> 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); - - controller_->GetScene().SetLayer(LINESET_1_ZINDEX, layer.release()); - } - - // Some text - { - std::unique_ptr<TextSceneLayer> layer(new TextSceneLayer); - layer->SetText("Hello"); - controller_->GetScene().SetLayer(LINESET_2_ZINDEX, layer.release()); - } - } - - - void TrackerSampleApp::DisableTracker() - { - if (activeTracker_) - { - activeTracker_->Cancel(); - activeTracker_.reset(); - } - } - - void TrackerSampleApp::TakeScreenshot(const std::string& target, - unsigned int canvasWidth, - unsigned int canvasHeight) - { - CairoCompositor compositor(controller_->GetScene(), canvasWidth, canvasHeight); - compositor.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, FONT_SIZE_0, 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); - } - - - boost::shared_ptr<IFlexiblePointerTracker> TrackerSampleApp::TrackerHitTest(const PointerEvent & e) - { - // std::vector<boost::shared_ptr<MeasureTool>> measureTools_; - ScenePoint2D scenePos = e.GetMainPosition().Apply( - controller_->GetScene().GetCanvasToSceneTransform()); - - std::vector<boost::shared_ptr<MeasureTool> > measureTools = controller_->HitTestMeasureTools(scenePos); - - if (measureTools.size() > 0) - { - return measureTools[0]->CreateEditionTracker(e); - } - return boost::shared_ptr<IFlexiblePointerTracker>(); - } - - static void GLAPIENTRY - OpenGLMessageCallback(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar* message, - const void* userParam) - { - if (severity != GL_DEBUG_SEVERITY_NOTIFICATION) - { - fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", - (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), - type, severity, message); - } - } - - static bool g_stopApplication = false; - - ICompositor& TrackerSampleApp::GetCompositor() - { - using namespace Orthanc; - try - { - SdlViewport& viewport = dynamic_cast<SdlViewport&>(viewport_); - return viewport.GetCompositor(); - } - catch (std::bad_cast e) - { - throw OrthancException(ErrorCode_InternalError, "Wrong viewport type!"); - } - } - - const ICompositor& TrackerSampleApp::GetCompositor() const - { - using namespace Orthanc; - try - { - SdlViewport& viewport = const_cast<SdlViewport&>(dynamic_cast<const SdlViewport&>(viewport_)); - return viewport.GetCompositor(); - } - catch (std::bad_cast e) - { - throw OrthancException(ErrorCode_InternalError, "Wrong viewport type!"); - } - } - - - void TrackerSampleApp::Run() - { - controller_->FitContent(viewport_.GetCanvasWidth(), viewport_.GetCanvasHeight()); - - glEnable(GL_DEBUG_OUTPUT); - glDebugMessageCallback(OpenGLMessageCallback, 0); - - GetCompositor().SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, - FONT_SIZE_0, Orthanc::Encoding_Latin1); - GetCompositor().SetFont(1, Orthanc::EmbeddedResources::UBUNTU_FONT, - FONT_SIZE_1, Orthanc::Encoding_Latin1); - - while (!g_stopApplication) - { - GetCompositor().Refresh(); - - SDL_Event event; - while (!g_stopApplication && SDL_PollEvent(&event)) - { - if (event.type == SDL_QUIT) - { - g_stopApplication = true; - break; - } - else if (event.type == SDL_WINDOWEVENT && - event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) - { - DisableTracker(); // was: tracker.reset(NULL); - } - else if (event.type == SDL_KEYDOWN && - event.key.repeat == 0 /* Ignore key bounce */) - { - switch (event.key.keysym.sym) - { - case SDLK_f: - viewport_.GetWindow().ToggleMaximize(); - break; - - case SDLK_q: - g_stopApplication = true; - break; - default: - break; - } - } - HandleApplicationEvent(event); - } - SDL_Delay(1); - } - } - - void TrackerSampleApp::SetInfoDisplayMessage( - std::string key, std::string value) - { - if (value == "") - infoTextMap_.erase(key); - else - infoTextMap_[key] = value; - DisplayInfoText(); - } - -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/Sdl/TrackerSampleApp.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,150 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../Framework/Messages/IObserver.h" -#include "../../Framework/Scene2D/OpenGLCompositor.h" -#include "../../Framework/Scene2DViewport/IFlexiblePointerTracker.h" -#include "../../Framework/Scene2DViewport/MeasureTool.h" -#include "../../Framework/Scene2DViewport/PredeclaredTypes.h" -#include "../../Framework/Scene2DViewport/ViewportController.h" -#include "../../Framework/Viewport/SdlViewport.h" - -#include <SDL.h> - -#include <boost/make_shared.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> - -namespace OrthancStone -{ - enum GuiTool - { - GuiTool_Rotate = 0, - GuiTool_Pan, - GuiTool_Zoom, - GuiTool_LineMeasure, - GuiTool_CircleMeasure, - GuiTool_AngleMeasure, - GuiTool_EllipseMeasure, - GuiTool_LAST - }; - - const char* MeasureToolToString(size_t i); - - static const unsigned int FONT_SIZE_0 = 32; - static const unsigned int FONT_SIZE_1 = 24; - - class Scene2D; - class UndoStack; - - class TrackerSampleApp : public IObserver - , public boost::enable_shared_from_this<TrackerSampleApp> - { - public: - // 12 because. - TrackerSampleApp(MessageBroker& broker); - void PrepareScene(); - void Run(); - void SetInfoDisplayMessage(std::string key, std::string value); - void DisableTracker(); - - void HandleApplicationEvent(const SDL_Event& event); - - /** - This method is called when the scene transform changes. It allows to - recompute the visual elements whose content depend upon the scene transform - */ - void OnSceneTransformChanged( - const ViewportController::SceneTransformChanged& message); - - private: - void SelectNextTool(); - void CreateRandomMeasureTool(); - - - /** - In the case of this app, the viewport is an SDL viewport and it has - a OpenGLCompositor& GetCompositor() method - */ - ICompositor& GetCompositor(); - - /** - See the other overload - */ - const ICompositor& GetCompositor() const; - - /** - This returns a random point in the canvas part of the scene, but in - scene coordinates - */ - ScenePoint2D GetRandomPointInScene() const; - - boost::shared_ptr<IFlexiblePointerTracker> TrackerHitTest(const PointerEvent& e); - - boost::shared_ptr<IFlexiblePointerTracker> CreateSuitableTracker( - const SDL_Event& event, - const PointerEvent& e); - - void TakeScreenshot( - const std::string& target, - unsigned int canvasWidth, - unsigned int canvasHeight); - - /** - This adds the command at the top of the undo stack - */ - void Commit(boost::shared_ptr<TrackerCommand> cmd); - void Undo(); - void Redo(); - - private: - void DisplayFloatingCtrlInfoText(const PointerEvent& e); - void DisplayInfoText(); - void HideInfoText(); - - private: - /** - WARNING: the measuring tools do store a reference to the scene, and it - paramount that the scene gets destroyed AFTER the measurement tools. - */ - boost::shared_ptr<ViewportController> controller_; - - std::map<std::string, std::string> infoTextMap_; - boost::shared_ptr<IFlexiblePointerTracker> activeTracker_; - - //static const int LAYER_POSITION = 150; - - int TEXTURE_2x2_1_ZINDEX; - int TEXTURE_1x1_ZINDEX; - int TEXTURE_2x2_2_ZINDEX; - int LINESET_1_ZINDEX; - int LINESET_2_ZINDEX; - int FLOATING_INFOTEXT_LAYER_ZINDEX; - int FIXED_INFOTEXT_LAYER_ZINDEX; - - GuiTool currentTool_; - boost::shared_ptr<UndoStack> undoStack_; - SdlOpenGLViewport viewport_; - }; - -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/Sdl/cpp.hint Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -#define ORTHANC_OVERRIDE -#define ORTHANC_STONE_DEFINE_EMPTY_MESSAGE(FILE, LINE, NAME) class NAME : public ::OrthancStone::IMessage {};
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/WebAssembly/BasicMPR.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,427 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - - -#include "dev.h" - -#include <emscripten.h> - -#include "../../Framework/Loaders/OrthancSeriesVolumeProgressiveLoader.h" -#include "../../Framework/Oracle/SleepOracleCommand.h" -#include "../../Framework/Oracle/WebAssemblyOracle.h" -#include "../../Framework/Scene2D/GrayscaleStyleConfigurator.h" -#include "../../Framework/StoneInitialization.h" -#include "../../Framework/Volumes/VolumeSceneLayerSource.h" - - -namespace OrthancStone -{ - class VolumeSlicerWidget : public IObserver - { - private: - OrthancStone::WebAssemblyViewport viewport_; - std::unique_ptr<VolumeSceneLayerSource> source_; - VolumeProjection projection_; - std::vector<CoordinateSystem3D> planes_; - size_t currentPlane_; - - void Handle(const DicomVolumeImage::GeometryReadyMessage& message) - { - LOG(INFO) << "Geometry is available"; - - const VolumeImageGeometry& geometry = message.GetOrigin().GetGeometry(); - - const unsigned int depth = geometry.GetProjectionDepth(projection_); - currentPlane_ = depth / 2; - - planes_.resize(depth); - - for (unsigned int z = 0; z < depth; z++) - { - planes_[z] = geometry.GetProjectionSlice(projection_, z); - } - - Refresh(); - - viewport_.FitContent(); - } - - public: - VolumeSlicerWidget(MessageBroker& broker, - const std::string& canvas, - VolumeProjection projection) : - IObserver(broker), - viewport_(broker, canvas), - projection_(projection), - currentPlane_(0) - { - } - - void UpdateSize() - { - viewport_.UpdateSize(); - } - - void SetSlicer(int layerDepth, - const boost::shared_ptr<IVolumeSlicer>& slicer, - IObservable& loader, - ILayerStyleConfigurator* configurator) - { - if (source_.get() != NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls, - "Only one slicer can be registered"); - } - - loader.RegisterObserverCallback( - new Callable<VolumeSlicerWidget, DicomVolumeImage::GeometryReadyMessage> - (*this, &VolumeSlicerWidget::Handle)); - - source_.reset(new VolumeSceneLayerSource(viewport_.GetScene(), layerDepth, slicer)); - - if (configurator != NULL) - { - source_->SetConfigurator(configurator); - } - } - - void Refresh() - { - if (source_.get() != NULL && - currentPlane_ < planes_.size()) - { - source_->Update(planes_[currentPlane_]); - viewport_.Refresh(); - } - } - - size_t GetSlicesCount() const - { - return planes_.size(); - } - - void Scroll(int delta) - { - if (!planes_.empty()) - { - int tmp = static_cast<int>(currentPlane_) + delta; - unsigned int next; - - if (tmp < 0) - { - next = 0; - } - else if (tmp >= static_cast<int>(planes_.size())) - { - next = planes_.size() - 1; - } - else - { - next = static_cast<size_t>(tmp); - } - - if (next != currentPlane_) - { - currentPlane_ = next; - Refresh(); - } - } - } - }; -} - - - - -boost::shared_ptr<OrthancStone::DicomVolumeImage> ct_(new OrthancStone::DicomVolumeImage); - -boost::shared_ptr<OrthancStone::OrthancSeriesVolumeProgressiveLoader> loader_; - -std::unique_ptr<OrthancStone::VolumeSlicerWidget> widget1_; -std::unique_ptr<OrthancStone::VolumeSlicerWidget> widget2_; -std::unique_ptr<OrthancStone::VolumeSlicerWidget> widget3_; - -OrthancStone::MessageBroker broker_; -OrthancStone::WebAssemblyOracle oracle_(broker_); - - -EM_BOOL OnWindowResize(int eventType, const EmscriptenUiEvent *uiEvent, void *userData) -{ - try - { - if (widget1_.get() != NULL) - { - widget1_->UpdateSize(); - } - - if (widget2_.get() != NULL) - { - widget2_->UpdateSize(); - } - - if (widget3_.get() != NULL) - { - widget3_->UpdateSize(); - } - } - catch (Orthanc::OrthancException& e) - { - LOG(ERROR) << "Exception while updating canvas size: " << e.What(); - } - - return true; -} - - - - -EM_BOOL OnAnimationFrame(double time, void *userData) -{ - try - { - if (widget1_.get() != NULL) - { - widget1_->Refresh(); - } - - if (widget2_.get() != NULL) - { - widget2_->Refresh(); - } - - if (widget3_.get() != NULL) - { - widget3_->Refresh(); - } - - return true; - } - catch (Orthanc::OrthancException& e) - { - LOG(ERROR) << "Exception in the animation loop, stopping now: " << e.What(); - return false; - } -} - - -static bool ctrlDown_ = false; - - -EM_BOOL OnMouseWheel(int eventType, - const EmscriptenWheelEvent *wheelEvent, - void *userData) -{ - try - { - if (userData != NULL) - { - int delta = 0; - - if (wheelEvent->deltaY < 0) - { - delta = -1; - } - - if (wheelEvent->deltaY > 0) - { - delta = 1; - } - - OrthancStone::VolumeSlicerWidget& widget = - *reinterpret_cast<OrthancStone::VolumeSlicerWidget*>(userData); - - if (ctrlDown_) - { - delta *= static_cast<int>(widget.GetSlicesCount() / 10); - } - - widget.Scroll(delta); - } - } - catch (Orthanc::OrthancException& e) - { - LOG(ERROR) << "Exception in the wheel event: " << e.What(); - } - - return true; -} - - -EM_BOOL OnKeyDown(int eventType, - const EmscriptenKeyboardEvent *keyEvent, - void *userData) -{ - ctrlDown_ = keyEvent->ctrlKey; - return false; -} - - -EM_BOOL OnKeyUp(int eventType, - const EmscriptenKeyboardEvent *keyEvent, - void *userData) -{ - ctrlDown_ = false; - return false; -} - - - - -namespace OrthancStone -{ - class TestSleep : public IObserver - { - private: - WebAssemblyOracle& oracle_; - - void Schedule() - { - oracle_.Schedule(*this, new OrthancStone::SleepOracleCommand(2000)); - } - - void Handle(const SleepOracleCommand::TimeoutMessage& message) - { - LOG(INFO) << "TIMEOUT"; - Schedule(); - } - - public: - TestSleep(MessageBroker& broker, - WebAssemblyOracle& oracle) : - IObserver(broker), - oracle_(oracle) - { - oracle.RegisterObserverCallback( - new Callable<TestSleep, SleepOracleCommand::TimeoutMessage> - (*this, &TestSleep::Handle)); - - LOG(INFO) << "STARTING"; - Schedule(); - } - }; - - //static TestSleep testSleep(broker_, oracle_); -} - - - -static std::map<std::string, std::string> arguments_; - -static bool GetArgument(std::string& value, - const std::string& key) -{ - std::map<std::string, std::string>::const_iterator found = arguments_.find(key); - - if (found == arguments_.end()) - { - return false; - } - else - { - value = found->second; - return true; - } -} - - -extern "C" -{ - int main(int argc, char const *argv[]) - { - OrthancStone::StoneInitialize(); - Orthanc::Logging::EnableInfoLevel(true); - // Orthanc::Logging::EnableTraceLevel(true); - EM_ASM(window.dispatchEvent(new CustomEvent("WebAssemblyLoaded"));); - } - - EMSCRIPTEN_KEEPALIVE - void SetArgument(const char* key, const char* value) - { - // This is called for each GET argument (cf. "app.js") - LOG(INFO) << "Received GET argument: [" << key << "] = [" << value << "]"; - arguments_[key] = value; - } - - EMSCRIPTEN_KEEPALIVE - void Initialize() - { - try - { - oracle_.SetOrthancRoot(".."); - - loader_.reset(new OrthancStone::OrthancSeriesVolumeProgressiveLoader(ct_, oracle_, oracle_)); - - widget1_.reset(new OrthancStone::VolumeSlicerWidget(broker_, "mycanvas1", OrthancStone::VolumeProjection_Axial)); - { - std::unique_ptr<OrthancStone::GrayscaleStyleConfigurator> style(new OrthancStone::GrayscaleStyleConfigurator); - style->SetLinearInterpolation(true); - style->SetWindowing(OrthancStone::ImageWindowing_Bone); - widget1_->SetSlicer(0, loader_, *loader_, style.release()); - } - widget1_->UpdateSize(); - - widget2_.reset(new OrthancStone::VolumeSlicerWidget(broker_, "mycanvas2", OrthancStone::VolumeProjection_Coronal)); - { - std::unique_ptr<OrthancStone::GrayscaleStyleConfigurator> style(new OrthancStone::GrayscaleStyleConfigurator); - style->SetLinearInterpolation(true); - style->SetWindowing(OrthancStone::ImageWindowing_Bone); - widget2_->SetSlicer(0, loader_, *loader_, style.release()); - } - widget2_->UpdateSize(); - - widget3_.reset(new OrthancStone::VolumeSlicerWidget(broker_, "mycanvas3", OrthancStone::VolumeProjection_Sagittal)); - { - std::unique_ptr<OrthancStone::GrayscaleStyleConfigurator> style(new OrthancStone::GrayscaleStyleConfigurator); - style->SetLinearInterpolation(true); - style->SetWindowing(OrthancStone::ImageWindowing_Bone); - widget3_->SetSlicer(0, loader_, *loader_, style.release()); - } - widget3_->UpdateSize(); - - emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, OnWindowResize); // DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=1 !! - - emscripten_set_wheel_callback("#mycanvas1", widget1_.get(), false, OnMouseWheel); - emscripten_set_wheel_callback("#mycanvas2", widget2_.get(), false, OnMouseWheel); - emscripten_set_wheel_callback("#mycanvas3", widget3_.get(), false, OnMouseWheel); - - emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, OnKeyDown); - emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, OnKeyUp); - - emscripten_request_animation_frame_loop(OnAnimationFrame, NULL); - - - std::string ct; - if (GetArgument(ct, "ct")) - { - //loader_->LoadSeries("a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa"); - loader_->LoadSeries(ct); - } - else - { - LOG(ERROR) << "No Orthanc identifier for the CT series was provided"; - } - } - catch (Orthanc::OrthancException& e) - { - LOG(ERROR) << "Exception during Initialize(): " << e.What(); - } - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/WebAssembly/BasicMPR.html Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -<!doctype html> -<html lang="en-us"> - <head> - <meta charset="utf-8"> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> - - <!-- Disable pinch zoom on mobile devices --> - <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> - <meta name="HandheldFriendly" content="true" /> - - - <title>Stone of Orthanc</title> - - <style> - html, body { - width: 100%; - height: 100%; - margin: 0px; - border: 0; - overflow: hidden; /* Disable scrollbars */ - display: block; /* No floating content on sides */ - } - - #mycanvas1 { - position:absolute; - left:0%; - top:0%; - background-color: red; - width: 50%; - height: 100%; - } - - #mycanvas2 { - position:absolute; - left:50%; - top:0%; - background-color: green; - width: 50%; - height: 50%; - } - - #mycanvas3 { - position:absolute; - left:50%; - top:50%; - background-color: blue; - width: 50%; - height: 50%; - } - </style> - </head> - <body> - <canvas id="mycanvas1" oncontextmenu="return false;"></canvas> - <canvas id="mycanvas2" oncontextmenu="return false;"></canvas> - <canvas id="mycanvas3" oncontextmenu="return false;"></canvas> - - <script type="text/javascript" src="app.js"></script> - <script type="text/javascript" async src="BasicMPR.js"></script> - </body> -</html>
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/WebAssembly/BasicScene.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,210 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "dev.h" - -#include <emscripten.h> -#include <emscripten/html5.h> - -// From Stone -#include "../../Framework/Scene2D/ColorTextureSceneLayer.h" -#include "../../Framework/StoneInitialization.h" - -// From Orthanc framework -#include <Core/Images/Image.h> -#include <Core/Logging.h> -#include <Core/OrthancException.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<uint8_t*>(i.GetRow(0)); - p[0] = 255; - p[1] = 0; - p[2] = 0; - - p[3] = 0; - p[4] = 255; - p[5] = 0; - - p = reinterpret_cast<uint8_t*>(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::unique_ptr<ColorTextureSceneLayer> 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<uint8_t*>(i.GetRow(0)); - p[0] = 255; - p[1] = 0; - p[2] = 0; - - std::unique_ptr<ColorTextureSceneLayer> 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::unique_ptr<PolylineSceneLayer> 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::unique_ptr<TextSceneLayer> layer(new TextSceneLayer); - layer->SetText("Hello"); - scene.SetLayer(100, layer.release()); - } -} - - -std::unique_ptr<OrthancStone::WebAssemblyViewport> viewport1_; -std::unique_ptr<OrthancStone::WebAssemblyViewport> viewport2_; -std::unique_ptr<OrthancStone::WebAssemblyViewport> viewport3_; -boost::shared_ptr<OrthancStone::ViewportController> controller1_; -boost::shared_ptr<OrthancStone::ViewportController> controller2_; -boost::shared_ptr<OrthancStone::ViewportController> controller3_; -OrthancStone::MessageBroker broker_; - - -EM_BOOL OnWindowResize( - int eventType, const EmscriptenUiEvent *uiEvent, void *userData) -{ - if (viewport1_.get() != NULL) - { - viewport1_->UpdateSize(); - } - - if (viewport2_.get() != NULL) - { - viewport2_->UpdateSize(); - } - - if (viewport3_.get() != NULL) - { - viewport3_->UpdateSize(); - } - - return true; -} - -extern "C" -{ - int main(int argc, char const *argv[]) - { - OrthancStone::StoneInitialize(); - // Orthanc::Logging::EnableInfoLevel(true); - // Orthanc::Logging::EnableTraceLevel(true); - EM_ASM(window.dispatchEvent(new CustomEvent("WebAssemblyLoaded"));); - } - - EMSCRIPTEN_KEEPALIVE - void Initialize() - { - viewport1_.reset(new OrthancStone::WebAssemblyViewport("mycanvas1")); - PrepareScene(viewport1_->GetScene()); - viewport1_->UpdateSize(); - - viewport2_.reset(new OrthancStone::WebAssemblyViewport("mycanvas2")); - PrepareScene(viewport2_->GetScene()); - viewport2_->UpdateSize(); - - 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<OrthancStone::UndoStack>(), broker_, *viewport1_)); - controller2_.reset(new OrthancStone::ViewportController(boost::make_shared<OrthancStone::UndoStack>(), broker_, *viewport2_)); - controller3_.reset(new OrthancStone::ViewportController(boost::make_shared<OrthancStone::UndoStack>(), 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); - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/WebAssembly/BasicScene.html Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -<!doctype html> -<html lang="en-us"> - <head> - <meta charset="utf-8"> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> - - <!-- Disable pinch zoom on mobile devices --> - <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> - <meta name="HandheldFriendly" content="true" /> - - - <title>Stone of Orthanc</title> - - <style> - html, body { - width: 100%; - height: 100%; - margin: 0px; - border: 0; - overflow: hidden; /* Disable scrollbars */ - display: block; /* No floating content on sides */ - } - - #mycanvas1 { - position:absolute; - left:0%; - top:0%; - background-color: red; - width: 50%; - height: 100%; - } - - #mycanvas2 { - position:absolute; - left:50%; - top:0%; - background-color: green; - width: 50%; - height: 50%; - } - - #mycanvas3 { - position:absolute; - left:50%; - top:50%; - background-color: blue; - width: 50%; - height: 50%; - } - </style> - </head> - <body> - <canvas id="mycanvas1" oncontextmenu="return false;"></canvas> - <canvas id="mycanvas2" oncontextmenu="return false;"></canvas> - <canvas id="mycanvas3" oncontextmenu="return false;"></canvas> - - <script type="text/javascript"> - if (!('WebAssembly' in window)) { - alert('Sorry, your browser does not support WebAssembly :('); - } else { - window.addEventListener('WebAssemblyLoaded', function() { - Module.ccall('Initialize', null, null, null); - }); - } - </script> - - <script type="text/javascript" async src="BasicScene.js"></script> - </body> -</html>
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/WebAssembly/CMakeLists.txt Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -cmake_minimum_required(VERSION 2.8.3) - - -##################################################################### -## Configuration of the Emscripten compiler for WebAssembly target -##################################################################### - -set(WASM_FLAGS "-s WASM=1 -s FETCH=1") - -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WASM_FLAGS}") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WASM_FLAGS}") -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"ccall\", \"cwrap\"]'") -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s ERROR_ON_UNDEFINED_SYMBOLS=1") -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s ALLOW_MEMORY_GROWTH=1") -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 -##################################################################### - -# This CMake file defines the "ORTHANC_STONE_VERSION" macro, so it -# must be the first inclusion -include(${CMAKE_SOURCE_DIR}/../../Resources/CMake/Version.cmake) - -if (ORTHANC_STONE_VERSION STREQUAL "mainline") - set(ORTHANC_FRAMEWORK_VERSION "mainline") - set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "hg") -else() - set(ORTHANC_FRAMEWORK_VERSION "1.5.7") - set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "web") -endif() - -set(ORTHANC_FRAMEWORK_SOURCE "${ORTHANC_FRAMEWORK_DEFAULT_SOURCE}" CACHE STRING "Source of the Orthanc source code (can be \"hg\", \"archive\", \"web\" or \"path\")") -set(ORTHANC_FRAMEWORK_ARCHIVE "" CACHE STRING "Path to the Orthanc archive, if ORTHANC_FRAMEWORK_SOURCE is \"archive\"") -set(ORTHANC_FRAMEWORK_ROOT "" CACHE STRING "Path to the Orthanc source directory, if ORTHANC_FRAMEWORK_SOURCE is \"path\"") - - -##################################################################### -## Configuration of the Stone framework -##################################################################### - -include(${CMAKE_SOURCE_DIR}/../../Resources/CMake/OrthancStoneParameters.cmake) -include(${ORTHANC_ROOT}/Resources/CMake/DownloadPackage.cmake) - -DownloadPackage( - "a24b8136b8f3bb93f166baf97d9328de" - "http://orthanc.osimis.io/ThirdPartyDownloads/ubuntu-font-family-0.83.zip" - "${CMAKE_BINARY_DIR}/ubuntu-font-family-0.83") - -set(ORTHANC_STONE_APPLICATION_RESOURCES - UBUNTU_FONT ${CMAKE_BINARY_DIR}/ubuntu-font-family-0.83/Ubuntu-R.ttf - ) - -SET(ENABLE_GOOGLE_TEST OFF) -SET(ENABLE_LOCALE ON) -SET(ORTHANC_SANDBOXED ON) -SET(ENABLE_WASM ON) - -include(${CMAKE_SOURCE_DIR}/../../Resources/CMake/OrthancStoneConfiguration.cmake) - -add_definitions( - -DORTHANC_ENABLE_LOGGING_PLUGIN=0 - ) - - -##################################################################### -## Build the samples -##################################################################### - -add_library(OrthancStone STATIC - ${ORTHANC_STONE_SOURCES} - ) - - -if (ON) - add_executable(BasicScene - BasicScene.cpp - #${CMAKE_CURRENT_LIST_DIR}/../Shared/SharedBasicScene.h - ${CMAKE_CURRENT_LIST_DIR}/../Shared/SharedBasicScene.cpp - ) - - target_link_libraries(BasicScene OrthancStone) - - install( - TARGETS BasicScene - RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX} - ) -endif() - - -if (ON) - add_executable(BasicMPR - BasicMPR.cpp - ) - - target_link_libraries(BasicMPR OrthancStone) - - install( - TARGETS BasicMPR - RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX} - ) -endif() - - -install( - FILES - ${CMAKE_CURRENT_BINARY_DIR}/BasicMPR.wasm - ${CMAKE_CURRENT_BINARY_DIR}/BasicScene.wasm - ${CMAKE_SOURCE_DIR}/BasicMPR.html - ${CMAKE_SOURCE_DIR}/BasicScene.html - ${CMAKE_SOURCE_DIR}/Configuration.json - ${CMAKE_SOURCE_DIR}/app.js - ${CMAKE_SOURCE_DIR}/index.html - DESTINATION ${CMAKE_INSTALL_PREFIX} - )
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/WebAssembly/Configuration.json Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -{ - "Plugins": [ - "/usr/local/share/orthanc/plugins/libOrthancWebViewer.so", - "/usr/local/share/orthanc/plugins/libServeFolders.so" - ], - "StorageDirectory" : "/var/lib/orthanc/db", - "IndexDirectory" : "/var/lib/orthanc/db", - "RemoteAccessAllowed" : true, - "AuthenticationEnabled" : false, - "ServeFolders" : { - "AllowCache" : false, - "GenerateETag" : true, - "Folders" : { - "/stone" : "/root/stone" - } - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/WebAssembly/ConfigurationLocalSJO.json Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -{ - "Plugins": [ - "/home/jodogne/Subversion/orthanc-webviewer/r/libOrthancWebViewer.so", - "/home/jodogne/Subversion/orthanc/r/libServeFolders.so" - ], - "StorageDirectory" : "/tmp/orthanc-db", - "IndexDirectory" : "/tmp/orthanc-db", - "RemoteAccessAllowed" : true, - "AuthenticationEnabled" : false, - "ServeFolders" : { - "AllowCache" : false, - "GenerateETag" : true, - "Folders" : { - "/stone" : "/tmp/stone" - } - }, - "WebViewer" : { - "CachePath" : "/tmp/orthanc-db/WebViewerCache" - } -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/WebAssembly/NOTES.txt Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -Docker SJO -========== - -$ source ~/Downloads/emsdk/emsdk_env.sh -$ cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=${EMSCRIPTEN}/cmake/Modules/Platform/Emscripten.cmake -DCMAKE_BUILD_TYPE=Release -DALLOW_DOWNLOADS=ON .. -DCMAKE_INSTALL_PREFIX=/tmp/stone -$ ninja install -$ docker run -p 4242:4242 -p 8042:8042 --rm -v /tmp/stone:/root/stone:ro -v /tmp/stone-db/:/var/lib/orthanc/db/ jodogne/orthanc-plugins:latest /root/stone/Configuration.json --verbose - -WARNING: This won't work using "orthanc-plugins:1.5.6", as support for -PAM is mandatatory in "/instances/.../image-uint16". - - -Docker BGO -========== - -On Ubuntu WSL -------------- -. ~/apps/emsdk/emsdk_env.sh -cd /mnt/c/osi/dev/ -mkdir -p build_stone_newsamples_wasm_wsl -mkdir -p build_install_stone_newsamples_wasm_wsl -cd build_stone_newsamples_wasm_wsl -cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=${EMSCRIPTEN}/cmake/Modules/Platform/Emscripten.cmake -DCMAKE_BUILD_TYPE=Release -DALLOW_DOWNLOADS=ON /mnt/c/osi/dev/orthanc-stone/OrthancStone/Samples/WebAssembly -DCMAKE_INSTALL_PREFIX=/mnt/c/osi/dev/build_install_stone_newsamples_wasm_wsl -ninja install - -Then, on Windows ------------------ -docker run -p 4242:4242 -p 8042:8042 --rm -v "C:/osi/dev/build_install_stone_newsamples_wasm_wsl:/root/stone:ro" jodogne/orthanc-plugins:1.5.6 /root/stone/Configuration.json --verbose - -# WAIT A COUPLE OF SECS -# if the archive has NOT already been unzipped, unzip it -# upload dicom files to running orthanc - -cd C:\osi\dev\twiga-orthanc-viewer\demo\dicomfiles -if (-not (test-path RTVIEWER-c8febcc6-eb9e22a4-130f208c-e0a6a4cd-4d432c57)) { unzip RTVIEWER-c8febcc6-eb9e22a4-130f208c-e0a6a4cd-4d432c57.zip} -ImportDicomFiles.ps1 127.0.0.1 8042 .\RTVIEWER-c8febcc6-eb9e22a4-130f208c-e0a6a4cd-4d432c57\ - ---> localhost:8042 --> Plugins --> serve-folders --> stone --> ... - -Local BGO -========== - -. ~/apps/emsdk/emsdk_env.sh -cd /mnt/c/osi/dev/ -mkdir -p build_stone_newsamples_wasm_wsl -mkdir -p build_install_stone_newsamples_wasm_wsl -cd build_stone_newsamples_wasm_wsl -cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=${EMSCRIPTEN}/cmake/Modules/Platform/Emscripten.cmake -DCMAKE_BUILD_TYPE=Release -DALLOW_DOWNLOADS=ON /mnt/c/osi/dev/orthanc-stone/OrthancStone/Samples/WebAssembly -DCMAKE_INSTALL_PREFIX=/mnt/c/osi/dev/build_install_stone_newsamples_wasm_wsl - - - -TODO: Orthanc.exe - - -Local SJO -========== - -$ source ~/Downloads/emsdk/emsdk_env.sh -$ cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=${EMSCRIPTEN}/cmake/Modules/Platform/Emscripten.cmake -DCMAKE_BUILD_TYPE=Release -DALLOW_DOWNLOADS=ON .. -DCMAKE_INSTALL_PREFIX=/tmp/stone -$ ninja install - -$ make -C ~/Subversion/orthanc/r -j4 -$ make -C ~/Subversion/orthanc-webviewer/r -j4 -$ ~/Subversion/orthanc/r/Orthanc ../ConfigurationLocalSJO.json - - -Local AM -======== - -. ~/apps/emsdk/emsdk_env.sh -cd /mnt/c/o/ -mkdir -p build_stone_newsamples_wasm_wsl -mkdir -p build_install_stone_newsamples_wasm_wsl -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/OrthancStone/Samples/WebAssembly -DCMAKE_INSTALL_PREFIX=/mnt/c/o/build_install_stone_newsamples_wasm_wsl -ninja
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/WebAssembly/app.js Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -/** - * This is a generic bootstrap code that is shared by all the Stone - * sample applications. - **/ - -// Check support for WebAssembly -if (!('WebAssembly' in window)) { - alert('Sorry, your browser does not support WebAssembly :('); -} else { - - // Wait for the module to be loaded (the event "WebAssemblyLoaded" - // must be emitted by the "main" function) - window.addEventListener('WebAssemblyLoaded', function() { - - // Loop over the GET arguments - var parameters = window.location.search.substr(1); - if (parameters != null && parameters != '') { - var tokens = parameters.split('&'); - for (var i = 0; i < tokens.length; i++) { - var arg = tokens[i].split('='); - if (arg.length == 2) { - - // Send each GET argument to WebAssembly - Module.ccall('SetArgument', null, [ 'string', 'string' ], - [ arg[0], decodeURIComponent(arg[1]) ]); - } - } - } - - // Inform the WebAssembly module that it can start - Module.ccall('Initialize', null, null, null); - }); -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/WebAssembly/dev.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,202 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#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 <Core/OrthancException.h> - -#include <emscripten/html5.h> -#include <boost/make_shared.hpp> - -static const unsigned int FONT_SIZE = 32; - -namespace OrthancStone -{ - class ActiveTracker : public boost::noncopyable - { - private: - boost::shared_ptr<IFlexiblePointerTracker> tracker_; - std::string canvasIdentifier_; - bool insideCanvas_; - - public: - ActiveTracker(const boost::shared_ptr<IFlexiblePointerTracker>& tracker, - const std::string& canvasId) : - tracker_(tracker), - canvasIdentifier_(canvasId), - insideCanvas_(true) - { - if (tracker_.get() == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); - } - } - - bool IsAlive() const - { - return tracker_->IsAlive(); - } - - void PointerMove(const PointerEvent& event) - { - tracker_->PointerMove(event); - } - - void PointerUp(const PointerEvent& event) - { - tracker_->PointerUp(event); - } - }; -} - -static OrthancStone::PointerEvent* ConvertMouseEvent( - const EmscriptenMouseEvent& source, - OrthancStone::IViewport& viewport) -{ - std::unique_ptr<OrthancStone::PointerEvent> target( - new OrthancStone::PointerEvent); - - target->AddPosition(viewport.GetPixelCenterCoordinates( - source.targetX, source.targetY)); - target->SetAltModifier(source.altKey); - target->SetControlModifier(source.ctrlKey); - target->SetShiftModifier(source.shiftKey); - - return target.release(); -} - -std::unique_ptr<OrthancStone::ActiveTracker> tracker_; - -EM_BOOL OnMouseEvent(int eventType, - const EmscriptenMouseEvent *mouseEvent, - void *userData) -{ - if (mouseEvent != NULL && - userData != NULL) - { - boost::shared_ptr<OrthancStone::ViewportController>& controller = - *reinterpret_cast<boost::shared_ptr<OrthancStone::ViewportController>*>(userData); - - switch (eventType) - { - case EMSCRIPTEN_EVENT_CLICK: - { - static unsigned int count = 0; - char buf[64]; - sprintf(buf, "click %d", count++); - - std::unique_ptr<OrthancStone::TextSceneLayer> layer(new OrthancStone::TextSceneLayer); - layer->SetText(buf); - controller->GetViewport().GetScene().SetLayer(100, layer.release()); - controller->GetViewport().Refresh(); - break; - } - - case EMSCRIPTEN_EVENT_MOUSEDOWN: - { - boost::shared_ptr<OrthancStone::IFlexiblePointerTracker> t; - - { - std::unique_ptr<OrthancStone::PointerEvent> event( - ConvertMouseEvent(*mouseEvent, controller->GetViewport())); - - switch (mouseEvent->button) - { - case 0: // Left button - emscripten_console_log("Creating RotateSceneTracker"); - t.reset(new OrthancStone::RotateSceneTracker( - controller, *event)); - break; - - case 1: // Middle button - emscripten_console_log("Creating PanSceneTracker"); - LOG(INFO) << "Creating PanSceneTracker" ; - t.reset(new OrthancStone::PanSceneTracker( - controller, *event)); - break; - - case 2: // Right button - emscripten_console_log("Creating ZoomSceneTracker"); - t.reset(new OrthancStone::ZoomSceneTracker( - controller, *event, controller->GetViewport().GetCanvasWidth())); - break; - - default: - break; - } - } - - if (t.get() != NULL) - { - tracker_.reset( - new OrthancStone::ActiveTracker(t, controller->GetViewport().GetCanvasIdentifier())); - controller->GetViewport().Refresh(); - } - - break; - } - - case EMSCRIPTEN_EVENT_MOUSEMOVE: - if (tracker_.get() != NULL) - { - std::unique_ptr<OrthancStone::PointerEvent> event( - ConvertMouseEvent(*mouseEvent, controller->GetViewport())); - tracker_->PointerMove(*event); - controller->GetViewport().Refresh(); - } - break; - - case EMSCRIPTEN_EVENT_MOUSEUP: - if (tracker_.get() != NULL) - { - std::unique_ptr<OrthancStone::PointerEvent> event( - ConvertMouseEvent(*mouseEvent, controller->GetViewport())); - tracker_->PointerUp(*event); - controller->GetViewport().Refresh(); - if (!tracker_->IsAlive()) - tracker_.reset(); - } - break; - - default: - break; - } - } - - return true; -} - - -void SetupEvents(const std::string& canvas, - boost::shared_ptr<OrthancStone::ViewportController>& controller) -{ - 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); -}
--- a/OrthancStone/Resources/Graveyard/Deprecated/Samples/WebAssembly/index.html Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -<!doctype html> -<html lang="en-us"> - <head> - <meta charset="utf-8"> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> - - <title>Stone of Orthanc</title> - </head> - <body> - <h1>Available samples</h1> - <ul> - <li><a href="BasicScene.html">Basic scene</a></li> - <li><a href="BasicMPR.html">Basic MPR display</a></li> - </ul> - </body> -</html>
--- a/OrthancStone/Sources/Deprecated/GuiAdapter.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1139 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#include "GuiAdapter.h" - -#if ORTHANC_ENABLE_OPENGL == 1 -# include "../OpenGL/OpenGLIncludes.h" -#endif - -#if ORTHANC_ENABLE_SDL == 1 -# include <SDL_video.h> -# include <SDL_render.h> -# include <SDL.h> -#endif - -#include <Compatibility.h> - -namespace OrthancStone -{ - std::ostream& operator<<( - std::ostream& os, const GuiAdapterKeyboardEvent& event) - { - os << "sym: " << event.sym << " (" << (int)(event.sym[0]) << ") ctrl: " << event.ctrlKey << ", " << - "shift: " << event.shiftKey << ", " << - "alt: " << event.altKey; - return os; - } - - std::ostream& operator<<( - std::ostream& os, const GuiAdapterMouseEvent& event) - { - os << "targetX: " << event.targetX << " targetY: " << event.targetY << " button: " << event.button - << "ctrlKey: " << event.ctrlKey << "shiftKey: " << event.shiftKey << "altKey: " << event.altKey; - - return os; - } - - int GuiAdapter::s_instanceCount = 0; - -#if ORTHANC_ENABLE_WASM == 1 - void GuiAdapter::Run(GuiAdapterRunFunc /*func*/, void* /*cookie*/) - { - } - - void ConvertFromPlatform( - GuiAdapterUiEvent& dest, - int eventType, - const EmscriptenUiEvent& src) - { - // no data for now - } - - void ConvertFromPlatform( - GuiAdapterMouseEvent& dest, - int eventType, - const EmscriptenMouseEvent& src) - { - memset(&dest, 0, sizeof(GuiAdapterMouseEvent)); - switch (eventType) - { - case EMSCRIPTEN_EVENT_CLICK: - LOG(ERROR) << "Emscripten EMSCRIPTEN_EVENT_CLICK is not supported"; - ORTHANC_ASSERT(false, "Not supported"); - break; - case EMSCRIPTEN_EVENT_MOUSEDOWN: - dest.type = GUIADAPTER_EVENT_MOUSEDOWN; - break; - case EMSCRIPTEN_EVENT_DBLCLICK: - dest.type = GUIADAPTER_EVENT_MOUSEDBLCLICK; - break; - case EMSCRIPTEN_EVENT_MOUSEMOVE: - dest.type = GUIADAPTER_EVENT_MOUSEMOVE; - break; - case EMSCRIPTEN_EVENT_MOUSEUP: - dest.type = GUIADAPTER_EVENT_MOUSEUP; - break; - case EMSCRIPTEN_EVENT_WHEEL: - dest.type = GUIADAPTER_EVENT_WHEEL; - break; - - default: - LOG(ERROR) << "Emscripten event: " << eventType << " is not supported"; - ORTHANC_ASSERT(false, "Not supported"); - } - //dest.timestamp = src.timestamp; - //dest.screenX = src.screenX; - //dest.screenY = src.screenY; - //dest.clientX = src.clientX; - //dest.clientY = src.clientY; - dest.ctrlKey = src.ctrlKey; - dest.shiftKey = src.shiftKey; - dest.altKey = src.altKey; - //dest.metaKey = src.metaKey; - dest.button = src.button; - //dest.buttons = src.buttons; - //dest.movementX = src.movementX; - //dest.movementY = src.movementY; - dest.targetX = src.targetX; - dest.targetY = src.targetY; - //dest.canvasX = src.canvasX; - //dest.canvasY = src.canvasY; - //dest.padding = src.padding; - } - - void ConvertFromPlatform( GuiAdapterWheelEvent& dest, int eventType, const EmscriptenWheelEvent& src) - { - ConvertFromPlatform(dest.mouse, eventType, src.mouse); - dest.deltaX = src.deltaX; - dest.deltaY = src.deltaY; - switch (src.deltaMode) - { - case DOM_DELTA_PIXEL: - dest.deltaMode = GUIADAPTER_DELTA_PIXEL; - break; - case DOM_DELTA_LINE: - dest.deltaMode = GUIADAPTER_DELTA_LINE; - break; - case DOM_DELTA_PAGE: - dest.deltaMode = GUIADAPTER_DELTA_PAGE; - break; - default: - ORTHANC_ASSERT(false, "Unknown deltaMode: " << src.deltaMode << - " in wheel event..."); - } - dest.deltaMode = src.deltaMode; - } - - void ConvertFromPlatform(GuiAdapterKeyboardEvent& dest, const EmscriptenKeyboardEvent& src) - { - dest.sym[0] = src.key[0]; - dest.sym[1] = 0; - dest.ctrlKey = src.ctrlKey; - dest.shiftKey = src.shiftKey; - dest.altKey = src.altKey; - } - - template<typename GenericFunc> - struct FuncAdapterPayload - { - std::string canvasCssSelector; - void* userData; - GenericFunc callback; - }; - - template<typename GenericFunc, - typename GuiAdapterEvent, - typename EmscriptenEvent> - EM_BOOL OnEventAdapterFunc( - int eventType, const EmscriptenEvent* emEvent, void* userData) - { - // userData is OnMouseWheelFuncAdapterPayload - FuncAdapterPayload<GenericFunc>* payload = - reinterpret_cast<FuncAdapterPayload<GenericFunc>*>(userData); - // LOG(INFO) << "OnEventAdapterFunc"; - // LOG(INFO) << "------------------"; - // LOG(INFO) << "eventType: " << eventType << " wheelEvent: " << - // (int)wheelEvent << " userData: " << userData << - // " payload->userData: " << payload->userData; - - GuiAdapterEvent guiEvent; - ConvertFromPlatform(guiEvent, eventType, *emEvent); - bool ret = (*(payload->callback))(payload->canvasCssSelector, &guiEvent, payload->userData); - return static_cast<EM_BOOL>(ret); - } - - template<typename GenericFunc, - typename GuiAdapterEvent, - typename EmscriptenEvent> - EM_BOOL OnEventAdapterFunc2( - int /*eventType*/, const EmscriptenEvent* wheelEvent, void* userData) - { - // userData is OnMouseWheelFuncAdapterPayload - FuncAdapterPayload<GenericFunc>* payload = - reinterpret_cast<FuncAdapterPayload<GenericFunc>*>(userData); - - GuiAdapterEvent guiEvent; - ConvertFromPlatform(guiEvent, *wheelEvent); - bool ret = (*(payload->callback))(payload->canvasCssSelector, &guiEvent, payload->userData); - return static_cast<EM_BOOL>(ret); - } - - template<typename GenericFunc> - EM_BOOL OnEventAdapterFunc3( - double time, void* userData) - { - // userData is OnMouseWheelFuncAdapterPayload - FuncAdapterPayload<GenericFunc>* payload = - reinterpret_cast<FuncAdapterPayload<GenericFunc>*>(userData); - //std::unique_ptr< FuncAdapterPayload<GenericFunc> > deleter(payload); - bool ret = (*(payload->callback))(time, payload->userData); - return static_cast<EM_BOOL>(ret); - } - - /* - - Explanation - =========== - - - in "older" Emscripten, where DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR doesn't exist or is set to 0, - the following strings need to be used to register events: - - for canvas, the canvas DOM id. In case of <canvas id="mycanvas1" width='640' ...></canvas>", the string needs - to be "mycanvas" - - for the window (for key events), the string needs to be "#window" - - in newer Emscripten where DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR==1 (or maybe is not there anymore, in the - future as of 2020-04-20) - - for canvas, the canvas DOM id. In case of <canvas id="mycanvas1" width='640' ...></canvas>", the string needs - to be "#mycanvas" (notice the "number sign", aka "hash", NOT AKA "sharp", as can be read on https://en.wikipedia.org/wiki/Number_sign) - - for the window (for key events), the string needs to be EMSCRIPTEN_EVENT_TARGET_WINDOW. I do not mean - "EMSCRIPTEN_EVENT_TARGET_WINDOW", but the #define EMSCRIPTEN_EVENT_TARGET_WINDOW ((const char*)2) that - can be found in emscripten/html5.h - - The code below converts the input canvasId (as in the old emscripten) to the emscripten-compliant one, with the - following compile condition : #if DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR == 1 - - If the DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR build parameter disappears, you might want to refactor this code - or continue to pass the DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR compile macro (which is different from the CMake - variable) - - What we are doing below: - - in older Emscripten, the registration functions will receive "mycanvas" and "#window" and the callbacks will receive - the same std::string in their payload ("mycanvas" and "#window") - - - in newer Emscripten, the registration functions will receive "#mycanvas" and EMSCRIPTEN_EVENT_TARGET_WINDOW, but - the callbacks will receive "#mycanvas" and "#window" (since it is not possible to store the EMSCRIPTEN_EVENT_TARGET_WINDOW - magic value in an std::string, while we still want the callback to be able to change its behavior according to the - target element. - - */ - - void convertElementTarget(const char*& outCanvasCssSelectorSz, std::string& outCanvasCssSelector, const std::string& canvasId) - { - // only "#window" can start with a # - if (canvasId[0] == '#') - { - ORTHANC_ASSERT(canvasId == "#window"); - } -#if DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR == 1 - if (canvasId == "#window") - { - // we store this in the payload so that the callback can - outCanvasCssSelector = "#window"; - outCanvasCssSelectorSz = EMSCRIPTEN_EVENT_TARGET_WINDOW; - } - else - { - outCanvasCssSelector = "#" + canvasId; - outCanvasCssSelectorSz = outCanvasCssSelector.c_str(); - } -#else - if (canvasId == "#window") - { - // we store this in the payload so that the callback can - outCanvasCssSelector = "#window"; - outCanvasCssSelectorSz = outCanvasCssSelector.c_str();; - } - else - { - outCanvasCssSelector = canvasId; - outCanvasCssSelectorSz = outCanvasCssSelector.c_str();; - } -#endif - } - - // resize: (const char* target, void* userData, EM_BOOL useCapture, em_ui_callback_func callback) - template< - typename GenericFunc, - typename GuiAdapterEvent, - typename EmscriptenEvent, - typename EmscriptenSetCallbackFunc> - static void SetCallback( - EmscriptenSetCallbackFunc emFunc, - std::string canvasId, void* userData, bool capture, GenericFunc func) - { - std::string canvasCssSelector; - const char* canvasCssSelectorSz = NULL; - convertElementTarget(canvasCssSelectorSz, canvasCssSelector, canvasId); - - // TODO: write RemoveCallback with an int id that gets returned from here - - // create userdata payload - std::unique_ptr<FuncAdapterPayload<GenericFunc> > payload(new FuncAdapterPayload<GenericFunc>()); - payload->canvasCssSelector = canvasCssSelector; - payload->callback = func; - payload->userData = userData; - void* userDataRaw = reinterpret_cast<void*>(payload.release()); - - // call the registration function - (*emFunc)( - canvasCssSelectorSz, - userDataRaw, - static_cast<EM_BOOL>(capture), - &OnEventAdapterFunc<GenericFunc, GuiAdapterEvent, EmscriptenEvent>, - EM_CALLBACK_THREAD_CONTEXT_CALLING_THREAD); - } - - template< - typename GenericFunc, - typename GuiAdapterEvent, - typename EmscriptenEvent, - typename EmscriptenSetCallbackFunc> - static void SetCallback2( - EmscriptenSetCallbackFunc emFunc, - std::string canvasId, void* userData, bool capture, GenericFunc func) - { - std::string canvasCssSelector; - const char* canvasCssSelectorSz = NULL; - convertElementTarget(canvasCssSelectorSz, canvasCssSelector, canvasId); - - // TODO: write RemoveCallback with an int id that gets returned from here - - // create userdata payload - std::unique_ptr<FuncAdapterPayload<GenericFunc> > payload(new FuncAdapterPayload<GenericFunc>()); - payload->canvasCssSelector = canvasCssSelector; - payload->callback = func; - payload->userData = userData; - void* userDataRaw = reinterpret_cast<void*>(payload.release()); - - // call the registration function - (*emFunc)( - canvasCssSelectorSz, - userDataRaw, - static_cast<EM_BOOL>(capture), - &OnEventAdapterFunc2<GenericFunc, GuiAdapterEvent, EmscriptenEvent>, - EM_CALLBACK_THREAD_CONTEXT_CALLING_THREAD); - } - - template< - typename GenericFunc, - typename EmscriptenSetCallbackFunc> - static void SetAnimationFrameCallback( - EmscriptenSetCallbackFunc emFunc, - void* userData, GenericFunc func) - { - std::unique_ptr<FuncAdapterPayload<GenericFunc> > payload( - new FuncAdapterPayload<GenericFunc>() - ); - payload->canvasCssSelector = "UNDEFINED"; - payload->callback = func; - payload->userData = userData; - void* userDataRaw = reinterpret_cast<void*>(payload.release()); - (*emFunc)( - &OnEventAdapterFunc3<GenericFunc>, - userDataRaw); - } - - void GuiAdapter::SetWheelCallback( - std::string canvasId, void* userData, bool capture, OnMouseWheelFunc func) - { - SetCallback<OnMouseWheelFunc, GuiAdapterWheelEvent, EmscriptenWheelEvent>( - &emscripten_set_wheel_callback_on_thread, - canvasId, - userData, - capture, - func); - } - - - void GuiAdapter::SetMouseDblClickCallback( - std::string canvasId, void* userData, bool capture, OnMouseEventFunc func) - { - SetCallback<OnMouseEventFunc, GuiAdapterMouseEvent, EmscriptenMouseEvent>( - &emscripten_set_dblclick_callback_on_thread, - canvasId, - userData, - capture, - func); - } - - - void GuiAdapter::SetMouseDownCallback( - std::string canvasId, void* userData, bool capture, OnMouseEventFunc func) - { - SetCallback<OnMouseEventFunc, GuiAdapterMouseEvent, EmscriptenMouseEvent>( - &emscripten_set_mousedown_callback_on_thread, - canvasId, - userData, - capture, - func); - } - - void GuiAdapter::SetMouseMoveCallback( - std::string canvasId, void* userData, bool capture, OnMouseEventFunc func) - { - // LOG(INFO) << "SetMouseMoveCallback -- " << "supplied userData: " << - // userData; - - SetCallback<OnMouseEventFunc, GuiAdapterMouseEvent, EmscriptenMouseEvent>( - &emscripten_set_mousemove_callback_on_thread, - canvasId, - userData, - capture, - func); - } - - void GuiAdapter::SetMouseUpCallback( - std::string canvasId, void* userData, bool capture, OnMouseEventFunc func) - { - SetCallback<OnMouseEventFunc, GuiAdapterMouseEvent, EmscriptenMouseEvent>( - &emscripten_set_mouseup_callback_on_thread, - canvasId, - userData, - capture, - func); - } - - void GuiAdapter::SetKeyDownCallback( - std::string canvasId, void* userData, bool capture, OnKeyDownFunc func) - { - SetCallback2<OnKeyDownFunc, GuiAdapterKeyboardEvent, EmscriptenKeyboardEvent>( - &emscripten_set_keydown_callback_on_thread, - canvasId, - userData, - capture, - func); - } - - void GuiAdapter::SetKeyUpCallback( - std::string canvasId, void* userData, bool capture, OnKeyUpFunc func) - { - SetCallback2<OnKeyUpFunc, GuiAdapterKeyboardEvent, EmscriptenKeyboardEvent>( - &emscripten_set_keyup_callback_on_thread, - canvasId, - userData, - capture, - func); - } - -#if 0 - // useless under Wasm where canvas resize is handled automatically - void GuiAdapter::SetResizeCallback( - std::string canvasId, void* userData, bool capture, OnWindowResizeFunc func) - { - SetCallback<OnWindowResizeFunc, GuiAdapterUiEvent, EmscriptenUiEvent>( - &emscripten_set_resize_callback_on_thread, - canvasId, - userData, - capture, - func); - } -#endif - - void GuiAdapter::RequestAnimationFrame( - OnAnimationFrameFunc func, void* userData) - { - SetAnimationFrameCallback<OnAnimationFrameFunc>( - &emscripten_request_animation_frame_loop, - userData, - func); - } - -#if 0 - void GuiAdapter::SetKeyDownCallback( - std::string canvasId, void* userData, bool capture, OnKeyDownFunc func) - { - emscripten_set_keydown_callback(canvasId.c_str(), userData, static_cast<EM_BOOL>(capture), func); - } - void GuiAdapter::SetKeyUpCallback( - std::string canvasId, void* userData, bool capture, OnKeyUpFunc func) - { - emscripten_set_keyup_callback(canvasId.c_str(), userData, static_cast<EM_BOOL>(capture), func); - } - - // handled from within WebAssemblyViewport - //void GuiAdapter::SetResizeCallback(std::string canvasId, void* userData, bool capture, OnWindowResizeFunc func) - //{ - // emscripten_set_resize_callback(canvasId.c_str(), userData, static_cast<EM_BOOL>(capture), func); - //} - - void GuiAdapter::RequestAnimationFrame(OnAnimationFrameFunc func, void* userData) - { - emscripten_request_animation_frame_loop(func, userData); - } -#endif - - -#else - - // SDL ONLY - void ConvertFromPlatform(GuiAdapterMouseEvent& dest, bool ctrlPressed, bool shiftPressed, bool altPressed, const SDL_Event& source) - { - memset(&dest, 0, sizeof(GuiAdapterMouseEvent)); - switch (source.type) - { - case SDL_MOUSEBUTTONDOWN: - if (source.button.clicks == 1) { - dest.type = GUIADAPTER_EVENT_MOUSEDOWN; - } else if (source.button.clicks == 2) { - dest.type = GUIADAPTER_EVENT_MOUSEDBLCLICK; - } else { - dest.type = GUIADAPTER_EVENT_MOUSEDBLCLICK; - LOG(WARNING) << "Multiple-click ignored."; - } - break; - case SDL_MOUSEMOTION: - dest.type = GUIADAPTER_EVENT_MOUSEMOVE; - break; - case SDL_MOUSEBUTTONUP: - dest.type = GUIADAPTER_EVENT_MOUSEUP; - break; - case SDL_MOUSEWHEEL: - dest.type = GUIADAPTER_EVENT_WHEEL; - break; - default: - LOG(ERROR) << "SDL event: " << source.type << " is not supported"; - ORTHANC_ASSERT(false, "Not supported"); - } - //dest.timestamp = src.timestamp; - //dest.screenX = src.screenX; - //dest.screenY = src.screenY; - //dest.clientX = src.clientX; - //dest.clientY = src.clientY; - dest.ctrlKey = ctrlPressed; - dest.shiftKey = shiftPressed; - dest.altKey = altPressed; - //dest.metaKey = src.metaKey; - switch (source.button.button) - { - case SDL_BUTTON_MIDDLE: - dest.button =GUIADAPTER_MOUSEBUTTON_MIDDLE; - break; - - case SDL_BUTTON_RIGHT: - dest.button = GUIADAPTER_MOUSEBUTTON_RIGHT; - break; - - case SDL_BUTTON_LEFT: - dest.button = GUIADAPTER_MOUSEBUTTON_LEFT; - break; - - default: - break; - } - //dest.buttons = src.buttons; - //dest.movementX = src.movementX; - //dest.movementY = src.movementY; - dest.targetX = source.button.x; - dest.targetY = source.button.y; - //dest.canvasX = src.canvasX; - //dest.canvasY = src.canvasY; - //dest.padding = src.padding; - } - - void ConvertFromPlatform( - GuiAdapterWheelEvent& dest, - bool ctrlPressed, bool shiftPressed, bool altPressed, - const SDL_Event& source) - { - ConvertFromPlatform(dest.mouse, ctrlPressed, shiftPressed, altPressed, source); - dest.deltaX = source.wheel.x; - dest.deltaY = source.wheel.y; - } - - void ConvertFromPlatform(GuiAdapterKeyboardEvent& dest, const SDL_Event& src) - { - memset(&dest, 0, sizeof(GuiAdapterMouseEvent)); - switch (src.type) - { - case SDL_KEYDOWN: - dest.type = GUIADAPTER_EVENT_KEYDOWN; - break; - case SDL_KEYUP: - dest.type = GUIADAPTER_EVENT_KEYUP; - break; - default: - LOG(ERROR) << "SDL event: " << src.type << " is not supported"; - ORTHANC_ASSERT(false, "Not supported"); - } - dest.sym[0] = src.key.keysym.sym; - dest.sym[1] = 0; - - if (src.key.keysym.mod & KMOD_CTRL) - dest.ctrlKey = true; - else - dest.ctrlKey = false; - - if (src.key.keysym.mod & KMOD_SHIFT) - dest.shiftKey = true; - else - dest.shiftKey = false; - - if (src.key.keysym.mod & KMOD_ALT) - dest.altKey = true; - else - dest.altKey = false; - } - - // SDL ONLY - void GuiAdapter::SetSdlResizeCallback( - std::string canvasId, void* userData, bool capture, OnSdlWindowResizeFunc func) - { - resizeHandlers_.push_back(EventHandlerData<OnSdlWindowResizeFunc>(canvasId, func, userData)); - } - - // SDL ONLY - void GuiAdapter::SetMouseDownCallback( - std::string canvasId, void* userData, bool capture, OnMouseEventFunc func) - { - mouseDownHandlers_.push_back(EventHandlerData<OnMouseEventFunc>(canvasId, func, userData)); - } - - // SDL ONLY - void GuiAdapter::SetMouseDblClickCallback( - std::string canvasId, void* userData, bool capture, OnMouseEventFunc func) - { - mouseDblCickHandlers_.push_back(EventHandlerData<OnMouseEventFunc>(canvasId, func, userData)); - } - - // SDL ONLY - void GuiAdapter::SetMouseMoveCallback( - std::string canvasId, void* userData, bool capture, OnMouseEventFunc func) - { - mouseMoveHandlers_.push_back(EventHandlerData<OnMouseEventFunc>(canvasId, func, userData)); - } - - // SDL ONLY - void GuiAdapter::SetMouseUpCallback( - std::string canvasId, void* userData, bool capture, OnMouseEventFunc func) - { - mouseUpHandlers_.push_back(EventHandlerData<OnMouseEventFunc>(canvasId, func, userData)); - } - - // SDL ONLY - void GuiAdapter::SetWheelCallback( - std::string canvasId, void* userData, bool capture, OnMouseWheelFunc func) - { - mouseWheelHandlers_.push_back(EventHandlerData<OnMouseWheelFunc>(canvasId, func, userData)); - } - - // SDL ONLY - void GuiAdapter::SetKeyDownCallback( - std::string canvasId, void* userData, bool capture, OnKeyDownFunc func) - { - keyDownHandlers_.push_back(EventHandlerData<OnKeyDownFunc>(canvasId, func, userData)); - } - - // SDL ONLY - void GuiAdapter::SetKeyUpCallback( - std::string canvasId, void* userData, bool capture, OnKeyUpFunc func) - { - keyUpHandlers_.push_back(EventHandlerData<OnKeyUpFunc>(canvasId, func, userData)); - } - - // SDL ONLY - void GuiAdapter::SetGenericSdlEventCallback( - std::string canvasId, void* userData, bool capture, OnSdlEventCallback func) - { - sdlEventHandlers_.push_back(EventHandlerData<OnSdlEventCallback>(canvasId, func, userData)); - } - - // SDL ONLY - void GuiAdapter::OnAnimationFrame() - { - std::vector<size_t> disabledAnimationHandlers; - for (size_t i = 0; i < animationFrameHandlers_.size(); i++) - { - // TODO: fix time - bool goOn = (*(animationFrameHandlers_[i].first))(0, animationFrameHandlers_[i].second); - - // If the function returns false, we need to emulate what happens in Web - // and remove the function from the handlers... - if (!goOn) - disabledAnimationHandlers.push_back(i); - } - for (size_t i = 0; i < disabledAnimationHandlers.size(); i++) - { - ORTHANC_ASSERT(animationFrameHandlers_.begin() + disabledAnimationHandlers[i] < animationFrameHandlers_.end()); - animationFrameHandlers_.erase(animationFrameHandlers_.begin() + disabledAnimationHandlers[i]); - } - } - - // SDL ONLY - void GuiAdapter::OnResize(unsigned int width, unsigned int height) - { - for (size_t i = 0; i < resizeHandlers_.size(); i++) - { - (*(resizeHandlers_[i].func))( - resizeHandlers_[i].canvasName, NULL, width, height, resizeHandlers_[i].userData); - } - } - - - - void GuiAdapter::OnSdlGenericEvent(const SDL_Event& sdlEvent) - { - // Events related to a window are only sent to the related canvas - // User events are sent to everyone (we can't filter them here) - - /* - SDL_WindowEvent SDL_WINDOWEVENT - SDL_KeyboardEvent SDL_KEYDOWN - SDL_KEYUP - SDL_TextEditingEvent SDL_TEXTEDITING - SDL_TextInputEvent SDL_TEXTINPUT - SDL_MouseMotionEvent SDL_MOUSEMOTION - SDL_MouseButtonEvent SDL_MOUSEBUTTONDOWN - SDL_MOUSEBUTTONUP - SDL_MouseWheelEvent SDL_MOUSEWHEEL - SDL_UserEvent SDL_USEREVENT through ::SDL_LASTEVENT-1 - */ - - // if this string is left empty, it means the message will be sent to - // all widgets. - // otherwise, it contains the originating message window title - - std::string windowTitle; - uint32_t windowId = 0; - - if (sdlEvent.type == SDL_WINDOWEVENT) - windowId = sdlEvent.window.windowID; - else if (sdlEvent.type == SDL_KEYDOWN || sdlEvent.type == SDL_KEYUP) - windowId = sdlEvent.key.windowID; - else if (sdlEvent.type == SDL_TEXTEDITING) - windowId = sdlEvent.edit.windowID; - else if (sdlEvent.type == SDL_TEXTINPUT) - windowId = sdlEvent.text.windowID; - else if (sdlEvent.type == SDL_MOUSEMOTION) - windowId = sdlEvent.motion.windowID; - else if (sdlEvent.type == SDL_MOUSEBUTTONDOWN || sdlEvent.type == SDL_MOUSEBUTTONUP) - windowId = sdlEvent.button.windowID; - else if (sdlEvent.type == SDL_MOUSEWHEEL) - windowId = sdlEvent.wheel.windowID; - else if (sdlEvent.type >= SDL_USEREVENT && sdlEvent.type <= (SDL_LASTEVENT-1)) - windowId = sdlEvent.user.windowID; - - if (windowId != 0) - { - SDL_Window* sdlWindow = SDL_GetWindowFromID(windowId); - ORTHANC_ASSERT(sdlWindow != NULL, "Window ID \"" << windowId << "\" is not a valid SDL window ID!"); - const char* windowTitleSz = SDL_GetWindowTitle(sdlWindow); - ORTHANC_ASSERT(windowTitleSz != NULL, "Window ID \"" << windowId << "\" has a NULL window title!"); - windowTitle = windowTitleSz; - ORTHANC_ASSERT(windowTitle != "", "Window ID \"" << windowId << "\" has an empty window title!"); - } - - for (size_t i = 0; i < sdlEventHandlers_.size(); i++) - { - // normally, the handlers return a bool indicating whether they - // have handled the event or not, but we don't really care about this - std::string& canvasName = sdlEventHandlers_[i].canvasName; - - bool sendEvent = true; - - if (windowTitle != "" && (canvasName != windowTitle)) - sendEvent = false; - - if (sendEvent) - { - OnSdlEventCallback func = sdlEventHandlers_[i].func; - (*func)(canvasName, sdlEvent, sdlEventHandlers_[i].userData); - } - } - } - - // SDL ONLY - void GuiAdapter::OnMouseWheelEvent(uint32_t windowID, const GuiAdapterWheelEvent& event) - { - // the SDL window name IS the canvas name ("canvas" is used because this lib - // is designed for Wasm - SDL_Window* sdlWindow = SDL_GetWindowFromID(windowID); - ORTHANC_ASSERT(sdlWindow != NULL, "Window ID \"" << windowID << "\" is not a valid SDL window ID!"); - - const char* windowTitleSz = SDL_GetWindowTitle(sdlWindow); - ORTHANC_ASSERT(windowTitleSz != NULL, "Window ID \"" << windowID << "\" has a NULL window title!"); - - std::string windowTitle(windowTitleSz); - ORTHANC_ASSERT(windowTitle != "", "Window ID \"" << windowID << "\" has an empty window title!"); - - switch (event.mouse.type) - { - case GUIADAPTER_EVENT_WHEEL: - for (size_t i = 0; i < mouseWheelHandlers_.size(); i++) - { - if (mouseWheelHandlers_[i].canvasName == windowTitle) - (*(mouseWheelHandlers_[i].func))(windowTitle, &event, mouseWheelHandlers_[i].userData); - } - break; - default: - ORTHANC_ASSERT(false, "Wrong event.type: " << event.mouse.type << " in GuiAdapter::OnMouseWheelEvent(...)"); - break; - } - } - - - void GuiAdapter::OnKeyboardEvent(uint32_t windowID, const GuiAdapterKeyboardEvent& event) - { - // only one-letter (ascii) keyboard events supported for now - ORTHANC_ASSERT(event.sym[0] != 0); - ORTHANC_ASSERT(event.sym[1] == 0); - - SDL_Window* sdlWindow = SDL_GetWindowFromID(windowID); - ORTHANC_ASSERT(sdlWindow != NULL, "Window ID \"" << windowID << "\" is not a valid SDL window ID!"); - - const char* windowTitleSz = SDL_GetWindowTitle(sdlWindow); - ORTHANC_ASSERT(windowTitleSz != NULL, "Window ID \"" << windowID << "\" has a NULL window title!"); - - std::string windowTitle(windowTitleSz); - ORTHANC_ASSERT(windowTitle != "", "Window ID \"" << windowID << "\" has an empty window title!"); - - switch (event.type) - { - case GUIADAPTER_EVENT_KEYDOWN: - for (size_t i = 0; i < keyDownHandlers_.size(); i++) - { - (*(keyDownHandlers_[i].func))(windowTitle, &event, keyDownHandlers_[i].userData); - } - break; - case GUIADAPTER_EVENT_KEYUP: - for (size_t i = 0; i < keyUpHandlers_.size(); i++) - { - (*(keyUpHandlers_[i].func))(windowTitle, &event, keyUpHandlers_[i].userData); - } - break; - default: - ORTHANC_ASSERT(false, "Wrong event.type: " << event.type << " in GuiAdapter::OnKeyboardEvent(...)"); - break; - } - } - - // SDL ONLY - void GuiAdapter::OnMouseEvent(uint32_t windowID, const GuiAdapterMouseEvent& event) - { - if (windowID == 0) - { - LOG(WARNING) << "GuiAdapter::OnMouseEvent -- windowID == 0 and event won't be routed!"; - } - else - { - // the SDL window name IS the canvas name ("canvas" is used because this lib - // is designed for Wasm - SDL_Window* sdlWindow = SDL_GetWindowFromID(windowID); - - ORTHANC_ASSERT(sdlWindow != NULL, "Window ID \"" << windowID << "\" is not a valid SDL window ID!"); - - const char* windowTitleSz = SDL_GetWindowTitle(sdlWindow); - ORTHANC_ASSERT(windowTitleSz != NULL, "Window ID \"" << windowID << "\" has a NULL window title!"); - - std::string windowTitle(windowTitleSz); - ORTHANC_ASSERT(windowTitle != "", "Window ID \"" << windowID << "\" has an empty window title!"); - - switch (event.type) - { - case GUIADAPTER_EVENT_MOUSEDOWN: - for (size_t i = 0; i < mouseDownHandlers_.size(); i++) - { - if (mouseDownHandlers_[i].canvasName == windowTitle) - (*(mouseDownHandlers_[i].func))(windowTitle, &event, mouseDownHandlers_[i].userData); - } - break; - case GUIADAPTER_EVENT_MOUSEDBLCLICK: - for (size_t i = 0; i < mouseDblCickHandlers_.size(); i++) - { - if (mouseDblCickHandlers_[i].canvasName == windowTitle) - (*(mouseDblCickHandlers_[i].func))(windowTitle, &event, mouseDblCickHandlers_[i].userData); - } - break; - case GUIADAPTER_EVENT_MOUSEMOVE: - for (size_t i = 0; i < mouseMoveHandlers_.size(); i++) - { - if (mouseMoveHandlers_[i].canvasName == windowTitle) - (*(mouseMoveHandlers_[i].func))(windowTitle, &event, mouseMoveHandlers_[i].userData); - } - break; - case GUIADAPTER_EVENT_MOUSEUP: - for (size_t i = 0; i < mouseUpHandlers_.size(); i++) - { - if (mouseUpHandlers_[i].canvasName == windowTitle) - (*(mouseUpHandlers_[i].func))(windowTitle, &event, mouseUpHandlers_[i].userData); - } - break; - default: - ORTHANC_ASSERT(false, "Wrong event.type: " << event.type << " in GuiAdapter::OnMouseEvent(...)"); - break; - } - } - } - - - // extern void Debug_SetContextToBeKilled(std::string title); - // extern void Debug_SetContextToBeRestored(std::string title); - - // SDL ONLY - void GuiAdapter::RequestAnimationFrame(OnAnimationFrameFunc func, void* userData) - { - animationFrameHandlers_.push_back(std::make_pair(func, userData)); - } - -# if ORTHANC_ENABLE_OPENGL == 1 && !defined(__APPLE__) /* OpenGL debug is not available on OS X */ - - // SDL ONLY - static void GLAPIENTRY - OpenGLMessageCallback(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar * message, - const void* userParam) - { - if (severity != GL_DEBUG_SEVERITY_NOTIFICATION) - { - fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", - (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), - type, severity, message); - } - } -# endif - -#if 0 - // TODO: remove this when generic sdl event handlers are implemented in - // the DoseView - // SDL ONLY - bool GuiAdapter::IsSdlViewPortRefreshEvent(const SDL_Event& event) const - { - SDL_Window* sdlWindow = SDL_GetWindowFromID(event.window.windowID); - - ORTHANC_ASSERT(sdlWindow != NULL, "Window ID \"" << event.window.windowID << "\" is not a valid SDL window ID!"); - - const char* windowTitleSz = SDL_GetWindowTitle(sdlWindow); - - // now we need to find the DoseView from from the canvas name! - // (and retrieve the SdlViewport) - boost::shared_ptr<IGuiAdapterWidget> foundWidget; - VisitWidgets([&foundWidget, windowTitleSz](auto widget) - { - if (widget->GetCanvasIdentifier() == std::string(windowTitleSz)) - foundWidget = widget; - }); - ORTHANC_ASSERT(foundWidget, "The window named: \"" << windowTitleSz << "\" was not found in the registered widgets!"); - return foundWidget->GetSdlViewport().IsRefreshEvent(event); - } -#endif - - // SDL ONLY - void GuiAdapter::Run(GuiAdapterRunFunc func, void* cookie) - { -#if 1 - // 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 - - bool stop = false; - while (!stop) - { - { - // TODO: lock all viewports here! (use a scoped object) - if(func != NULL) - (*func)(cookie); - OnAnimationFrame(); // in SDL we must call it - } - - while (!stop) - { - std::vector<SDL_Event> sdlEvents; - std::map<Uint32,SDL_Event> userEventsMap; - - SDL_Event sdlEvent; - - // FIRST: collect all pending events - while (SDL_PollEvent(&sdlEvent) != 0) - { - if ( (sdlEvent.type >= SDL_USEREVENT) && - (sdlEvent.type < SDL_LASTEVENT) ) - { - // we don't want to have multiple events with the same event.type - userEventsMap[sdlEvent.type] = sdlEvent; - } - else - { - sdlEvents.push_back(sdlEvent); - } - } - - // SECOND: collect all user events - for (std::map<Uint32,SDL_Event>::const_iterator it = userEventsMap.begin(); it != userEventsMap.end(); ++it) - sdlEvents.push_back(it->second); - - // now process the events - for (std::vector<SDL_Event>::const_iterator it = sdlEvents.begin(); it != sdlEvents.end(); ++it) - { - const SDL_Event& sdlEvent = *it; - // TODO: lock all viewports here! (use a scoped object) - - if (sdlEvent.type == SDL_QUIT) - { - // TODO: call exit callbacks here - stop = true; - break; - } - else if ((sdlEvent.type == SDL_MOUSEMOTION) || - (sdlEvent.type == SDL_MOUSEBUTTONDOWN) || - (sdlEvent.type == SDL_MOUSEBUTTONUP)) - { - int scancodeCount = 0; - const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount); - bool ctrlPressed(false); - bool shiftPressed(false); - bool altPressed(false); - - 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; - - GuiAdapterMouseEvent dest; - ConvertFromPlatform(dest, ctrlPressed, shiftPressed, altPressed, sdlEvent); - OnMouseEvent(sdlEvent.window.windowID, dest); - #if 0 - // for reference, how to create trackers - if (tracker) - { - PointerEvent e; - e.AddPosition(compositor.GetPixelCenterCoordinates( - sdlEvent.button.x, sdlEvent.button.y)); - tracker->PointerMove(e); - } - #endif - } - else if (sdlEvent.type == SDL_MOUSEWHEEL) - { - - int scancodeCount = 0; - const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount); - bool ctrlPressed(false); - bool shiftPressed(false); - bool altPressed(false); - - 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; - - GuiAdapterWheelEvent dest; - ConvertFromPlatform(dest, ctrlPressed, shiftPressed, altPressed, sdlEvent); - OnMouseWheelEvent(sdlEvent.window.windowID, dest); - - //KeyboardModifiers modifiers = GetKeyboardModifiers(keyboardState, scancodeCount); - - //int x, y; - //SDL_GetMouseState(&x, &y); - - //if (sdlEvent.wheel.y > 0) - //{ - // locker.GetCentralViewport().MouseWheel(MouseWheelDirection_Up, x, y, modifiers); - //} - //else if (sdlEvent.wheel.y < 0) - //{ - // locker.GetCentralViewport().MouseWheel(MouseWheelDirection_Down, x, y, modifiers); - //} - } - else if (sdlEvent.type == SDL_WINDOWEVENT && - (sdlEvent.window.event == SDL_WINDOWEVENT_RESIZED || - sdlEvent.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)) - { - #if 0 - tracker.reset(); - #endif - OnResize(sdlEvent.window.data1, sdlEvent.window.data2); - } - else if (sdlEvent.type == SDL_KEYDOWN && sdlEvent.key.repeat == 0 /* Ignore key bounce */) - { - switch (sdlEvent.key.keysym.sym) - { - case SDLK_f: - // window.GetWindow().ToggleMaximize(); //TODO: move to particular handler - break; - - // This commented out code was used to debug the context - // loss/restoring code (2019-08-10) - // case SDLK_k: - // { - // SDL_Window* window = SDL_GetWindowFromID(sdlEvent.window.windowID); - // std::string windowTitle(SDL_GetWindowTitle(window)); - // Debug_SetContextToBeKilled(windowTitle); - // } - // break; - // case SDLK_l: - // { - // SDL_Window* window = SDL_GetWindowFromID(sdlEvent.window.windowID); - // std::string windowTitle(SDL_GetWindowTitle(window)); - // Debug_SetContextToBeRestored(windowTitle); - // } - // break; - - case SDLK_q: - stop = true; - break; - - default: - GuiAdapterKeyboardEvent dest; - ConvertFromPlatform(dest, sdlEvent); - OnKeyboardEvent(sdlEvent.window.windowID, dest); - break; - } - } - - OnSdlGenericEvent(sdlEvent); - } - SDL_Delay(1); - } - } - } -#endif -} -
--- a/OrthancStone/Sources/Deprecated/GuiAdapter.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,377 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ -#pragma once - -#include <string> - -#if ORTHANC_ENABLE_WASM != 1 -# ifdef __EMSCRIPTEN__ -# error __EMSCRIPTEN__ is defined and ORTHANC_ENABLE_WASM != 1 -# endif -#endif - -#if ORTHANC_ENABLE_WASM == 1 -# ifndef __EMSCRIPTEN__ -# error __EMSCRIPTEN__ is not defined and ORTHANC_ENABLE_WASM == 1 -# endif -#endif - -#if ORTHANC_ENABLE_WASM == 1 -# include <emscripten/html5.h> -#else -# if ORTHANC_ENABLE_SDL == 1 -# include <SDL.h> -# endif -#endif - -#include "../StoneException.h" - -#include <vector> -#include <boost/shared_ptr.hpp> -#include <boost/weak_ptr.hpp> - -namespace OrthancStone -{ -#if ORTHANC_ENABLE_SDL == 1 - class SdlViewport; -#endif - -#if 0 - - /** - This interface is used to store the widgets that are controlled by the - GuiAdapter and receive event callbacks. - The callbacks may possibly be downcast (using dynamic_cast, for safety) \ - to the actual widget type - */ - class IGuiAdapterWidget - { - public: - virtual ~IGuiAdapterWidget() {} - -#if #if ORTHANC_ENABLE_SDL == 1 - /** - Returns the SdlViewport that this widget contains. If the underlying - viewport type is *not* SDL, then an error is returned. - */ - virtual SdlViewport& GetSdlViewport() = 0; -#endif - }; - -#endif - - enum GuiAdapterMouseButtonType - { - GUIADAPTER_MOUSEBUTTON_LEFT = 0, - GUIADAPTER_MOUSEBUTTON_MIDDLE = 1, - GUIADAPTER_MOUSEBUTTON_RIGHT = 2 - }; - - - enum GuiAdapterHidEventType - { - GUIADAPTER_EVENT_MOUSEDOWN = 1973, - GUIADAPTER_EVENT_MOUSEMOVE = 1974, - GUIADAPTER_EVENT_MOUSEDBLCLICK = 1975, - GUIADAPTER_EVENT_MOUSEUP = 1976, - GUIADAPTER_EVENT_WHEEL = 1977, - GUIADAPTER_EVENT_KEYDOWN = 1978, - GUIADAPTER_EVENT_KEYUP = 1979, - }; - - const unsigned int GUIADAPTER_DELTA_PIXEL = 2973; - const unsigned int GUIADAPTER_DELTA_LINE = 2974; - const unsigned int GUIADAPTER_DELTA_PAGE = 2975; - - struct GuiAdapterUiEvent; - struct GuiAdapterMouseEvent; - struct GuiAdapterWheelEvent; - struct GuiAdapterKeyboardEvent; - -#if 1 - typedef bool (*OnMouseEventFunc) (std::string canvasId, const GuiAdapterMouseEvent* mouseEvent, void* userData); - typedef bool (*OnMouseWheelFunc) (std::string canvasId, const GuiAdapterWheelEvent* wheelEvent, void* userData); - typedef bool (*OnKeyDownFunc) (std::string canvasId, const GuiAdapterKeyboardEvent* keyEvent, void* userData); - typedef bool (*OnKeyUpFunc) (std::string canvasId, const GuiAdapterKeyboardEvent* keyEvent, void* userData); - typedef bool (*OnAnimationFrameFunc)(double time, void* userData); - -#if ORTHANC_ENABLE_SDL == 1 - typedef bool (*OnSdlEventCallback) (std::string canvasId, const SDL_Event& sdlEvent, void* userData); - - typedef bool (*OnSdlWindowResizeFunc)(std::string canvasId, - const GuiAdapterUiEvent* uiEvent, - unsigned int width, - unsigned int height, - void* userData); - - -#endif - -#else - -#if ORTHANC_ENABLE_WASM == 1 - typedef EM_BOOL (*OnMouseEventFunc)(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData); - typedef EM_BOOL (*OnMouseWheelFunc)(int eventType, const EmscriptenWheelEvent* wheelEvent, void* userData); - typedef EM_BOOL (*OnKeyDownFunc) (int eventType, const EmscriptenKeyboardEvent* keyEvent, void* userData); - typedef EM_BOOL (*OnKeyUpFunc) (int eventType, const EmscriptenKeyboardEvent* keyEvent, void* userData); - - typedef EM_BOOL (*OnAnimationFrameFunc)(double time, void* userData); - typedef EM_BOOL (*OnWindowResizeFunc)(int eventType, const EmscriptenUiEvent* uiEvent, void* userData); -#else - typedef bool (*OnMouseEventFunc)(int eventType, const SDL_Event* mouseEvent, void* userData); - typedef bool (*OnMouseWheelFunc)(int eventType, const SDL_Event* wheelEvent, void* userData); - typedef bool (*OnKeyDownFunc) (int eventType, const SDL_Event* keyEvent, void* userData); - typedef bool (*OnKeyUpFunc) (int eventType, const SDL_Event* keyEvent, void* userData); - - typedef bool (*OnAnimationFrameFunc)(double time, void* userData); - typedef bool (*OnWindowResizeFunc)(int eventType, const GuiAdapterUiEvent* uiEvent, void* userData); -#endif - -#endif - struct GuiAdapterMouseEvent - { - GuiAdapterHidEventType type; - //double timestamp; - //long screenX; - //long screenY; - //long clientX; - //long clientY; - bool ctrlKey; - bool shiftKey; - bool altKey; - //bool metaKey; - unsigned short button; - //unsigned short buttons; - //long movementX; - //long movementY; - long targetX; - long targetY; - // canvasX and canvasY are deprecated - there no longer exists a Module['canvas'] object, so canvasX/Y are no longer reported (register a listener on canvas directly to get canvas coordinates, or translate manually) - //long canvasX; - //long canvasY; - //long padding; - - public: - GuiAdapterMouseEvent() - : ctrlKey(false), - shiftKey(false), - altKey(false) - { - } - }; - - struct GuiAdapterWheelEvent { - GuiAdapterMouseEvent mouse; - double deltaX; - double deltaY; - unsigned long deltaMode; - }; - - // we don't use any data now - struct GuiAdapterUiEvent {}; - - // EmscriptenKeyboardEvent - struct GuiAdapterKeyboardEvent - { - GuiAdapterHidEventType type; - char sym[32]; - bool ctrlKey; - bool shiftKey; - bool altKey; - }; - - std::ostream& operator<<(std::ostream& os, const GuiAdapterKeyboardEvent& event); - std::ostream& operator<<(std::ostream& os, const GuiAdapterMouseEvent& event); - - /* - Mousedown event trigger when either the left or right (or middle) mouse is pressed - on the object; - - Mouseup event trigger when either the left or right (or middle) mouse is released - above the object after triggered mousedown event and held. - - Click event trigger when the only left mouse button is pressed and released on the - same object, requires the Mousedown and Mouseup event happened before Click event. - - The normal expect trigger order: onMousedown >> onMouseup >> onClick - - Testing in Chrome v58, the time between onMouseup and onClick events are around - 7ms to 15ms - - FROM: https://codingrepo.com/javascript/2017/05/19/javascript-difference-mousedown-mouseup-click-events/ - */ -#if ORTHANC_ENABLE_WASM == 1 - void ConvertFromPlatform(GuiAdapterUiEvent& dest, int eventType, const EmscriptenUiEvent& src); - - void ConvertFromPlatform(GuiAdapterMouseEvent& dest, int eventType, const EmscriptenMouseEvent& src); - - void ConvertFromPlatform(GuiAdapterWheelEvent& dest, int eventType, const EmscriptenWheelEvent& src); - - void ConvertFromPlatform(GuiAdapterKeyboardEvent& dest, const EmscriptenKeyboardEvent& src); -#else - -# if ORTHANC_ENABLE_SDL == 1 - void ConvertFromPlatform(GuiAdapterMouseEvent& dest, bool ctrlPressed, bool shiftPressed, bool altPressed, const SDL_Event& source); - - void ConvertFromPlatform(GuiAdapterWheelEvent& dest, bool ctrlPressed, bool shiftPressed, bool altPressed, const SDL_Event& source); - - void ConvertFromPlatform(GuiAdapterKeyboardEvent& dest, const SDL_Event& source); - -# endif - -#endif - - typedef void (*GuiAdapterRunFunc)(void*); - - class GuiAdapter - { - public: - GuiAdapter() - { - ORTHANC_ASSERT(s_instanceCount == 0); - s_instanceCount = 1; - } - - ~GuiAdapter() - { - s_instanceCount -= 1; - } - - /** - emscripten_set_resize_callback("EMSCRIPTEN_EVENT_TARGET_WINDOW", NULL, false, OnWindowResize); - - emscripten_set_wheel_callback("#mycanvas1", widget1_.get(), false, OnXXXMouseWheel); - emscripten_set_wheel_callback("#mycanvas2", widget2_.get(), false, OnXXXMouseWheel); - emscripten_set_wheel_callback("#mycanvas3", widget3_.get(), false, OnXXXMouseWheel); - - emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, OnKeyDown); ---> NO! - emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, OnKeyUp); - - emscripten_request_animation_frame_loop(OnAnimationFrame, NULL); - - SDL: - see https://wiki.libsdl.org/SDL_CaptureMouse - - */ - - void SetMouseDownCallback (std::string canvasId, void* userData, bool capture, OnMouseEventFunc func); - void SetMouseDblClickCallback (std::string canvasId, void* userData, bool capture, OnMouseEventFunc func); - void SetMouseMoveCallback (std::string canvasId, void* userData, bool capture, OnMouseEventFunc func); - void SetMouseUpCallback (std::string canvasId, void* userData, bool capture, OnMouseEventFunc func); - void SetWheelCallback (std::string canvasId, void* userData, bool capture, OnMouseWheelFunc func); - void SetKeyDownCallback (std::string canvasId, void* userData, bool capture, OnKeyDownFunc func); - void SetKeyUpCallback (std::string canvasId, void* userData, bool capture, OnKeyUpFunc func); - -#if ORTHANC_ENABLE_SDL == 1 - - void SetGenericSdlEventCallback (std::string canvasId, void* userData, bool capture, OnSdlEventCallback func); - - typedef bool (*OnSdlEventCallback) (std::string canvasId, const SDL_Event& sdlEvent, void* userData); - - // if you pass "#window", then any Window resize will trigger the callback - // (this special string is converted to EMSCRIPTEN_EVENT_TARGET_WINDOW in DOM, when DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=1) - void SetSdlResizeCallback(std::string canvasId, - void* userData, - bool capture, - OnSdlWindowResizeFunc func); -#endif - - void RequestAnimationFrame(OnAnimationFrameFunc func, void* userData); - - // TODO: implement and call to remove canvases [in SDL, although code should be generic] - void SetOnExitCallback(); - - /** - Under SDL, this function does NOT return until all windows have been closed. - Under wasm, it returns without doing anything, since the event loop is managed - by the browser. - */ - void Run(GuiAdapterRunFunc func = NULL, void* cookie = NULL); - - private: - -#if ORTHANC_ENABLE_SDL == 1 - /** - Gives observers a chance to react based on generic event handlers. This - is used, for instance, when the viewport lock interface is invalidated. - */ - void OnSdlGenericEvent(const SDL_Event& sdlEvent); -#endif - - /** - In SDL, this executes all the registered headers - */ - void OnAnimationFrame(); - - //void RequestAnimationFrame(OnAnimationFrameFunc func, void* userData); - std::vector<std::pair<OnAnimationFrameFunc, void*> > - animationFrameHandlers_; - - void OnResize(unsigned int width, unsigned int height); - -#if ORTHANC_ENABLE_SDL == 1 - template<typename Func> - struct EventHandlerData - { - EventHandlerData(std::string canvasName, Func func, void* userData) - : canvasName(canvasName) - , func(func) - , userData(userData) - { - } - - std::string canvasName; - Func func; - void* userData; - }; - std::vector<EventHandlerData<OnSdlWindowResizeFunc> > resizeHandlers_; - std::vector<EventHandlerData<OnMouseEventFunc > > mouseDownHandlers_; - std::vector<EventHandlerData<OnMouseEventFunc > > mouseDblCickHandlers_; - std::vector<EventHandlerData<OnMouseEventFunc > > mouseMoveHandlers_; - std::vector<EventHandlerData<OnMouseEventFunc > > mouseUpHandlers_; - std::vector<EventHandlerData<OnMouseWheelFunc > > mouseWheelHandlers_; - std::vector<EventHandlerData<OnKeyDownFunc > > keyDownHandlers_; - std::vector<EventHandlerData<OnKeyUpFunc > > keyUpHandlers_; - std::vector<EventHandlerData<OnSdlEventCallback > > sdlEventHandlers_; - - /** - This executes all the registered headers if needed (in wasm, the browser - deals with this) - */ - void OnMouseEvent(uint32_t windowID, const GuiAdapterMouseEvent& event); - - void OnKeyboardEvent(uint32_t windowID, const GuiAdapterKeyboardEvent& event); - - /** - Same remark as OnMouseEvent - */ - void OnMouseWheelEvent(uint32_t windowID, const GuiAdapterWheelEvent& event); - -#endif - - /** - This executes all the registered headers if needed (in wasm, the browser - deals with this) - */ - void ViewportsUpdateSize(); - - static int s_instanceCount; - }; -}
--- a/OrthancStone/Sources/Deprecated/Layers/CircleMeasureTracker.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "CircleMeasureTracker.h" - -#include <stdio.h> -#include <boost/math/constants/constants.hpp> - -namespace Deprecated -{ - CircleMeasureTracker::CircleMeasureTracker(IStatusBar* statusBar, - const OrthancStone::CoordinateSystem3D& slice, - double x, - double y, - uint8_t red, - uint8_t green, - uint8_t blue, - const Orthanc::Font& font) : - statusBar_(statusBar), - slice_(slice), - x1_(x), - y1_(y), - x2_(x), - y2_(y), - font_(font) - { - color_[0] = red; - color_[1] = green; - color_[2] = blue; - } - - - void CircleMeasureTracker::Render(OrthancStone::CairoContext& context, - double zoom) - { - double x = (x1_ + x2_) / 2.0; - double y = (y1_ + y2_) / 2.0; - - OrthancStone::Vector tmp; - OrthancStone::LinearAlgebra::AssignVector(tmp, x2_ - x1_, y2_ - y1_); - double r = boost::numeric::ublas::norm_2(tmp) / 2.0; - - context.SetSourceColor(color_[0], color_[1], color_[2]); - - cairo_t* cr = context.GetObject(); - cairo_save(cr); - cairo_set_line_width(cr, 2.0 / zoom); - cairo_translate(cr, x, y); - cairo_arc(cr, 0, 0, r, 0, 2.0 * boost::math::constants::pi<double>()); - cairo_stroke_preserve(cr); - cairo_stroke(cr); - cairo_restore(cr); - - context.DrawText(font_, FormatRadius(), x, y, OrthancStone::BitmapAnchor_Center); - } - - - double CircleMeasureTracker::GetRadius() const // In millimeters - { - OrthancStone::Vector a = slice_.MapSliceToWorldCoordinates(x1_, y1_); - OrthancStone::Vector b = slice_.MapSliceToWorldCoordinates(x2_, y2_); - return boost::numeric::ublas::norm_2(b - a) / 2.0; - } - - - std::string CircleMeasureTracker::FormatRadius() const - { - char buf[64]; - sprintf(buf, "%0.01f cm", GetRadius() / 10.0); - return buf; - } - - void CircleMeasureTracker::MouseMove(int displayX, - int displayY, - double x, - double y, - const std::vector<Touch>& displayTouches, - const std::vector<Touch>& sceneTouches) - { - x2_ = x; - y2_ = y; - - if (statusBar_ != NULL) - { - statusBar_->SetMessage("Circle radius: " + FormatRadius()); - } - } -}
--- a/OrthancStone/Sources/Deprecated/Layers/CircleMeasureTracker.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../Widgets/IWorldSceneMouseTracker.h" -#include "../Viewport/IStatusBar.h" -#include "../../Toolbox/CoordinateSystem3D.h" - -#include <Images/Font.h> - -namespace Deprecated -{ - class CircleMeasureTracker : public IWorldSceneMouseTracker - { - private: - IStatusBar* statusBar_; - OrthancStone::CoordinateSystem3D slice_; - double x1_; - double y1_; - double x2_; - double y2_; - uint8_t color_[3]; - const Orthanc::Font& font_; - - public: - CircleMeasureTracker(IStatusBar* statusBar, - const OrthancStone::CoordinateSystem3D& slice, - double x, - double y, - uint8_t red, - uint8_t green, - uint8_t blue, - const Orthanc::Font& font); - - virtual bool HasRender() const - { - return true; - } - - virtual void Render(OrthancStone::CairoContext& context, - double zoom); - - double GetRadius() const; // In millimeters - - std::string FormatRadius() const; - - virtual void MouseUp() - { - // Possibly create a new landmark "volume" with the circle in subclasses - } - - virtual void MouseMove(int displayX, - int displayY, - double x, - double y, - const std::vector<Touch>& displayTouches, - const std::vector<Touch>& sceneTouches); - }; -}
--- a/OrthancStone/Sources/Deprecated/Layers/ColorFrameRenderer.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "ColorFrameRenderer.h" - -#include <OrthancException.h> -#include <Images/Image.h> -#include <Images/ImageProcessing.h> - -namespace Deprecated -{ - OrthancStone::CairoSurface* ColorFrameRenderer::GenerateDisplay(const RenderStyle& style) - { - std::unique_ptr<OrthancStone::CairoSurface> display - (new OrthancStone::CairoSurface(frame_->GetWidth(), frame_->GetHeight(), false /* no alpha */)); - - Orthanc::ImageAccessor target; - display->GetWriteableAccessor(target); - - Orthanc::ImageProcessing::Convert(target, *frame_); - - return display.release(); - } - - - ColorFrameRenderer::ColorFrameRenderer(const Orthanc::ImageAccessor& frame, - const OrthancStone::CoordinateSystem3D& framePlane, - double pixelSpacingX, - double pixelSpacingY, - bool isFullQuality) : - FrameRenderer(framePlane, pixelSpacingX, pixelSpacingY, isFullQuality), - frame_(Orthanc::Image::Clone(frame)) - { - if (frame_.get() == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - if (frame_->GetFormat() != Orthanc::PixelFormat_RGB24) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); - } - } -}
--- a/OrthancStone/Sources/Deprecated/Layers/ColorFrameRenderer.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "FrameRenderer.h" - -namespace Deprecated -{ - class ColorFrameRenderer : public FrameRenderer - { - private: - std::unique_ptr<Orthanc::ImageAccessor> frame_; // In RGB24 - - protected: - virtual OrthancStone::CairoSurface* GenerateDisplay(const RenderStyle& style); - - public: - ColorFrameRenderer(const Orthanc::ImageAccessor& frame, - const OrthancStone::CoordinateSystem3D& framePlane, - double pixelSpacingX, - double pixelSpacingY, - bool isFullQuality); - }; -}
--- a/OrthancStone/Sources/Deprecated/Layers/DicomSeriesVolumeSlicer.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,181 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "DicomSeriesVolumeSlicer.h" - -#include "FrameRenderer.h" -#include "../Toolbox/DicomFrameConverter.h" - -#include <Logging.h> -#include <OrthancException.h> - -#include <boost/lexical_cast.hpp> - -namespace Deprecated -{ - - void DicomSeriesVolumeSlicer::OnSliceGeometryReady(const OrthancSlicesLoader::SliceGeometryReadyMessage& message) - { - if (message.GetOrigin().GetSlicesCount() > 0) - { - BroadcastMessage(IVolumeSlicer::GeometryReadyMessage(*this)); - } - else - { - BroadcastMessage(IVolumeSlicer::GeometryErrorMessage(*this)); - } - } - - void DicomSeriesVolumeSlicer::OnSliceGeometryError(const OrthancSlicesLoader::SliceGeometryErrorMessage& message) - { - BroadcastMessage(IVolumeSlicer::GeometryErrorMessage(*this)); - } - - - class DicomSeriesVolumeSlicer::RendererFactory : public LayerReadyMessage::IRendererFactory - { - private: - const OrthancSlicesLoader::SliceImageReadyMessage& message_; - - public: - RendererFactory(const OrthancSlicesLoader::SliceImageReadyMessage& message) : - message_(message) - { - } - - virtual ILayerRenderer* CreateRenderer() const - { - bool isFull = (message_.GetEffectiveQuality() == SliceImageQuality_FullPng || - message_.GetEffectiveQuality() == SliceImageQuality_FullPam); - - return FrameRenderer::CreateRenderer(message_.GetImage(), message_.GetSlice(), isFull); - } - }; - - void DicomSeriesVolumeSlicer::OnSliceImageReady(const OrthancSlicesLoader::SliceImageReadyMessage& message) - { - // first notify that the pixel data of the frame is ready (targeted to, i.e: an image cache) - BroadcastMessage(FrameReadyMessage(*this, message.GetImage(), - message.GetEffectiveQuality(), message.GetSlice())); - - // then notify that the layer is ready for rendering - RendererFactory factory(message); - BroadcastMessage(IVolumeSlicer::LayerReadyMessage(*this, factory, message.GetSlice().GetGeometry())); - } - - void DicomSeriesVolumeSlicer::OnSliceImageError(const OrthancSlicesLoader::SliceImageErrorMessage& message) - { - BroadcastMessage(IVolumeSlicer::LayerErrorMessage(*this, message.GetSlice().GetGeometry())); - } - - - DicomSeriesVolumeSlicer::DicomSeriesVolumeSlicer() : - quality_(SliceImageQuality_FullPng) - { - } - - void DicomSeriesVolumeSlicer::Connect(boost::shared_ptr<OrthancApiClient> orthanc) - { - loader_.reset(new OrthancSlicesLoader(orthanc)); - Register<OrthancSlicesLoader::SliceGeometryReadyMessage>(*loader_, &DicomSeriesVolumeSlicer::OnSliceGeometryReady); - Register<OrthancSlicesLoader::SliceGeometryErrorMessage>(*loader_, &DicomSeriesVolumeSlicer::OnSliceGeometryError); - Register<OrthancSlicesLoader::SliceImageReadyMessage>(*loader_, &DicomSeriesVolumeSlicer::OnSliceImageReady); - Register<OrthancSlicesLoader::SliceImageErrorMessage>(*loader_, &DicomSeriesVolumeSlicer::OnSliceImageError); - } - - void DicomSeriesVolumeSlicer::LoadSeries(const std::string& seriesId) - { - if (loader_.get() == NULL) - { - // Should have called "Connect()" - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - loader_->ScheduleLoadSeries(seriesId); - } - - - void DicomSeriesVolumeSlicer::LoadInstance(const std::string& instanceId) - { - if (loader_.get() == NULL) - { - // Should have called "Connect()" - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - loader_->ScheduleLoadInstance(instanceId); - } - - - void DicomSeriesVolumeSlicer::LoadFrame(const std::string& instanceId, - unsigned int frame) - { - if (loader_.get() == NULL) - { - // Should have called "Connect()" - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - loader_->ScheduleLoadFrame(instanceId, frame); - } - - - bool DicomSeriesVolumeSlicer::GetExtent(std::vector<OrthancStone::Vector>& points, - const OrthancStone::CoordinateSystem3D& viewportSlice) - { - if (loader_.get() == NULL) - { - // Should have called "Connect()" - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - size_t index; - - if (loader_->IsGeometryReady() && - loader_->LookupSlice(index, viewportSlice)) - { - loader_->GetSlice(index).GetExtent(points); - return true; - } - else - { - return false; - } - } - - - void DicomSeriesVolumeSlicer::ScheduleLayerCreation(const OrthancStone::CoordinateSystem3D& viewportSlice) - { - if (loader_.get() == NULL) - { - // Should have called "Connect()" - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - size_t index; - - if (loader_->IsGeometryReady() && - loader_->LookupSlice(index, viewportSlice)) - { - loader_->ScheduleLoadSliceImage(index, quality_); - } - } -}
--- a/OrthancStone/Sources/Deprecated/Layers/DicomSeriesVolumeSlicer.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,129 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "IVolumeSlicer.h" -#include "../../Messages/ObserverBase.h" -#include "../Toolbox/IWebService.h" -#include "../Toolbox/OrthancSlicesLoader.h" -#include "../Toolbox/OrthancApiClient.h" - -namespace Deprecated -{ - // this class is in charge of loading a Frame. - // once it's been loaded (first the geometry and then the image), - // messages are sent to observers so they can use it - class DicomSeriesVolumeSlicer : - public IVolumeSlicer, - public OrthancStone::ObserverBase<DicomSeriesVolumeSlicer> - //private OrthancSlicesLoader::ISliceLoaderObserver - { - public: - // TODO: Add "frame" and "instanceId" - class FrameReadyMessage : public OrthancStone::OriginMessage<DicomSeriesVolumeSlicer> - { - ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); - - private: - const Orthanc::ImageAccessor& frame_; - SliceImageQuality imageQuality_; - const Slice& slice_; - - public: - FrameReadyMessage(DicomSeriesVolumeSlicer& origin, - const Orthanc::ImageAccessor& frame, - SliceImageQuality imageQuality, - const Slice& slice) : - OriginMessage(origin), - frame_(frame), - imageQuality_(imageQuality), - slice_(slice) - { - } - - const Orthanc::ImageAccessor& GetFrame() const - { - return frame_; - } - - SliceImageQuality GetImageQuality() const - { - return imageQuality_; - } - - const Slice& GetSlice() const - { - return slice_; - } - }; - - - private: - class RendererFactory; - - boost::shared_ptr<OrthancSlicesLoader> loader_; - SliceImageQuality quality_; - - public: - DicomSeriesVolumeSlicer(); - - void Connect(boost::shared_ptr<OrthancApiClient> orthanc); - - void LoadSeries(const std::string& seriesId); - - void LoadInstance(const std::string& instanceId); - - void LoadFrame(const std::string& instanceId, - unsigned int frame); - - void SetImageQuality(SliceImageQuality quality) - { - quality_ = quality; - } - - SliceImageQuality GetImageQuality() const - { - return quality_; - } - - size_t GetSlicesCount() const - { - return loader_->GetSlicesCount(); - } - - const Slice& GetSlice(size_t slice) const - { - return loader_->GetSlice(slice); - } - - virtual bool GetExtent(std::vector<OrthancStone::Vector>& points, - const OrthancStone::CoordinateSystem3D& viewportSlice); - - virtual void ScheduleLayerCreation(const OrthancStone::CoordinateSystem3D& viewportSlice); - -protected: - void OnSliceGeometryReady(const OrthancSlicesLoader::SliceGeometryReadyMessage& message); - void OnSliceGeometryError(const OrthancSlicesLoader::SliceGeometryErrorMessage& message); - void OnSliceImageReady(const OrthancSlicesLoader::SliceImageReadyMessage& message); - void OnSliceImageError(const OrthancSlicesLoader::SliceImageErrorMessage& message); - }; -}
--- a/OrthancStone/Sources/Deprecated/Layers/DicomStructureSetSlicer.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,183 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#include "DicomStructureSetSlicer.h" - -#include "../../Toolbox/DicomStructureSet.h" - -namespace Deprecated -{ - class DicomStructureSetSlicer::Renderer : public ILayerRenderer - { - private: - class Structure - { - private: - bool visible_; - uint8_t red_; - uint8_t green_; - uint8_t blue_; - std::string name_; - -#if USE_BOOST_UNION_FOR_POLYGONS == 1 - std::vector< std::vector<OrthancStone::Point2D> > polygons_; -#else - std::vector< std::pair<OrthancStone::Point2D, OrthancStone::Point2D> > segments_; -#endif - - public: - Structure(OrthancStone::DicomStructureSet& structureSet, - const OrthancStone::CoordinateSystem3D& plane, - size_t index) : - name_(structureSet.GetStructureName(index)) - { - structureSet.GetStructureColor(red_, green_, blue_, index); - -#if USE_BOOST_UNION_FOR_POLYGONS == 1 - visible_ = structureSet.ProjectStructure(polygons_, index, plane); -#else - visible_ = structureSet.ProjectStructure(segments_, index, plane); -#endif - } - - void Render(OrthancStone::CairoContext& context) - { - if (visible_) - { - cairo_t* cr = context.GetObject(); - - context.SetSourceColor(red_, green_, blue_); - -#if USE_BOOST_UNION_FOR_POLYGONS == 1 - for (size_t i = 0; i < polygons_.size(); i++) - { - cairo_move_to(cr, polygons_[i][0].x, polygons_[i][0].y); - for (size_t j = 0; j < polygons_[i].size(); j++) - { - cairo_line_to(cr, polygons_[i][j].x, polygons_[i][j].y); - } - cairo_line_to(cr, polygons_[i][0].x, polygons_[i][0].y); - cairo_stroke(cr); - } -#else - for (size_t i = 0; i < segments_.size(); i++) - { - cairo_move_to(cr, segments_[i].first.x, segments_[i].first.y); - cairo_line_to(cr, segments_[i].second.x, segments_[i].second.y); - cairo_stroke(cr); - } -#endif - } - } - }; - - typedef std::list<Structure*> Structures; - - OrthancStone::CoordinateSystem3D plane_; - Structures structures_; - - public: - Renderer(OrthancStone::DicomStructureSet& structureSet, - const OrthancStone::CoordinateSystem3D& plane) : - plane_(plane) - { - for (size_t k = 0; k < structureSet.GetStructuresCount(); k++) - { - structures_.push_back(new Structure(structureSet, plane, k)); - } - } - - virtual ~Renderer() - { - for (Structures::iterator it = structures_.begin(); - it != structures_.end(); ++it) - { - delete *it; - } - } - - virtual bool RenderLayer(OrthancStone::CairoContext& context, - const ViewportGeometry& view) - { - cairo_set_line_width(context.GetObject(), 2.0f / view.GetZoom()); - - for (Structures::const_iterator it = structures_.begin(); - it != structures_.end(); ++it) - { - assert(*it != NULL); - (*it)->Render(context); - } - - return true; - } - - virtual const OrthancStone::CoordinateSystem3D& GetLayerPlane() - { - return plane_; - } - - virtual void SetLayerStyle(const RenderStyle& style) - { - } - - virtual bool IsFullQuality() - { - return true; - } - }; - - - class DicomStructureSetSlicer::RendererFactory : public LayerReadyMessage::IRendererFactory - { - private: - OrthancStone::DicomStructureSet& structureSet_; - const OrthancStone::CoordinateSystem3D& plane_; - - public: - RendererFactory(OrthancStone::DicomStructureSet& structureSet, - const OrthancStone::CoordinateSystem3D& plane) : - structureSet_(structureSet), - plane_(plane) - { - } - - virtual ILayerRenderer* CreateRenderer() const - { - return new Renderer(structureSet_, plane_); - } - }; - - - DicomStructureSetSlicer::DicomStructureSetSlicer(StructureSetLoader& loader) : - loader_(loader) - { - Register<StructureSetLoader::ContentChangedMessage>(loader_, &DicomStructureSetSlicer::OnStructureSetLoaded); - } - - - void DicomStructureSetSlicer::ScheduleLayerCreation(const OrthancStone::CoordinateSystem3D& viewportPlane) - { - if (loader_.HasStructureSet()) - { - RendererFactory factory(loader_.GetStructureSet(), viewportPlane); - BroadcastMessage(IVolumeSlicer::LayerReadyMessage(*this, factory, viewportPlane)); - } - } -}
--- a/OrthancStone/Sources/Deprecated/Layers/DicomStructureSetSlicer.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "IVolumeSlicer.h" -#include "../Volumes/StructureSetLoader.h" - -namespace Deprecated -{ - class DicomStructureSetSlicer : - public IVolumeSlicer, - public OrthancStone::ObserverBase<DicomStructureSetSlicer> - { - private: - class Renderer; - class RendererFactory; - - StructureSetLoader& loader_; - - void OnStructureSetLoaded(const IVolumeLoader::ContentChangedMessage& message) - { - BroadcastMessage(IVolumeSlicer::ContentChangedMessage(*this)); - } - - public: - DicomStructureSetSlicer(StructureSetLoader& loader); - - virtual bool GetExtent(std::vector<OrthancStone::Vector>& points, - const OrthancStone::CoordinateSystem3D& viewportPlane) - { - return false; - } - - virtual void ScheduleLayerCreation(const OrthancStone::CoordinateSystem3D& viewportPlane); - }; -}
--- a/OrthancStone/Sources/Deprecated/Layers/FrameRenderer.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "FrameRenderer.h" - -#include "GrayscaleFrameRenderer.h" -#include "ColorFrameRenderer.h" - -#include <OrthancException.h> - -namespace Deprecated -{ - FrameRenderer::FrameRenderer(const OrthancStone::CoordinateSystem3D& framePlane, - double pixelSpacingX, - double pixelSpacingY, - bool isFullQuality) : - framePlane_(framePlane), - pixelSpacingX_(pixelSpacingX), - pixelSpacingY_(pixelSpacingY), - isFullQuality_(isFullQuality) - { - } - - - bool FrameRenderer::RenderLayer(OrthancStone::CairoContext& context, - const ViewportGeometry& view) - { - if (!style_.visible_) - { - return true; - } - - if (display_.get() == NULL) - { - display_.reset(GenerateDisplay(style_)); - } - - assert(display_.get() != NULL); - - cairo_t *cr = context.GetObject(); - - cairo_save(cr); - - cairo_matrix_t transform; - cairo_matrix_init_identity(&transform); - cairo_matrix_scale(&transform, pixelSpacingX_, pixelSpacingY_); - cairo_matrix_translate(&transform, -0.5, -0.5); - cairo_transform(cr, &transform); - - //cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - cairo_set_source_surface(cr, display_->GetObject(), 0, 0); - - switch (style_.interpolation_) - { - case OrthancStone::ImageInterpolation_Nearest: - cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST); - break; - - case OrthancStone::ImageInterpolation_Bilinear: - cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_BILINEAR); - break; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - cairo_paint_with_alpha(cr, style_.alpha_); - - if (style_.drawGrid_) - { - context.SetSourceColor(style_.drawColor_); - cairo_set_line_width(cr, 0.5 / view.GetZoom()); - - for (unsigned int x = 0; x <= display_->GetWidth(); x++) - { - cairo_move_to(cr, x, 0); - cairo_line_to(cr, x, display_->GetHeight()); - } - - for (unsigned int y = 0; y <= display_->GetHeight(); y++) - { - cairo_move_to(cr, 0, y); - cairo_line_to(cr, display_->GetWidth(), y); - } - - cairo_stroke(cr); - } - - cairo_restore(cr); - - return true; - } - - - void FrameRenderer::SetLayerStyle(const RenderStyle& style) - { - style_ = style; - display_.reset(NULL); - } - - - ILayerRenderer* FrameRenderer::CreateRenderer(const Orthanc::ImageAccessor& frame, - const Deprecated::Slice& framePlane, - bool isFullQuality) - { - if (frame.GetFormat() == Orthanc::PixelFormat_RGB24) - { - return new ColorFrameRenderer(frame, - framePlane.GetGeometry(), - framePlane.GetPixelSpacingX(), - framePlane.GetPixelSpacingY(), isFullQuality); - } - else - { - return new GrayscaleFrameRenderer(frame, - framePlane.GetConverter(), - framePlane.GetGeometry(), - framePlane.GetPixelSpacingX(), - framePlane.GetPixelSpacingY(), isFullQuality); - } - } -}
--- a/OrthancStone/Sources/Deprecated/Layers/FrameRenderer.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "ILayerRenderer.h" - -#include "../Toolbox/Slice.h" - -namespace Deprecated -{ - class FrameRenderer : public ILayerRenderer - { - private: - OrthancStone::CoordinateSystem3D framePlane_; - double pixelSpacingX_; - double pixelSpacingY_; - RenderStyle style_; - bool isFullQuality_; - std::unique_ptr<OrthancStone::CairoSurface> display_; - - protected: - virtual OrthancStone::CairoSurface* GenerateDisplay(const RenderStyle& style) = 0; - - public: - FrameRenderer(const OrthancStone::CoordinateSystem3D& framePlane, - double pixelSpacingX, - double pixelSpacingY, - bool isFullQuality); - - virtual bool RenderLayer(OrthancStone::CairoContext& context, - const ViewportGeometry& view); - - virtual const OrthancStone::CoordinateSystem3D& GetLayerPlane() - { - return framePlane_; - } - - virtual void SetLayerStyle(const RenderStyle& style); - - virtual bool IsFullQuality() - { - return isFullQuality_; - } - - // TODO: Avoid cloning the "frame" - static ILayerRenderer* CreateRenderer(const Orthanc::ImageAccessor& frame, - const Deprecated::Slice& framePlane, - bool isFullQuality); - }; -}
--- a/OrthancStone/Sources/Deprecated/Layers/GrayscaleFrameRenderer.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,141 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "GrayscaleFrameRenderer.h" - -#include <Images/Image.h> -#include <OrthancException.h> - -namespace Deprecated -{ - OrthancStone::CairoSurface* GrayscaleFrameRenderer::GenerateDisplay(const RenderStyle& style) - { - assert(frame_->GetFormat() == Orthanc::PixelFormat_Float32); - - std::unique_ptr<OrthancStone::CairoSurface> result; - - float windowCenter, windowWidth; - style.ComputeWindowing(windowCenter, windowWidth, - defaultWindowCenter_, defaultWindowWidth_); - - float x0 = windowCenter - windowWidth / 2.0f; - float x1 = windowCenter + windowWidth / 2.0f; - - //LOG(INFO) << "Window: " << x0 << " => " << x1; - - result.reset(new OrthancStone::CairoSurface(frame_->GetWidth(), frame_->GetHeight(), false /* no alpha */)); - - const uint8_t* lut = NULL; - if (style.applyLut_) - { - if (Orthanc::EmbeddedResources::GetFileResourceSize(style.lut_) != 3 * 256) - { - // Invalid colormap - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - - lut = reinterpret_cast<const uint8_t*>(Orthanc::EmbeddedResources::GetFileResourceBuffer(style.lut_)); - } - - Orthanc::ImageAccessor target; - result->GetWriteableAccessor(target); - - const unsigned int width = target.GetWidth(); - const unsigned int height = target.GetHeight(); - - for (unsigned int y = 0; y < height; y++) - { - const float* p = reinterpret_cast<const float*>(frame_->GetConstRow(y)); - uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y)); - - for (unsigned int x = 0; x < width; x++, p++, q += 4) - { - uint8_t v = 0; - if (windowWidth >= 0.001f) // Avoid division by zero - { - if (*p >= x1) - { - v = 255; - } - else if (*p <= x0) - { - v = 0; - } - else - { - // https://en.wikipedia.org/wiki/Linear_interpolation - v = static_cast<uint8_t>(255.0f * (*p - x0) / (x1 - x0)); - } - - if (style.reverse_ ^ (photometric_ == Orthanc::PhotometricInterpretation_Monochrome1)) - { - v = 255 - v; - } - } - - if (style.applyLut_) - { - assert(lut != NULL); - q[3] = 255; - q[2] = lut[3 * v]; - q[1] = lut[3 * v + 1]; - q[0] = lut[3 * v + 2]; - } - else - { - q[3] = 255; - q[2] = v; - q[1] = v; - q[0] = v; - } - } - } - - return result.release(); - } - - - GrayscaleFrameRenderer::GrayscaleFrameRenderer(const Orthanc::ImageAccessor& frame, - const Deprecated::DicomFrameConverter& converter, - const OrthancStone::CoordinateSystem3D& framePlane, - double pixelSpacingX, - double pixelSpacingY, - bool isFullQuality) : - FrameRenderer(framePlane, pixelSpacingX, pixelSpacingY, isFullQuality), - frame_(Orthanc::Image::Clone(frame)), - defaultWindowCenter_(static_cast<float>(converter.GetDefaultWindowCenter())), - defaultWindowWidth_(static_cast<float>(converter.GetDefaultWindowWidth())), - photometric_(converter.GetPhotometricInterpretation()) - { - if (frame_.get() == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - converter.ConvertFrameInplace(frame_); - assert(frame_.get() != NULL); - - if (frame_->GetFormat() != Orthanc::PixelFormat_Float32) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); - } - } -}
--- a/OrthancStone/Sources/Deprecated/Layers/GrayscaleFrameRenderer.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "FrameRenderer.h" -#include "../Toolbox/DicomFrameConverter.h" - -namespace Deprecated -{ - class GrayscaleFrameRenderer : public FrameRenderer - { - private: - std::unique_ptr<Orthanc::ImageAccessor> frame_; // In Float32 - float defaultWindowCenter_; - float defaultWindowWidth_; - Orthanc::PhotometricInterpretation photometric_; - - protected: - virtual OrthancStone::CairoSurface* GenerateDisplay(const RenderStyle& style); - - public: - GrayscaleFrameRenderer(const Orthanc::ImageAccessor& frame, - const Deprecated::DicomFrameConverter& converter, - const OrthancStone::CoordinateSystem3D& framePlane, - double pixelSpacingX, - double pixelSpacingY, - bool isFullQuality); - }; -}
--- a/OrthancStone/Sources/Deprecated/Layers/ILayerRenderer.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../Wrappers/CairoContext.h" -#include "../../Toolbox/CoordinateSystem3D.h" -#include "../Toolbox/ViewportGeometry.h" -#include "RenderStyle.h" - -namespace Deprecated -{ - class ILayerRenderer : public boost::noncopyable - { - public: - virtual ~ILayerRenderer() - { - } - - virtual bool RenderLayer(OrthancStone::CairoContext& context, - const ViewportGeometry& view) = 0; - - virtual void SetLayerStyle(const RenderStyle& style) = 0; - - virtual const OrthancStone::CoordinateSystem3D& GetLayerPlane() = 0; - - virtual bool IsFullQuality() = 0; - }; -}
--- a/OrthancStone/Sources/Deprecated/Layers/IVolumeSlicer.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "ILayerRenderer.h" -#include "../Toolbox/Slice.h" -#include "../../Messages/IObservable.h" -#include "../../Messages/IMessage.h" -#include "Images/Image.h" -#include <boost/shared_ptr.hpp> - -namespace Deprecated -{ - class IVolumeSlicer : public OrthancStone::IObservable - { - public: - ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, GeometryReadyMessage, IVolumeSlicer); - ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, GeometryErrorMessage, IVolumeSlicer); - ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, ContentChangedMessage, IVolumeSlicer); - - class SliceContentChangedMessage : public OrthancStone::OriginMessage<IVolumeSlicer> - { - ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); - - private: - const Deprecated::Slice& slice_; - - public: - SliceContentChangedMessage(IVolumeSlicer& origin, - const Deprecated::Slice& slice) : - OriginMessage(origin), - slice_(slice) - { - } - - const Deprecated::Slice& GetSlice() const - { - return slice_; - } - }; - - - class LayerReadyMessage : public OrthancStone::OriginMessage<IVolumeSlicer> - { - ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); - - public: - class IRendererFactory : public boost::noncopyable - { - public: - virtual ~IRendererFactory() - { - } - - virtual ILayerRenderer* CreateRenderer() const = 0; - }; - - private: - const IRendererFactory& factory_; - const OrthancStone::CoordinateSystem3D& slice_; - - public: - LayerReadyMessage(IVolumeSlicer& origin, - const IRendererFactory& rendererFactory, - const OrthancStone::CoordinateSystem3D& slice) : - OriginMessage(origin), - factory_(rendererFactory), - slice_(slice) - { - } - - ILayerRenderer* CreateRenderer() const - { - return factory_.CreateRenderer(); - } - - const OrthancStone::CoordinateSystem3D& GetSlice() const - { - return slice_; - } - }; - - - class LayerErrorMessage : public OrthancStone::OriginMessage<IVolumeSlicer> - { - ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); - - private: - const OrthancStone::CoordinateSystem3D& slice_; - - public: - LayerErrorMessage(IVolumeSlicer& origin, - const OrthancStone::CoordinateSystem3D& slice) : - OriginMessage(origin), - slice_(slice) - { - } - - const OrthancStone::CoordinateSystem3D& GetSlice() const - { - return slice_; - } - }; - - - virtual ~IVolumeSlicer() - { - } - - virtual bool GetExtent(std::vector<OrthancStone::Vector>& points, - const OrthancStone::CoordinateSystem3D& viewportSlice) = 0; - - virtual void ScheduleLayerCreation(const OrthancStone::CoordinateSystem3D& viewportSlice) = 0; - }; -}
--- a/OrthancStone/Sources/Deprecated/Layers/LineLayerRenderer.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "LineLayerRenderer.h" - -namespace Deprecated -{ - LineLayerRenderer::LineLayerRenderer(double x1, - double y1, - double x2, - double y2, - const OrthancStone::CoordinateSystem3D& plane) : - x1_(x1), - y1_(y1), - x2_(x2), - y2_(y2), - plane_(plane) - { - RenderStyle style; - SetLayerStyle(style); - } - - - bool LineLayerRenderer::RenderLayer(OrthancStone::CairoContext& context, - const ViewportGeometry& view) - { - if (visible_) - { - context.SetSourceColor(color_); - - cairo_t *cr = context.GetObject(); - cairo_set_line_width(cr, 1.0 / view.GetZoom()); - cairo_move_to(cr, x1_, y1_); - cairo_line_to(cr, x2_, y2_); - cairo_stroke(cr); - } - - return true; - } - - - void LineLayerRenderer::SetLayerStyle(const RenderStyle& style) - { - visible_ = style.visible_; - color_[0] = style.drawColor_[0]; - color_[1] = style.drawColor_[1]; - color_[2] = style.drawColor_[2]; - } -}
--- a/OrthancStone/Sources/Deprecated/Layers/LineLayerRenderer.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "ILayerRenderer.h" - -namespace Deprecated -{ - class LineLayerRenderer : public ILayerRenderer - { - private: - double x1_; - double y1_; - double x2_; - double y2_; - OrthancStone::CoordinateSystem3D plane_; - bool visible_; - uint8_t color_[3]; - - public: - LineLayerRenderer(double x1, - double y1, - double x2, - double y2, - const OrthancStone::CoordinateSystem3D& plane); - - virtual bool RenderLayer(OrthancStone::CairoContext& context, - const ViewportGeometry& view); - - virtual void SetLayerStyle(const RenderStyle& style); - - virtual const OrthancStone::CoordinateSystem3D& GetLayerPlane() - { - return plane_; - } - - virtual bool IsFullQuality() - { - return true; - } - }; -}
--- a/OrthancStone/Sources/Deprecated/Layers/LineMeasureTracker.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "LineMeasureTracker.h" - -#include <stdio.h> - -namespace Deprecated -{ - LineMeasureTracker::LineMeasureTracker(IStatusBar* statusBar, - const OrthancStone::CoordinateSystem3D& slice, - double x, - double y, - uint8_t red, - uint8_t green, - uint8_t blue, - const Orthanc::Font& font) : - statusBar_(statusBar), - slice_(slice), - x1_(x), - y1_(y), - x2_(x), - y2_(y), - font_(font) - { - color_[0] = red; - color_[1] = green; - color_[2] = blue; - } - - - void LineMeasureTracker::Render(OrthancStone::CairoContext& context, - double zoom) - { - context.SetSourceColor(color_[0], color_[1], color_[2]); - - cairo_t* cr = context.GetObject(); - cairo_set_line_width(cr, 2.0 / zoom); - cairo_move_to(cr, x1_, y1_); - cairo_line_to(cr, x2_, y2_); - cairo_stroke(cr); - - if (y2_ - y1_ < 0) - { - context.DrawText(font_, FormatLength(), x2_, y2_ - 5, OrthancStone::BitmapAnchor_BottomCenter); - } - else - { - context.DrawText(font_, FormatLength(), x2_, y2_ + 5, OrthancStone::BitmapAnchor_TopCenter); - } - } - - - double LineMeasureTracker::GetLength() const // In millimeters - { - OrthancStone::Vector a = slice_.MapSliceToWorldCoordinates(x1_, y1_); - OrthancStone::Vector b = slice_.MapSliceToWorldCoordinates(x2_, y2_); - return boost::numeric::ublas::norm_2(b - a); - } - - - std::string LineMeasureTracker::FormatLength() const - { - char buf[64]; - sprintf(buf, "%0.01f cm", GetLength() / 10.0); - return buf; - } - - void LineMeasureTracker::MouseMove(int displayX, - int displayY, - double x, - double y, - const std::vector<Touch>& displayTouches, - const std::vector<Touch>& sceneTouches) - { - x2_ = x; - y2_ = y; - - if (statusBar_ != NULL) - { - statusBar_->SetMessage("Line length: " + FormatLength()); - } - } -}
--- a/OrthancStone/Sources/Deprecated/Layers/LineMeasureTracker.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../Widgets/IWorldSceneMouseTracker.h" - -#include "../Viewport/IStatusBar.h" -#include "../../Toolbox/CoordinateSystem3D.h" - -namespace Deprecated -{ - class LineMeasureTracker : public IWorldSceneMouseTracker - { - private: - IStatusBar* statusBar_; - OrthancStone::CoordinateSystem3D slice_; - double x1_; - double y1_; - double x2_; - double y2_; - uint8_t color_[3]; - unsigned int fontSize_; - const Orthanc::Font& font_; - - public: - LineMeasureTracker(IStatusBar* statusBar, - const OrthancStone::CoordinateSystem3D& slice, - double x, - double y, - uint8_t red, - uint8_t green, - uint8_t blue, - const Orthanc::Font& font); - - virtual bool HasRender() const - { - return true; - } - - virtual void Render(OrthancStone::CairoContext& context, - double zoom); - - double GetLength() const; // In millimeters - - std::string FormatLength() const; - - virtual void MouseUp() - { - // Possibly create a new landmark "volume" with the line in subclasses - } - - virtual void MouseMove(int displayX, - int displayY, - double x, - double y, - const std::vector<Touch>& displayTouches, - const std::vector<Touch>& sceneTouches); - }; -}
--- a/OrthancStone/Sources/Deprecated/Layers/RenderStyle.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "RenderStyle.h" - -#include "../../Volumes/ImageBuffer3D.h" -#include "../Toolbox/DicomFrameConverter.h" - -#include <OrthancException.h> - -namespace Deprecated -{ - RenderStyle::RenderStyle() - { - visible_ = true; - reverse_ = false; - windowing_ = OrthancStone::ImageWindowing_Custom; - alpha_ = 1; - applyLut_ = false; - lut_ = Orthanc::EmbeddedResources::COLORMAP_HOT; - drawGrid_ = false; - drawColor_[0] = 255; - drawColor_[1] = 255; - drawColor_[2] = 255; - customWindowCenter_ = 128; - customWindowWidth_ = 256; - interpolation_ = OrthancStone::ImageInterpolation_Nearest; - fontSize_ = 14; - } - - - void RenderStyle::ComputeWindowing(float& targetCenter, - float& targetWidth, - float defaultCenter, - float defaultWidth) const - { - if (windowing_ == OrthancStone::ImageWindowing_Custom) - { - targetCenter = customWindowCenter_; - targetWidth = customWindowWidth_; - } - else - { - return ::OrthancStone::ComputeWindowing - (targetCenter, targetWidth, windowing_, defaultCenter, defaultWidth); - } - } - - - void RenderStyle::SetColor(uint8_t red, - uint8_t green, - uint8_t blue) - { - drawColor_[0] = red; - drawColor_[1] = green; - drawColor_[2] = blue; - } - - - bool RenderStyle::FitRange(const OrthancStone::ImageBuffer3D& image, - const DicomFrameConverter& converter) - { - float minValue, maxValue; - - windowing_ = OrthancStone::ImageWindowing_Custom; - - if (image.GetRange(minValue, maxValue)) - { - // casting the narrower type to wider before calling the + operator - // will prevent overflowing (this is why the cast to double is only - // done on the first operand) - customWindowCenter_ = static_cast<float>( - converter.Apply((static_cast<double>(minValue) + maxValue) / 2.0)); - - customWindowWidth_ = static_cast<float>( - converter.Apply(static_cast<double>(maxValue) - minValue)); - - if (customWindowWidth_ > 1) - { - return true; - } - } - - customWindowCenter_ = 128.0; - customWindowWidth_ = 256.0; - return false; - } -}
--- a/OrthancStone/Sources/Deprecated/Layers/RenderStyle.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../StoneEnumerations.h" -#include "../../Volumes/ImageBuffer3D.h" -#include "../Toolbox/DicomFrameConverter.h" - -#include <EmbeddedResources.h> - -#include <stdint.h> - -namespace Deprecated -{ - struct RenderStyle - { - bool visible_; - bool reverse_; - OrthancStone::ImageWindowing windowing_; - float alpha_; // In [0,1] - bool applyLut_; - Orthanc::EmbeddedResources::FileResourceId lut_; - bool drawGrid_; - uint8_t drawColor_[3]; - float customWindowCenter_; - float customWindowWidth_; - OrthancStone::ImageInterpolation interpolation_; - unsigned int fontSize_; - - RenderStyle(); - - void ComputeWindowing(float& targetCenter, - float& targetWidth, - float defaultCenter, - float defaultWidth) const; - - void SetColor(uint8_t red, - uint8_t green, - uint8_t blue); - - bool FitRange(const OrthancStone::ImageBuffer3D& image, - const DicomFrameConverter& converter); - }; -}
--- a/OrthancStone/Sources/Deprecated/Layers/SeriesFrameRendererFactory.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,177 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "SeriesFrameRendererFactory.h" - -#include "FrameRenderer.h" - -#include <OrthancException.h> -#include <Logging.h> -#include <Toolbox.h> -#include <OrthancPluginException.h> -#include <DicomDatasetReader.h> - - -namespace Deprecated -{ - void SeriesFrameRendererFactory::ReadCurrentFrameDataset(size_t frame) - { - if (currentDataset_.get() != NULL && - (fast_ || currentFrame_ == frame)) - { - // The frame has not changed since the previous call, no need to - // update the DICOM dataset - return; - } - - currentDataset_.reset(loader_->DownloadDicom(frame)); - currentFrame_ = frame; - - if (currentDataset_.get() == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - } - - - void SeriesFrameRendererFactory::GetCurrentPixelSpacing(double& spacingX, - double& spacingY) const - { - if (currentDataset_.get() == NULL) - { - // There was no previous call "ReadCurrentFrameDataset()" - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - - GeometryToolbox::GetPixelSpacing(spacingX, spacingY, *currentDataset_); - } - - - double SeriesFrameRendererFactory::GetCurrentSliceThickness() const - { - if (currentDataset_.get() == NULL) - { - // There was no previous call "ReadCurrentFrameDataset()" - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - - try - { - OrthancPlugins::DicomDatasetReader reader(*currentDataset_); - - double thickness; - if (reader.GetDoubleValue(thickness, OrthancPlugins::DICOM_TAG_SLICE_THICKNESS)) - { - return thickness; - } - } - catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e) - { - } - - // Some arbitrary large slice thickness - return std::numeric_limits<double>::infinity(); - } - - - SeriesFrameRendererFactory::SeriesFrameRendererFactory(ISeriesLoader* loader, // Takes ownership - bool fast) : - loader_(loader), - currentFrame_(0), - fast_(fast) - { - if (loader == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - } - - - bool SeriesFrameRendererFactory::GetExtent(double& x1, - double& y1, - double& x2, - double& y2, - const SliceGeometry& viewportSlice) - { - if (currentDataset_.get() == NULL) - { - // There has been no previous call to - // "CreateLayerRenderer". Read some arbitrary DICOM frame, the - // one at the middle of the series. - unsigned int depth = loader_->GetGeometry().GetSliceCount(); - ReadCurrentFrameDataset(depth / 2); - } - - double spacingX, spacingY; - GetCurrentPixelSpacing(spacingX, spacingY); - - return FrameRenderer::ComputeFrameExtent(x1, y1, x2, y2, - viewportSlice, - loader_->GetGeometry().GetSlice(0), - loader_->GetWidth(), - loader_->GetHeight(), - spacingX, spacingY); - } - - - ILayerRenderer* SeriesFrameRendererFactory::CreateLayerRenderer(const SliceGeometry& viewportSlice) - { - size_t closest; - double distance; - - bool isOpposite; - if (!GeometryToolbox::IsParallelOrOpposite(isOpposite, loader_->GetGeometry().GetNormal(), viewportSlice.GetNormal()) || - !loader_->GetGeometry().ComputeClosestSlice(closest, distance, viewportSlice.GetOrigin())) - { - // Unable to compute the slice in the series that is the - // closest to the slice displayed by the viewport - return NULL; - } - - ReadCurrentFrameDataset(closest); - assert(currentDataset_.get() != NULL); - - double spacingX, spacingY; - GetCurrentPixelSpacing(spacingX, spacingY); - - if (distance <= GetCurrentSliceThickness() / 2.0) - { - SliceGeometry frameSlice(*currentDataset_); - return FrameRenderer::CreateRenderer(loader_->DownloadFrame(closest), - frameSlice, - *currentDataset_, - spacingX, spacingY, - true); - } - else - { - // The closest slice of the series is too far away from the - // slice displayed by the viewport - return NULL; - } - } - - - ISliceableVolume& SeriesFrameRendererFactory::GetSourceVolume() const - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } -}
--- a/OrthancStone/Sources/Deprecated/Layers/SeriesFrameRendererFactory.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "ILayerRendererFactory.h" - -#include "../Toolbox/ISeriesLoader.h" - -namespace Deprecated -{ - class SeriesFrameRendererFactory : public ILayerRendererFactory - { - private: - std::unique_ptr<ISeriesLoader> loader_; - size_t currentFrame_; - bool fast_; - - std::unique_ptr<OrthancPlugins::IDicomDataset> currentDataset_; - - void ReadCurrentFrameDataset(size_t frame); - - void GetCurrentPixelSpacing(double& spacingX, - double& spacingY) const; - - double GetCurrentSliceThickness() const; - - public: - SeriesFrameRendererFactory(ISeriesLoader* loader, // Takes ownership - bool fast); - - virtual bool GetExtent(double& x1, - double& y1, - double& x2, - double& y2, - const SliceGeometry& viewportSlice); - - virtual ILayerRenderer* CreateLayerRenderer(const SliceGeometry& viewportSlice); - - virtual bool HasSourceVolume() const - { - return false; - } - - virtual ISliceableVolume& GetSourceVolume() const; - }; -}
--- a/OrthancStone/Sources/Deprecated/Layers/SingleFrameRendererFactory.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "SingleFrameRendererFactory.h" - -#include "FrameRenderer.h" -#include "../Toolbox/MessagingToolbox.h" -#include "../Toolbox/DicomFrameConverter.h" - -#include <OrthancException.h> -#include <FullOrthancDataset.h> -#include <DicomDatasetReader.h> - -namespace Deprecated -{ - SingleFrameRendererFactory::SingleFrameRendererFactory(OrthancPlugins::IOrthancConnection& orthanc, - const std::string& instanceId, - unsigned int frame) : - orthanc_(orthanc), - instance_(instanceId), - frame_(frame) - { - dicom_.reset(new OrthancPlugins::FullOrthancDataset(orthanc, "/instances/" + instanceId + "/tags")); - - DicomFrameConverter converter; - converter.ReadParameters(*dicom_); - format_ = converter.GetExpectedPixelFormat(); - } - - - bool SingleFrameRendererFactory::GetExtent(double& x1, - double& y1, - double& x2, - double& y2, - const SliceGeometry& viewportSlice) - { - // Assume that PixelSpacingX == PixelSpacingY == 1 - - OrthancPlugins::DicomDatasetReader reader(*dicom_); - - unsigned int width, height; - - if (!reader.GetUnsignedIntegerValue(width, OrthancPlugins::DICOM_TAG_COLUMNS) || - !reader.GetUnsignedIntegerValue(height, OrthancPlugins::DICOM_TAG_ROWS)) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); - } - - x1 = 0; - y1 = 0; - x2 = static_cast<double>(width); - y2 = static_cast<double>(height); - - return true; - } - - - ILayerRenderer* SingleFrameRendererFactory::CreateLayerRenderer(const SliceGeometry& viewportSlice) - { - SliceGeometry frameSlice(*dicom_); - return FrameRenderer::CreateRenderer(MessagingToolbox::DecodeFrame(orthanc_, instance_, frame_, format_), - frameSlice, *dicom_, 1, 1, true); - } - - - ISliceableVolume& SingleFrameRendererFactory::GetSourceVolume() const - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } -}
--- a/OrthancStone/Sources/Deprecated/Layers/SingleFrameRendererFactory.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "ILayerRendererFactory.h" -#include <IOrthancConnection.h> - -namespace Deprecated -{ - class SingleFrameRendererFactory : public ILayerRendererFactory - { - private: - OrthancPlugins::IOrthancConnection& orthanc_; - std::unique_ptr<OrthancPlugins::IDicomDataset> dicom_; - - std::string instance_; - unsigned int frame_; - Orthanc::PixelFormat format_; - - public: - SingleFrameRendererFactory(OrthancPlugins::IOrthancConnection& orthanc, - const std::string& instanceId, - unsigned int frame); - - const OrthancPlugins::IDicomDataset& GetDataset() const - { - return *dicom_; - } - - SliceGeometry GetSliceGeometry() - { - return SliceGeometry(*dicom_); - } - - virtual bool GetExtent(double& x1, - double& y1, - double& x2, - double& y2, - const SliceGeometry& viewportSlice); - - virtual ILayerRenderer* CreateLayerRenderer(const SliceGeometry& viewportSlice); - - virtual bool HasSourceVolume() const - { - return false; - } - - virtual ISliceableVolume& GetSourceVolume() const; - }; -}
--- a/OrthancStone/Sources/Deprecated/Layers/SliceOutlineRenderer.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "SliceOutlineRenderer.h" - -namespace Deprecated -{ - bool SliceOutlineRenderer::RenderLayer(OrthancStone::CairoContext& context, - const ViewportGeometry& view) - { - if (style_.visible_) - { - cairo_t *cr = context.GetObject(); - cairo_save(cr); - - context.SetSourceColor(style_.drawColor_); - - double x1 = -0.5 * pixelSpacingX_; - double y1 = -0.5 * pixelSpacingY_; - - cairo_set_line_width(cr, 1.0 / view.GetZoom()); - cairo_rectangle(cr, x1, y1, - static_cast<double>(width_) * pixelSpacingX_, - static_cast<double>(height_) * pixelSpacingY_); - - double handleSize = 10.0f / view.GetZoom(); - cairo_move_to(cr, x1 + handleSize, y1); - cairo_line_to(cr, x1, y1 + handleSize); - - cairo_stroke(cr); - cairo_restore(cr); - } - - return true; - } -}
--- a/OrthancStone/Sources/Deprecated/Layers/SliceOutlineRenderer.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "ILayerRenderer.h" -#include "../Toolbox/Slice.h" - -namespace Deprecated -{ - class SliceOutlineRenderer : public ILayerRenderer - { - private: - OrthancStone::CoordinateSystem3D geometry_; - double pixelSpacingX_; - double pixelSpacingY_; - unsigned int width_; - unsigned int height_; - RenderStyle style_; - - public: - SliceOutlineRenderer(const Slice& slice) : - geometry_(slice.GetGeometry()), - pixelSpacingX_(slice.GetPixelSpacingX()), - pixelSpacingY_(slice.GetPixelSpacingY()), - width_(slice.GetWidth()), - height_(slice.GetHeight()) - { - } - - virtual bool RenderLayer(OrthancStone::CairoContext& context, - const ViewportGeometry& view); - - virtual void SetLayerStyle(const RenderStyle& style) - { - style_ = style; - } - - virtual const OrthancStone::CoordinateSystem3D& GetLayerSlice() - { - return geometry_; - } - - virtual bool IsFullQuality() - { - return true; - } - }; -}
--- a/OrthancStone/Sources/Deprecated/Loaders/DicomStructureSetLoader2.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,125 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2 - -#include "DicomStructureSetLoader2.h" - -#include "../Messages/IObservable.h" -#include "../Oracle/IOracle.h" -#include "../Oracle/OracleCommandExceptionMessage.h" - -namespace Deprecated -{ - - DicomStructureSetLoader2::DicomStructureSetLoader2( - DicomStructureSet2& structureSet - , IOracle& oracle - , IObservable& oracleObservable) - : IObserver(oracleObservable.GetBroker()) - , IObservable(oracleObservable.GetBroker()) - , structureSet_(structureSet) - , oracle_(oracle) - , oracleObservable_(oracleObservable) - , structuresReady_(false) - { - LOG(TRACE) << "DicomStructureSetLoader2(" << std::hex << this << std::dec << ")::DicomStructureSetLoader2()"; - - oracleObservable.RegisterObserverCallback( - new Callable<DicomStructureSetLoader2, OrthancRestApiCommand::SuccessMessage> - (*this, &DicomStructureSetLoader2::HandleSuccessMessage)); - - oracleObservable.RegisterObserverCallback( - new Callable<DicomStructureSetLoader2, OracleCommandExceptionMessage> - (*this, &DicomStructureSetLoader2::HandleExceptionMessage)); - } - - DicomStructureSetLoader2::~DicomStructureSetLoader2() - { - LOG(TRACE) << "DicomStructureSetLoader2(" << std::hex << this << std::dec << ")::~DicomStructureSetLoader2()"; - oracleObservable_.Unregister(this); - } - - void DicomStructureSetLoader2::LoadInstanceFromString(const std::string& body) - { - OrthancPlugins::FullOrthancDataset dicom(body); - //loader.content_.reset(new DicomStructureSet(dicom)); - structureSet_.Clear(); - structureSet_.SetContents(dicom); - SetStructuresReady(); - } - - void DicomStructureSetLoader2::HandleSuccessMessage(const OrthancRestApiCommand::SuccessMessage& message) - { - const std::string& body = message.GetAnswer(); - LoadInstanceFromString(body); - } - - void DicomStructureSetLoader2::HandleExceptionMessage(const OracleCommandExceptionMessage& message) - { - LOG(ERROR) << "DicomStructureSetLoader2::HandleExceptionMessage: error when trying to load data. " - << "Error: " << message.GetException().What() << " Details: " - << message.GetException().GetDetails(); - } - - void DicomStructureSetLoader2::LoadInstance(const std::string& instanceId) - { - std::unique_ptr<OrthancRestApiCommand> command(new OrthancRestApiCommand); - command->SetHttpHeader("Accept-Encoding", "gzip"); - - std::string uri = "/instances/" + instanceId + "/tags?ignore-length=3006-0050"; - - command->SetUri(uri); - oracle_.Schedule(*this, command.release()); - } - - void DicomStructureSetLoader2::SetStructuresReady() - { - structuresReady_ = true; - } - - bool DicomStructureSetLoader2::AreStructuresReady() const - { - return structuresReady_; - } - - /* - - void LoaderStateMachine::HandleExceptionMessage(const OracleCommandExceptionMessage& message) - { - LOG(ERROR) << "LoaderStateMachine::HandleExceptionMessage: error in the state machine, stopping all processing"; - LOG(ERROR) << "Error: " << message.GetException().What() << " Details: " << - message.GetException().GetDetails(); - Clear(); - } - - LoaderStateMachine::~LoaderStateMachine() - { - Clear(); - } - - - */ - -} - -#endif -// BGO_ENABLE_DICOMSTRUCTURESETLOADER2 -
--- a/OrthancStone/Sources/Deprecated/Loaders/DicomStructureSetLoader2.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#pragma once - -#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2 - -#include "../Toolbox/DicomStructureSet2.h" -#include "../Messages/IMessage.h" -#include "../Messages/IObserver.h" -#include "../Messages/IObservable.h" -#include "../Oracle/OrthancRestApiCommand.h" - -#include <boost/noncopyable.hpp> - -namespace Deprecated -{ - class IOracle; - class IObservable; - class OrthancRestApiCommand; - class OracleCommandExceptionMessage; - - class DicomStructureSetLoader2 : public IObserver, public IObservable - { - public: - ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, StructuresReady, DicomStructureSetLoader2); - - /** - Warning: the structureSet, oracle and oracleObservable objects must live - at least as long as this object (TODO: shared_ptr?) - */ - DicomStructureSetLoader2(DicomStructureSet2& structureSet, IOracle& oracle, IObservable& oracleObservable); - - ~DicomStructureSetLoader2(); - - void LoadInstance(const std::string& instanceId); - - /** Internal use */ - void LoadInstanceFromString(const std::string& body); - - void SetStructuresReady(); - bool AreStructuresReady() const; - - private: - /** - Called back by the oracle when data is ready! - */ - void HandleSuccessMessage(const OrthancRestApiCommand::SuccessMessage& message); - - /** - Called back by the oracle when shit hits the fan - */ - void HandleExceptionMessage(const OracleCommandExceptionMessage& message); - - /** - The structure set that will be (cleared and) filled with data from the - loader - */ - DicomStructureSet2& structureSet_; - - IOracle& oracle_; - IObservable& oracleObservable_; - bool structuresReady_; - }; -} - -#endif -// BGO_ENABLE_DICOMSTRUCTURESETLOADER2 - -
--- a/OrthancStone/Sources/Deprecated/Messages/LockingEmitter.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#include "LockingEmitter.h" - -#include <OrthancException.h> - -namespace Deprecated -{ - void LockingEmitter::EmitMessage(boost::weak_ptr<OrthancStone::IObserver> observer, - const OrthancStone::IMessage& message) - { - try - { - boost::unique_lock<boost::shared_mutex> lock(mutex_); - oracleObservable_.EmitMessage(observer, message); - } - catch (Orthanc::OrthancException& e) - { - LOG(ERROR) << "Exception while emitting a message: " << e.What(); - } - } -}
--- a/OrthancStone/Sources/Deprecated/Messages/LockingEmitter.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#pragma once - -#include <Enumerations.h> -#include <OrthancException.h> - -#include "../../Messages/IMessageEmitter.h" -#include "../../Messages/IObservable.h" - -#include <boost/thread/shared_mutex.hpp> - -namespace Deprecated -{ - /** - * This class is used when using the ThreadedOracle : since messages - * can be sent from multiple Oracle threads, this IMessageEmitter - * implementation serializes the callbacks. - * - * The internal mutex used in Oracle messaging can also be used to - * protect the application data. Thus, this class can be used as a single - * application-wide mutex. - */ - class LockingEmitter : public OrthancStone::IMessageEmitter - { - private: - boost::shared_mutex mutex_; - OrthancStone::IObservable oracleObservable_; - - public: - virtual void EmitMessage(boost::weak_ptr<OrthancStone::IObserver> observer, - const OrthancStone::IMessage& message) ORTHANC_OVERRIDE; - - - class ReaderLock : public boost::noncopyable - { - private: - LockingEmitter& that_; - boost::shared_lock<boost::shared_mutex> lock_; - - public: - ReaderLock(LockingEmitter& that) : - that_(that), - lock_(that.mutex_) - { - } - }; - - - class WriterLock : public boost::noncopyable - { - private: - LockingEmitter& that_; - boost::unique_lock<boost::shared_mutex> lock_; - - public: - WriterLock(LockingEmitter& that) : - that_(that), - lock_(that.mutex_) - { - } - - OrthancStone::IObservable& GetOracleObservable() - { - return that_.oracleObservable_; - } - }; - }; -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyAlphaLayer.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,152 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "RadiographyAlphaLayer.h" - -#include "RadiographyScene.h" -#include "../Toolbox/ImageGeometry.h" - -#include <Compatibility.h> -#include <Images/Image.h> -#include <OrthancException.h> - - -namespace OrthancStone -{ - - void RadiographyAlphaLayer::SetAlpha(Orthanc::ImageAccessor* image) - { - std::unique_ptr<Orthanc::ImageAccessor> raii(image); - - if (image == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); - } - - if (image->GetFormat() != Orthanc::PixelFormat_Grayscale8) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); - } - - SetSize(image->GetWidth(), image->GetHeight()); - -#if __cplusplus < 201103L - alpha_.reset(raii.release()); -#else - alpha_ = std::move(raii); -#endif - - BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this)); - } - - void RadiographyAlphaLayer::Render(Orthanc::ImageAccessor& buffer, - const AffineTransform2D& viewTransform, - ImageInterpolation interpolation, - float windowCenter, - float windowWidth, - bool applyWindowing) const - { - if (alpha_.get() == NULL) - { - return; - } - - if (buffer.GetFormat() != Orthanc::PixelFormat_Float32) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); - } - - unsigned int cropX, cropY, cropWidth, cropHeight; - GetCrop(cropX, cropY, cropWidth, cropHeight); - - const AffineTransform2D t = AffineTransform2D::Combine( - viewTransform, GetTransform(), - AffineTransform2D::CreateOffset(cropX, cropY)); - - Orthanc::ImageAccessor cropped; - alpha_->GetRegion(cropped, cropX, cropY, cropWidth, cropHeight); - - Orthanc::Image tmp(Orthanc::PixelFormat_Grayscale8, buffer.GetWidth(), buffer.GetHeight(), false); - - unsigned int x1, y1, x2, y2; - - if (!OrthancStone::GetProjectiveTransformExtent(x1, y1, x2, y2, - t.GetHomogeneousMatrix(), - cropped.GetWidth(), - cropped.GetHeight(), - buffer.GetWidth(), - buffer.GetHeight())) - { - return; // layer is outside the buffer - } - - t.Apply(tmp, cropped, interpolation, true /* clear */); - - float value = foreground_; - - if (!applyWindowing) // if applying the windowing, it means we are ie rendering the image for a realtime visualization -> the foreground_ value is the value we want to see on the screen -> don't change it - { - // if not applying the windowing, it means ie that we are saving a dicom image to file and the windowing will be applied by a viewer later on -> we want the "foreground" value to be correct once the windowing will be applied - value = windowCenter - windowWidth/2 + (foreground_ / 65535.0f) * windowWidth; - - if (value < 0.0f) - { - value = 0.0f; - } - if (value > 65535.0f) - { - value = 65535.0f; - } - } - - for (unsigned int y = y1; y <= y2; y++) - { - float *q = reinterpret_cast<float*>(buffer.GetRow(y)) + x1; - const uint8_t *p = reinterpret_cast<uint8_t*>(tmp.GetRow(y)) + x1; - - for (unsigned int x = x1; x <= x2; x++, p++, q++) - { - float a = static_cast<float>(*p) / 255.0f; - - *q = (a * value + (1.0f - a) * (*q)); - } - } - } - - bool RadiographyAlphaLayer::GetRange(float& minValue, - float& maxValue) const - { - minValue = 0; - maxValue = 0; - - if (foreground_ < 0) - { - minValue = foreground_; - } - - if (foreground_ > 0) - { - maxValue = foreground_; - } - - return true; - } -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyAlphaLayer.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "RadiographyLayer.h" - -#include <Compatibility.h> - -namespace OrthancStone -{ - class RadiographyScene; - - // creates a transparent layer whose alpha channel is provided as a UINT8 image to SetAlpha. - // The color of the "mask" is either defined by a ForegroundValue or by the center value of the - // windowing from the scene. - class RadiographyAlphaLayer : public RadiographyLayer - { - private: - std::unique_ptr<Orthanc::ImageAccessor> alpha_; // Grayscale8 in the range [0, 255] 0 = transparent, 255 = opaque -> the foreground value will be displayed - float foreground_; // in the range [0.0, 65535.0] - - public: - RadiographyAlphaLayer(const RadiographyScene& scene) : - RadiographyLayer(scene), - foreground_(0) - { - } - - - void SetForegroundValue(float foreground) - { - foreground_ = foreground; - } - - float GetForegroundValue() const - { - return foreground_; - } - - void SetAlpha(Orthanc::ImageAccessor* image); - - virtual bool GetDefaultWindowing(float& center, - float& width) const - { - return false; - } - - - virtual void Render(Orthanc::ImageAccessor& buffer, - const AffineTransform2D& viewTransform, - ImageInterpolation interpolation, - float windowCenter, - float windowWidth, - bool applyWindowing) const; - - virtual bool GetRange(float& minValue, - float& maxValue) const; - - const Orthanc::ImageAccessor& GetAlpha() const - { - return *(alpha_.get()); - } - - - }; -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyDicomLayer.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,264 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "RadiographyDicomLayer.h" - -#include "RadiographyScene.h" -#include "../Deprecated/Toolbox/DicomFrameConverter.h" -#include "../Toolbox/ImageGeometry.h" - -#include <OrthancException.h> -#include <Images/Image.h> -#include <Images/ImageProcessing.h> -#include <DicomDatasetReader.h> - -static OrthancPlugins::DicomTag ConvertTag(const Orthanc::DicomTag& tag) -{ - return OrthancPlugins::DicomTag(tag.GetGroup(), tag.GetElement()); -} - -namespace OrthancStone -{ - - void RadiographyDicomLayer::ApplyConverter() - { - if (source_.get() != NULL && - converter_.get() != NULL) - { - converted_.reset(converter_->ConvertFrame(*source_)); - } - } - - - RadiographyDicomLayer::RadiographyDicomLayer(const RadiographyScene& scene) : - RadiographyLayer(scene) - { - - } - - void RadiographyDicomLayer::SetDicomTags(const OrthancPlugins::FullOrthancDataset& dataset) - { - converter_.reset(new Deprecated::DicomFrameConverter); - converter_->ReadParameters(dataset); - ApplyConverter(); - - std::string tmp; - Vector pixelSpacing; - - if (dataset.GetStringValue(tmp, ConvertTag(Orthanc::DICOM_TAG_PIXEL_SPACING)) && - LinearAlgebra::ParseVector(pixelSpacing, tmp) && - pixelSpacing.size() == 2) - { - SetPixelSpacing(pixelSpacing[0], pixelSpacing[1]); - } - - OrthancPlugins::DicomDatasetReader reader(dataset); - - unsigned int width, height; - if (!reader.GetUnsignedIntegerValue(width, ConvertTag(Orthanc::DICOM_TAG_COLUMNS)) || - !reader.GetUnsignedIntegerValue(height, ConvertTag(Orthanc::DICOM_TAG_ROWS))) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); - } - else - { - SetSize(width, height); - } - - if (dataset.GetStringValue(tmp, ConvertTag(Orthanc::DICOM_TAG_PHOTOMETRIC_INTERPRETATION))) - { - if (tmp == "MONOCHROME1") - { - SetPreferredPhotomotricDisplayMode(RadiographyPhotometricDisplayMode_Monochrome1); - } - else if (tmp == "MONOCHROME2") - { - SetPreferredPhotomotricDisplayMode(RadiographyPhotometricDisplayMode_Monochrome2); - } - } - } - - void RadiographyDicomLayer::SetSourceImage(Orthanc::ImageAccessor* image) // Takes ownership - { - std::unique_ptr<Orthanc::ImageAccessor> raii(image); - - if (image == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); - } - - SetSize(image->GetWidth(), image->GetHeight()); - -#if __cplusplus < 201103L - source_.reset(raii.release()); -#else - source_ = std::move(raii); -#endif - - ApplyConverter(); - - BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this)); - } - - void RadiographyDicomLayer::SetSourceImage(Orthanc::ImageAccessor* image, double newPixelSpacingX, double newPixelSpacingY, bool emitLayerEditedEvent) // Takes ownership - { - std::unique_ptr<Orthanc::ImageAccessor> raii(image); - - if (image == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); - } - - SetSize(image->GetWidth(), image->GetHeight(), false); - -#if __cplusplus < 201103L - source_.reset(raii.release()); -#else - source_ = std::move(raii); -#endif - - ApplyConverter(); - - SetPixelSpacing(newPixelSpacingX, newPixelSpacingY, false); - - if (emitLayerEditedEvent) - { - BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this)); - } - } - - - void RadiographyDicomLayer::SetDicomFrameConverter(Deprecated::DicomFrameConverter* converter) - { - converter_.reset(converter); - } - - void RadiographyDicomLayer::Render(Orthanc::ImageAccessor& buffer, - const AffineTransform2D& viewTransform, - ImageInterpolation interpolation, - float windowCenter, - float windowWidth, - bool applyWindowing) const - { - if (converted_.get() != NULL) - { - if (converted_->GetFormat() != Orthanc::PixelFormat_Float32) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - - unsigned int cropX, cropY, cropWidth, cropHeight; - GetCrop(cropX, cropY, cropWidth, cropHeight); - - AffineTransform2D t = AffineTransform2D::Combine( - viewTransform, GetTransform(), - AffineTransform2D::CreateOffset(cropX, cropY)); - - Orthanc::ImageAccessor cropped; - converted_->GetRegion(cropped, cropX, cropY, cropWidth, cropHeight); - - unsigned int x1, y1, x2, y2; - if (!OrthancStone::GetProjectiveTransformExtent(x1, y1, x2, y2, - t.GetHomogeneousMatrix(), - cropped.GetWidth(), - cropped.GetHeight(), - buffer.GetWidth(), - buffer.GetHeight())) - { - return; // layer is outside the buffer - } - - t.Apply(buffer, cropped, interpolation, false); - - if (applyWindowing) - { - // apply windowing but stay in the range [0.0, 65535.0] - float w0 = windowCenter - windowWidth / 2.0f; - float w1 = windowCenter + windowWidth / 2.0f; - - if (windowWidth >= 0.001f) // Avoid division by zero at (*) - { - float scaling = 1.0f / (w1 - w0) * 65535.0f; - for (unsigned int y = y1; y <= y2; y++) - { - float* p = reinterpret_cast<float*>(buffer.GetRow(y)) + x1; - - for (unsigned int x = x1; x <= x2; x++, p++) - { - if (*p >= w1) - { - *p = 65535.0; - } - else if (*p <= w0) - { - *p = 0; - } - else - { - // https://en.wikipedia.org/wiki/Linear_interpolation - *p = scaling * (*p - w0); // (*) - } - } - } - } - } - - } - } - - - bool RadiographyDicomLayer::GetDefaultWindowing(float& center, - float& width) const - { - if (converter_.get() != NULL && - converter_->HasDefaultWindow()) - { - center = static_cast<float>(converter_->GetDefaultWindowCenter()); - width = static_cast<float>(converter_->GetDefaultWindowWidth()); - return true; - } - else - { - return false; - } - } - - - bool RadiographyDicomLayer::GetRange(float& minValue, - float& maxValue) const - { - if (converted_.get() != NULL) - { - if (converted_->GetFormat() != Orthanc::PixelFormat_Float32) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - - Orthanc::ImageProcessing::GetMinMaxFloatValue(minValue, maxValue, *converted_); - return true; - } - else - { - return false; - } - } - -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyDicomLayer.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../Deprecated/Toolbox/DicomFrameConverter.h" -#include "RadiographyLayer.h" - -#include <FullOrthancDataset.h> - -namespace OrthancStone -{ - class RadiographyScene; - - class RadiographyDicomLayer : public RadiographyLayer - { - private: - std::unique_ptr<Orthanc::ImageAccessor> source_; // Content of PixelData - std::unique_ptr<Deprecated::DicomFrameConverter> converter_; - std::unique_ptr<Orthanc::ImageAccessor> converted_; // Float32 - std::string instanceId_; - unsigned int frame_; - - void ApplyConverter(); - - public: - RadiographyDicomLayer(const RadiographyScene& scene); - - void SetInstance(const std::string& instanceId, unsigned int frame) - { - instanceId_ = instanceId; - frame_ = frame; - } - - std::string GetInstanceId() const - { - return instanceId_; - } - - unsigned int GetFrame() const - { - return frame_; - } - - virtual size_t GetApproximateMemoryUsage() const - { - size_t size = 0; - if (source_.get() != NULL) - { - size += source_->GetPitch() * source_->GetHeight(); - } - if (converted_.get() != NULL) - { - size += converted_->GetPitch() * converted_->GetHeight(); - } - - return size; - } - - - void SetDicomTags(const OrthancPlugins::FullOrthancDataset& dataset); - - void SetSourceImage(Orthanc::ImageAccessor* image); // Takes ownership - - void SetSourceImage(Orthanc::ImageAccessor* image, double newPixelSpacingX, double newPixelSpacingY, bool emitLayerEditedEvent = true); // Takes ownership - - const Orthanc::ImageAccessor* GetSourceImage() const {return source_.get();} // currently need this access to serialize scene in plain old data to send to a WASM worker - - const Deprecated::DicomFrameConverter& GetDicomFrameConverter() const {return *converter_;} // currently need this access to serialize scene in plain old data to send to a WASM worker - - // Takes ownership - void SetDicomFrameConverter(Deprecated::DicomFrameConverter* converter); - - virtual void Render(Orthanc::ImageAccessor& buffer, - const AffineTransform2D& viewTransform, - ImageInterpolation interpolation, - float windowCenter, - float windowWidth, - bool applyWindowing) const; - - virtual bool GetDefaultWindowing(float& center, - float& width) const; - - virtual bool GetRange(float& minValue, - float& maxValue) const; - }; -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyLayer.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,402 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "RadiographyLayer.h" - -#include <OrthancException.h> - - -namespace OrthancStone -{ - static double Square(double x) - { - return x * x; - } - - - RadiographyLayer::Geometry::Geometry() : - hasCrop_(false), - flipVertical_(false), - flipHorizontal_(false), - panX_(0), - panY_(0), - angle_(0), - resizeable_(false), - pixelSpacingX_(1), - pixelSpacingY_(1) - { - - } - - void RadiographyLayer::Geometry::GetCrop(unsigned int &x, unsigned int &y, unsigned int &width, unsigned int &height) const - { - if (!hasCrop_) - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); // you should probably use RadiographyLayer::GetCrop() or at least call HasCrop() before - - x = cropX_; - y = cropY_; - width = cropWidth_; - height = cropHeight_; - } - - void RadiographyLayer::UpdateTransform() - { - // important to update transform_ before getting the center to use the right scaling !!! - transform_ = AffineTransform2D::CreateScaling(geometry_.GetScalingX(), geometry_.GetScalingY()); - - double centerX, centerY; - GetCenter(centerX, centerY); - - transform_ = AffineTransform2D::Combine( - AffineTransform2D::CreateOffset(geometry_.GetPanX(), geometry_.GetPanY()), - AffineTransform2D::CreateRotation(geometry_.GetAngle(), centerX, centerY), - transform_); - - transformInverse_ = AffineTransform2D::Invert(transform_); - } - - - void RadiographyLayer::AddToExtent(Extent2D& extent, - double x, - double y) const - { - GetTransform().Apply(x, y); - extent.AddPoint(x, y); - } - - bool RadiographyLayer::Contains(double x, - double y) const - { - GetTransformInverse().Apply(x, y); - - unsigned int cropX, cropY, cropWidth, cropHeight; - GetCrop(cropX, cropY, cropWidth, cropHeight); - - return (x >= cropX && x <= cropX + cropWidth && - y >= cropY && y <= cropY + cropHeight); - } - - - void RadiographyLayer::DrawBorders(CairoContext& context, - double zoom) - { - if (GetControlPointCount() < 3 ) - return; - - cairo_t* cr = context.GetObject(); - cairo_set_line_width(cr, 2.0 / zoom); - - ControlPoint cp; - GetControlPoint(cp, 0); - cairo_move_to(cr, cp.x, cp.y); - - for (size_t i = 0; i < GetControlPointCount(); i++) - { - GetControlPoint(cp, i); - cairo_line_to(cr, cp.x, cp.y); - } - - cairo_close_path(cr); - cairo_stroke(cr); - } - - - RadiographyLayer::RadiographyLayer(const RadiographyScene& scene) : - index_(0), - hasSize_(false), - width_(0), - height_(0), - prefferedPhotometricDisplayMode_(RadiographyPhotometricDisplayMode_Default), - scene_(scene) - { - UpdateTransform(); - } - - void RadiographyLayer::ResetCrop() - { - geometry_.ResetCrop(); - UpdateTransform(); - } - - void RadiographyLayer::SetPreferredPhotomotricDisplayMode(RadiographyPhotometricDisplayMode prefferedPhotometricDisplayMode) - { - prefferedPhotometricDisplayMode_ = prefferedPhotometricDisplayMode; - - BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this)); - } - - void RadiographyLayer::SetCrop(unsigned int x, - unsigned int y, - unsigned int width, - unsigned int height) - { - if (!hasSize_) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - if (x + width > width_ || - y + height > height_) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - geometry_.SetCrop(x, y, width, height); - UpdateTransform(); - - BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this)); - } - - void RadiographyLayer::SetGeometry(const Geometry& geometry) - { - geometry_ = geometry; - - if (hasSize_) - { - UpdateTransform(); - } - - BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this)); - } - - - void RadiographyLayer::GetCrop(unsigned int& x, - unsigned int& y, - unsigned int& width, - unsigned int& height) const - { - if (GetGeometry().HasCrop()) - { - GetGeometry().GetCrop(x, y, width, height); - } - else - { - x = 0; - y = 0; - width = width_; - height = height_; - } - } - - - void RadiographyLayer::SetAngle(double angle) - { - geometry_.SetAngle(angle); - UpdateTransform(); - - BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this)); - } - - void RadiographyLayer::SetFlipVertical(bool flip) - { - geometry_.SetFlipVertical(flip); - UpdateTransform(); - - BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this)); - } - - void RadiographyLayer::SetFlipHorizontal(bool flip) - { - geometry_.SetFlipHorizontal(flip); - UpdateTransform(); - - BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this)); - } - - void RadiographyLayer::SetSize(unsigned int width, - unsigned int height, - bool emitLayerEditedEvent) - { - hasSize_ = true; - width_ = width; - height_ = height; - - UpdateTransform(); - - if (emitLayerEditedEvent) - { - BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this)); - } - } - - Extent2D RadiographyLayer::GetSceneExtent(bool /*minimal*/) const - { - Extent2D extent; - - unsigned int x, y, width, height; - GetCrop(x, y, width, height); - - double dx = static_cast<double>(x); - double dy = static_cast<double>(y); - double dwidth = static_cast<double>(width); - double dheight = static_cast<double>(height); - - // AddToExtent transforms the coordinates from image to scene - AddToExtent(extent, dx, dy); - AddToExtent(extent, dx + dwidth, dy); - AddToExtent(extent, dx, dy + dheight); - AddToExtent(extent, dx + dwidth, dy + dheight); - - return extent; - } - - - bool RadiographyLayer::GetPixel(unsigned int& imageX, - unsigned int& imageY, - double sceneX, - double sceneY) const - { - if (width_ == 0 || - height_ == 0) - { - return false; - } - else - { - GetTransformInverse().Apply(sceneX, sceneY); - - int x = static_cast<int>(std::floor(sceneX)); - int y = static_cast<int>(std::floor(sceneY)); - - if (x < 0) - { - imageX = 0; - } - else if (x >= static_cast<int>(width_)) - { - imageX = width_; - } - else - { - imageX = static_cast<unsigned int>(x); - } - - if (y < 0) - { - imageY = 0; - } - else if (y >= static_cast<int>(height_)) - { - imageY = height_; - } - else - { - imageY = static_cast<unsigned int>(y); - } - - return true; - } - } - - - void RadiographyLayer::SetPan(double x, - double y) - { - geometry_.SetPan(x, y); - UpdateTransform(); - BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this)); - } - - - void RadiographyLayer::SetPixelSpacing(double x, - double y, - bool emitLayerEditedEvent) - { - geometry_.SetPixelSpacing(x, y); - UpdateTransform(); - if (emitLayerEditedEvent) - { - BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this)); - } - } - - - void RadiographyLayer::GetCenter(double& centerX, - double& centerY) const - { - centerX = static_cast<double>(width_) / 2.0; - centerY = static_cast<double>(height_) / 2.0; - GetTransform().Apply(centerX, centerY); - } - - - - size_t RadiographyLayer::GetControlPointCount() const {return 4;} - - void RadiographyLayer::GetControlPoint(ControlPoint& cpScene /* out in scene coordinates */, - size_t index) const - { - unsigned int cropX, cropY, cropWidth, cropHeight; - GetCrop(cropX, cropY, cropWidth, cropHeight); - - ControlPoint cp; - switch (index) - { - case RadiographyControlPointType_TopLeftCorner: - cp = ControlPoint(cropX, cropY, RadiographyControlPointType_TopLeftCorner); - break; - - case RadiographyControlPointType_TopRightCorner: - cp = ControlPoint(cropX + cropWidth, cropY, RadiographyControlPointType_TopRightCorner); - break; - - case RadiographyControlPointType_BottomLeftCorner: - cp = ControlPoint(cropX, cropY + cropHeight, RadiographyControlPointType_BottomLeftCorner); - break; - - case RadiographyControlPointType_BottomRightCorner: - cp = ControlPoint(cropX + cropWidth, cropY + cropHeight, RadiographyControlPointType_BottomRightCorner); - break; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - // transforms image coordinates into scene coordinates - GetTransform().Apply(cp.x, cp.y); - cpScene = cp; - } - - bool RadiographyLayer::LookupControlPoint(ControlPoint& cpScene /* out */, - double x, - double y, - double zoom, - double viewportDistance) const - { - double threshold = Square(viewportDistance / zoom); - - for (size_t i = 0; i < GetControlPointCount(); i++) - { - ControlPoint cp; - GetControlPoint(cp, i); - - double d = Square(cp.x - x) + Square(cp.y - y); - - if (d <= threshold) - { - cpScene = cp; - return true; - } - } - - return false; - } -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyLayer.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,395 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include <algorithm> - -#include "../Toolbox/AffineTransform2D.h" -#include "../Toolbox/Extent2D.h" -#include "../Wrappers/CairoContext.h" -#include "../Messages/IMessage.h" -#include "../Messages/IObservable.h" - -namespace OrthancStone -{ - class RadiographyScene; - - enum RadiographyControlPointType - { - RadiographyControlPointType_TopLeftCorner = 0, - RadiographyControlPointType_TopRightCorner = 1, - RadiographyControlPointType_BottomRightCorner = 2, - RadiographyControlPointType_BottomLeftCorner = 3 - }; - - enum RadiographyPhotometricDisplayMode - { - RadiographyPhotometricDisplayMode_Default, - - RadiographyPhotometricDisplayMode_Monochrome1, - RadiographyPhotometricDisplayMode_Monochrome2 - }; - - - struct ControlPoint - { - double x; - double y; - size_t index; - - ControlPoint(double x, double y, size_t index) - : x(x), - y(y), - index(index) - {} - - ControlPoint() - : x(0), - y(0), - index(std::numeric_limits<size_t>::max()) - {} - }; - - class RadiographyLayer : public IObservable - { - friend class RadiographyScene; - - public: - ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, LayerEditedMessage, RadiographyLayer); - - class Geometry - { - bool hasCrop_; - unsigned int cropX_; - unsigned int cropY_; - unsigned int cropWidth_; - unsigned int cropHeight_; - bool flipVertical_; - bool flipHorizontal_; - double panX_; - double panY_; - double angle_; - bool resizeable_; - double pixelSpacingX_; - double pixelSpacingY_; - - public: - Geometry(); - - void ResetCrop() - { - hasCrop_ = false; - } - - void SetCrop(unsigned int x, - unsigned int y, - unsigned int width, - unsigned int height) - { - hasCrop_ = true; - cropX_ = x; - cropY_ = y; - cropWidth_ = width; - cropHeight_ = height; - } - - bool HasCrop() const - { - return hasCrop_; - } - - void GetCrop(unsigned int& x, - unsigned int& y, - unsigned int& width, - unsigned int& height) const; - - void SetAngle(double angle) - { - angle_ = angle; - } - - double GetAngle() const - { - return angle_; - } - - void SetPan(double x, - double y) - { - panX_ = x; - panY_ = y; - } - - double GetPanX() const - { - return panX_; - } - - double GetPanY() const - { - return panY_; - } - - bool IsResizeable() const - { - return resizeable_; - } - - void SetResizeable(bool resizeable) - { - resizeable_ = resizeable; - } - - void SetPixelSpacing(double x, - double y) - { - pixelSpacingX_ = x; - pixelSpacingY_ = y; - } - - double GetPixelSpacingX() const - { - return pixelSpacingX_; - } - - double GetPixelSpacingY() const - { - return pixelSpacingY_; - } - - void SetFlipVertical(bool flip) // mirrors image around an horizontal axis (note: flip is applied before the rotation !) - { - flipVertical_ = flip; - } - - void SetFlipHorizontal(bool flip) // mirrors image around a vertical axis (note: flip is applied before the rotation !) - { - flipHorizontal_ = flip; - } - - bool GetFlipVertical() const - { - return flipVertical_; - } - - bool GetFlipHorizontal() const - { - return flipHorizontal_; - } - - double GetScalingX() const - { - return (flipHorizontal_ ? - pixelSpacingX_: pixelSpacingX_); - } - - double GetScalingY() const - { - return (flipVertical_ ? - pixelSpacingY_: pixelSpacingY_); - } - }; - - private: - size_t index_; - bool hasSize_; - unsigned int width_; - unsigned int height_; - AffineTransform2D transform_; - AffineTransform2D transformInverse_; - Geometry geometry_; - RadiographyPhotometricDisplayMode prefferedPhotometricDisplayMode_; - const RadiographyScene& scene_; - - protected: - void SetPreferredPhotomotricDisplayMode(RadiographyPhotometricDisplayMode prefferedPhotometricDisplayMode); - - private: - void UpdateTransform(); - - void AddToExtent(Extent2D& extent, - double x, - double y) const; - - void SetIndex(size_t index) - { - index_ = index; - } - - bool Contains(double x, - double y) const; - - void DrawBorders(CairoContext& context, - double zoom); - - public: - RadiographyLayer(const RadiographyScene& scene); - - virtual ~RadiographyLayer() - { - } - - virtual const AffineTransform2D& GetTransform() const - { - return transform_; - } - - virtual const AffineTransform2D& GetTransformInverse() const - { - return transformInverse_; - } - - size_t GetIndex() const - { - return index_; - } - - const RadiographyScene& GetScene() const - { - return scene_; - } - - const Geometry& GetGeometry() const - { - return geometry_; - } - - void SetGeometry(const Geometry& geometry); - - void ResetCrop(); - - void SetCrop(unsigned int x, // those are pixel coordinates/size - unsigned int y, - unsigned int width, - unsigned int height); - - void SetCrop(const Extent2D& sceneExtent) - { - Extent2D imageCrop; - - { - double x = sceneExtent.GetX1(); - double y = sceneExtent.GetY1(); - GetTransformInverse().Apply(x, y); - imageCrop.AddPoint(x, y); - } - - { - double x = sceneExtent.GetX2(); - double y = sceneExtent.GetY2(); - GetTransformInverse().Apply(x, y); - imageCrop.AddPoint(x, y); - } - - SetCrop(static_cast<unsigned int>(std::max(0.0, std::floor(imageCrop.GetX1()))), - static_cast<unsigned int>(std::max(0.0, std::floor(imageCrop.GetY1()))), - std::min(width_, static_cast<unsigned int>(std::ceil(imageCrop.GetWidth()))), - std::min(height_, static_cast<unsigned int>(std::ceil(imageCrop.GetHeight()))) - ); - } - - - void GetCrop(unsigned int& x, - unsigned int& y, - unsigned int& width, - unsigned int& height) const; - - void SetAngle(double angle); - - void SetPan(double x, - double y); - - void SetFlipVertical(bool flip); // mirrors image around an horizontal axis (note: flip is applied before the rotation !) - - void SetFlipHorizontal(bool flip); // mirrors image around a vertical axis (note: flip is applied before the rotation !) - - void SetResizeable(bool resizeable) - { - geometry_.SetResizeable(resizeable); - } - - void SetSize(unsigned int width, - unsigned int height, - bool emitLayerEditedEvent = true); - - bool HasSize() const - { - return hasSize_; - } - - unsigned int GetWidth() const - { - return width_; - } - - unsigned int GetHeight() const - { - return height_; - } - - virtual Extent2D GetSceneExtent(bool minimal) const; - - virtual bool GetPixel(unsigned int& imageX, - unsigned int& imageY, - double sceneX, - double sceneY) const; - - void SetPixelSpacing(double x, - double y, - bool emitLayerEditedEvent = true); - - void GetCenter(double& centerX, - double& centerY) const; - - virtual void GetControlPoint(ControlPoint& cpScene /* out in scene coordinates */, - size_t index) const; - - virtual size_t GetControlPointCount() const; - - bool LookupControlPoint(ControlPoint& cpScene /* out */, - double x, - double y, - double zoom, - double viewportDistance) const; - - virtual bool GetDefaultWindowing(float& center, - float& width) const = 0; - - RadiographyPhotometricDisplayMode GetPreferredPhotomotricDisplayMode() const - { - return prefferedPhotometricDisplayMode_; - } - - virtual void Render(Orthanc::ImageAccessor& buffer, - const AffineTransform2D& viewTransform, - ImageInterpolation interpolation, - float windowCenter, - float windowWidth, - bool applyWindowing) const = 0; - - virtual bool GetRange(float& minValue, - float& maxValue) const = 0; - - virtual size_t GetApproximateMemoryUsage() const // this is used to limit the number of scenes loaded in RAM when resources are limited (we actually only count the size used by the images, not the C structs) - { - return 0; - } - }; -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyLayerCropTracker.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,145 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "RadiographyLayerCropTracker.h" - -#include "RadiographySceneCommand.h" - -#include <OrthancException.h> - -namespace OrthancStone -{ - class RadiographyLayerCropTracker::UndoRedoCommand : public RadiographySceneCommand - { - private: - unsigned int sourceCropX_; - unsigned int sourceCropY_; - unsigned int sourceCropWidth_; - unsigned int sourceCropHeight_; - unsigned int targetCropX_; - unsigned int targetCropY_; - unsigned int targetCropWidth_; - unsigned int targetCropHeight_; - - protected: - virtual void UndoInternal(RadiographyLayer& layer) const - { - layer.SetCrop(sourceCropX_, sourceCropY_, sourceCropWidth_, sourceCropHeight_); - } - - virtual void RedoInternal(RadiographyLayer& layer) const - { - layer.SetCrop(targetCropX_, targetCropY_, targetCropWidth_, targetCropHeight_); - } - - public: - UndoRedoCommand(const RadiographyLayerCropTracker& tracker) : - RadiographySceneCommand(tracker.accessor_), - sourceCropX_(tracker.cropX_), - sourceCropY_(tracker.cropY_), - sourceCropWidth_(tracker.cropWidth_), - sourceCropHeight_(tracker.cropHeight_) - { - tracker.accessor_.GetLayer().GetCrop(targetCropX_, targetCropY_, - targetCropWidth_, targetCropHeight_); - } - }; - - - RadiographyLayerCropTracker::RadiographyLayerCropTracker(UndoRedoStack& undoRedoStack, - RadiographyScene& scene, - const Deprecated::ViewportGeometry& view, - size_t layer, - const ControlPoint& startControlPoint) : - undoRedoStack_(undoRedoStack), - accessor_(scene, layer), - startControlPoint_(startControlPoint) - { - if (accessor_.IsValid()) - { - accessor_.GetLayer().GetCrop(cropX_, cropY_, cropWidth_, cropHeight_); - } - } - - - void RadiographyLayerCropTracker::Render(CairoContext& context, - double zoom) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - - - void RadiographyLayerCropTracker::MouseUp() - { - if (accessor_.IsValid()) - { - undoRedoStack_.Add(new UndoRedoCommand(*this)); - } - } - - - void RadiographyLayerCropTracker::MouseMove(int displayX, - int displayY, - double sceneX, - double sceneY, - const std::vector<Deprecated::Touch>& displayTouches, - const std::vector<Deprecated::Touch>& sceneTouches) - { - if (accessor_.IsValid()) - { - unsigned int x, y; - - RadiographyLayer& layer = accessor_.GetLayer(); - if (layer.GetPixel(x, y, sceneX, sceneY)) - { - unsigned int targetX, targetWidth; - - if (startControlPoint_.index == RadiographyControlPointType_TopLeftCorner || - startControlPoint_.index == RadiographyControlPointType_BottomLeftCorner) - { - targetX = std::min(x, cropX_ + cropWidth_); - targetWidth = cropX_ + cropWidth_ - targetX; - } - else - { - targetX = cropX_; - targetWidth = std::max(x, cropX_) - cropX_; - } - - unsigned int targetY, targetHeight; - - if (startControlPoint_.index == RadiographyControlPointType_TopLeftCorner || - startControlPoint_.index == RadiographyControlPointType_TopRightCorner) - { - targetY = std::min(y, cropY_ + cropHeight_); - targetHeight = cropY_ + cropHeight_ - targetY; - } - else - { - targetY = cropY_; - targetHeight = std::max(y, cropY_) - cropY_; - } - - layer.SetCrop(targetX, targetY, targetWidth, targetHeight); - } - } - } -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyLayerCropTracker.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../Toolbox/UndoRedoStack.h" -#include "../Deprecated/Toolbox/ViewportGeometry.h" -#include "../Deprecated/Widgets/IWorldSceneMouseTracker.h" -#include "RadiographyScene.h" - -namespace OrthancStone -{ - class RadiographyLayerCropTracker : public Deprecated::IWorldSceneMouseTracker - { - private: - class UndoRedoCommand; - - UndoRedoStack& undoRedoStack_; - RadiographyScene::LayerAccessor accessor_; - ControlPoint startControlPoint_; - unsigned int cropX_; - unsigned int cropY_; - unsigned int cropWidth_; - unsigned int cropHeight_; - - public: - RadiographyLayerCropTracker(UndoRedoStack& undoRedoStack, - RadiographyScene& scene, - const Deprecated::ViewportGeometry& view, - size_t layer, - const ControlPoint& startControlPoint); - - virtual bool HasRender() const - { - return false; - } - - virtual void Render(CairoContext& context, - double zoom); - - virtual void MouseUp(); - - virtual void MouseMove(int displayX, - int displayY, - double sceneX, - double sceneY, - const std::vector<Deprecated::Touch>& displayTouches, - const std::vector<Deprecated::Touch>& sceneTouches); - }; -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyLayerMaskTracker.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "RadiographyLayerMaskTracker.h" -#include "RadiographyMaskLayer.h" - -#include "RadiographySceneCommand.h" - -#include <OrthancException.h> - -namespace OrthancStone -{ - class RadiographyLayerMaskTracker::UndoRedoCommand : public RadiographySceneCommand - { - private: - ControlPoint sourceSceneCp_; - ControlPoint targetSceneCp_; - - protected: - virtual void UndoInternal(RadiographyLayer& layer) const - { - RadiographyMaskLayer* maskLayer = dynamic_cast<RadiographyMaskLayer*>(&layer); - if (maskLayer == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - unsigned int ix, iy; // image coordinates - if (maskLayer->GetPixel(ix, iy, sourceSceneCp_.x, sourceSceneCp_.y)) - { - maskLayer->SetCorner(Orthanc::ImageProcessing::ImagePoint((int32_t)ix, (int32_t)iy), sourceSceneCp_.index); - } - } - - virtual void RedoInternal(RadiographyLayer& layer) const - { - RadiographyMaskLayer* maskLayer = dynamic_cast<RadiographyMaskLayer*>(&layer); - if (maskLayer == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - unsigned int ix, iy; // image coordinates - if (maskLayer->GetPixel(ix, iy, targetSceneCp_.x, targetSceneCp_.y)) - { - maskLayer->SetCorner(Orthanc::ImageProcessing::ImagePoint((int32_t)ix, (int32_t)iy), targetSceneCp_.index); - } - } - - public: - UndoRedoCommand(const RadiographyLayerMaskTracker& tracker) : - RadiographySceneCommand(tracker.accessor_), - sourceSceneCp_(tracker.startSceneCp_), - targetSceneCp_(tracker.endSceneCp_) - { - RadiographyMaskLayer* maskLayer = dynamic_cast<RadiographyMaskLayer*>(&(tracker.accessor_.GetLayer())); - if (maskLayer == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - unsigned int ix, iy; // image coordinates - if (maskLayer->GetPixel(ix, iy, targetSceneCp_.x, targetSceneCp_.y)) - { - maskLayer->SetCorner(Orthanc::ImageProcessing::ImagePoint((int32_t)ix, (int32_t)iy), targetSceneCp_.index); - } - } - }; - - - RadiographyLayerMaskTracker::RadiographyLayerMaskTracker(UndoRedoStack& undoRedoStack, - RadiographyScene& scene, - const Deprecated::ViewportGeometry& view, - size_t layer, - const ControlPoint& startSceneControlPoint) : - undoRedoStack_(undoRedoStack), - accessor_(scene, layer), - startSceneCp_(startSceneControlPoint), - endSceneCp_(startSceneControlPoint) - { - } - - - void RadiographyLayerMaskTracker::Render(CairoContext& context, - double zoom) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - - - void RadiographyLayerMaskTracker::MouseUp() - { - if (accessor_.IsValid() && startSceneCp_.x != endSceneCp_.x && startSceneCp_.y != endSceneCp_.y) - { - undoRedoStack_.Add(new UndoRedoCommand(*this)); - } - } - - - void RadiographyLayerMaskTracker::MouseMove(int displayX, - int displayY, - double sceneX, - double sceneY, - const std::vector<Deprecated::Touch>& displayTouches, - const std::vector<Deprecated::Touch>& sceneTouches) - { - if (accessor_.IsValid()) - { - unsigned int ix, iy; // image coordinates - - RadiographyLayer& layer = accessor_.GetLayer(); - if (layer.GetPixel(ix, iy, sceneX, sceneY)) - { - endSceneCp_ = ControlPoint(sceneX, sceneY, startSceneCp_.index); - - RadiographyMaskLayer* maskLayer = dynamic_cast<RadiographyMaskLayer*>(&layer); - if (maskLayer == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - maskLayer->SetCorner(Orthanc::ImageProcessing::ImagePoint((int32_t)ix, (int32_t)iy), startSceneCp_.index); - } - } - } -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyLayerMaskTracker.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../Toolbox/UndoRedoStack.h" -#include "../Deprecated/Toolbox/ViewportGeometry.h" -#include "../Deprecated/Widgets/IWorldSceneMouseTracker.h" -#include "RadiographyScene.h" - -namespace OrthancStone -{ - class RadiographyLayerMaskTracker : public Deprecated::IWorldSceneMouseTracker - { - private: - class UndoRedoCommand; - - UndoRedoStack& undoRedoStack_; - RadiographyScene::LayerAccessor accessor_; - ControlPoint startSceneCp_; - ControlPoint endSceneCp_; - - public: - RadiographyLayerMaskTracker(UndoRedoStack& undoRedoStack, - RadiographyScene& scene, - const Deprecated::ViewportGeometry& view, - size_t layer, - const ControlPoint& startSceneControlPoint); - - virtual bool HasRender() const - { - return false; - } - - virtual void Render(CairoContext& context, - double zoom); - - virtual void MouseUp(); - - virtual void MouseMove(int displayX, - int displayY, - double sceneX, - double sceneY, - const std::vector<Deprecated::Touch>& displayTouches, - const std::vector<Deprecated::Touch>& sceneTouches); - }; -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyLayerMoveTracker.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,126 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "RadiographyLayerMoveTracker.h" - -#include "RadiographySceneCommand.h" - -#include <OrthancException.h> - -namespace OrthancStone -{ - class RadiographyLayerMoveTracker::UndoRedoCommand : public RadiographySceneCommand - { - private: - double sourceX_; - double sourceY_; - double targetX_; - double targetY_; - - protected: - virtual void UndoInternal(RadiographyLayer& layer) const - { - layer.SetPan(sourceX_, sourceY_); - } - - virtual void RedoInternal(RadiographyLayer& layer) const - { - layer.SetPan(targetX_, targetY_); - } - - public: - UndoRedoCommand(const RadiographyLayerMoveTracker& tracker) : - RadiographySceneCommand(tracker.accessor_), - sourceX_(tracker.panX_), - sourceY_(tracker.panY_), - targetX_(tracker.accessor_.GetLayer().GetGeometry().GetPanX()), - targetY_(tracker.accessor_.GetLayer().GetGeometry().GetPanY()) - { - } - }; - - - RadiographyLayerMoveTracker::RadiographyLayerMoveTracker(UndoRedoStack& undoRedoStack, - RadiographyScene& scene, - size_t layer, - double x, - double y, - bool oneAxis) : - undoRedoStack_(undoRedoStack), - accessor_(scene, layer), - clickX_(x), - clickY_(y), - oneAxis_(oneAxis) - { - if (accessor_.IsValid()) - { - panX_ = accessor_.GetLayer().GetGeometry().GetPanX(); - panY_ = accessor_.GetLayer().GetGeometry().GetPanY(); - } - } - - - void RadiographyLayerMoveTracker::Render(CairoContext& context, - double zoom) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - - - void RadiographyLayerMoveTracker::MouseUp() - { - if (accessor_.IsValid()) - { - undoRedoStack_.Add(new UndoRedoCommand(*this)); - } - } - - - void RadiographyLayerMoveTracker::MouseMove(int displayX, - int displayY, - double sceneX, - double sceneY, - const std::vector<Deprecated::Touch>& displayTouches, - const std::vector<Deprecated::Touch>& sceneTouches) - { - if (accessor_.IsValid()) - { - double dx = sceneX - clickX_; - double dy = sceneY - clickY_; - - if (oneAxis_) - { - if (fabs(dx) > fabs(dy)) - { - accessor_.GetLayer().SetPan(dx + panX_, panY_); - } - else - { - accessor_.GetLayer().SetPan(panX_, dy + panY_); - } - } - else - { - accessor_.GetLayer().SetPan(dx + panX_, dy + panY_); - } - } - } -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyLayerMoveTracker.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../Toolbox/UndoRedoStack.h" -#include "../Deprecated/Widgets/IWorldSceneMouseTracker.h" -#include "RadiographyScene.h" - -namespace OrthancStone -{ - class RadiographyLayerMoveTracker : public Deprecated::IWorldSceneMouseTracker - { - private: - class UndoRedoCommand; - - UndoRedoStack& undoRedoStack_; - RadiographyScene::LayerAccessor accessor_; - double clickX_; - double clickY_; - double panX_; - double panY_; - bool oneAxis_; - - public: - RadiographyLayerMoveTracker(UndoRedoStack& undoRedoStack, - RadiographyScene& scene, - size_t layer, - double x, - double y, - bool oneAxis); - - virtual bool HasRender() const - { - return false; - } - - virtual void Render(CairoContext& context, - double zoom); - - virtual void MouseUp(); - - virtual void MouseMove(int displayX, - int displayY, - double sceneX, - double sceneY, - const std::vector<Deprecated::Touch>& displayTouches, - const std::vector<Deprecated::Touch>& sceneTouches); - }; -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyLayerResizeTracker.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,188 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "RadiographyLayerResizeTracker.h" - -#include "RadiographySceneCommand.h" - -#include <OrthancException.h> - -#include <boost/math/special_functions/round.hpp> - - -namespace OrthancStone -{ - static double ComputeDistance(double x1, - double y1, - double x2, - double y2) - { - double dx = x1 - x2; - double dy = y1 - y2; - return sqrt(dx * dx + dy * dy); - } - - - class RadiographyLayerResizeTracker::UndoRedoCommand : public RadiographySceneCommand - { - private: - double sourceSpacingX_; - double sourceSpacingY_; - double sourcePanX_; - double sourcePanY_; - double targetSpacingX_; - double targetSpacingY_; - double targetPanX_; - double targetPanY_; - - protected: - virtual void UndoInternal(RadiographyLayer& layer) const - { - layer.SetPixelSpacing(sourceSpacingX_, sourceSpacingY_); - layer.SetPan(sourcePanX_, sourcePanY_); - } - - virtual void RedoInternal(RadiographyLayer& layer) const - { - layer.SetPixelSpacing(targetSpacingX_, targetSpacingY_); - layer.SetPan(targetPanX_, targetPanY_); - } - - public: - UndoRedoCommand(const RadiographyLayerResizeTracker& tracker) : - RadiographySceneCommand(tracker.accessor_), - sourceSpacingX_(tracker.originalSpacingX_), - sourceSpacingY_(tracker.originalSpacingY_), - sourcePanX_(tracker.originalPanX_), - sourcePanY_(tracker.originalPanY_), - targetSpacingX_(tracker.accessor_.GetLayer().GetGeometry().GetPixelSpacingX()), - targetSpacingY_(tracker.accessor_.GetLayer().GetGeometry().GetPixelSpacingY()), - targetPanX_(tracker.accessor_.GetLayer().GetGeometry().GetPanX()), - targetPanY_(tracker.accessor_.GetLayer().GetGeometry().GetPanY()) - { - } - }; - - - RadiographyLayerResizeTracker::RadiographyLayerResizeTracker(UndoRedoStack& undoRedoStack, - RadiographyScene& scene, - size_t layer, - const ControlPoint& startControlPoint, - bool roundScaling) : - undoRedoStack_(undoRedoStack), - accessor_(scene, layer), - roundScaling_(roundScaling) - { - if (accessor_.IsValid() && - accessor_.GetLayer().GetGeometry().IsResizeable()) - { - originalSpacingX_ = accessor_.GetLayer().GetGeometry().GetPixelSpacingX(); - originalSpacingY_ = accessor_.GetLayer().GetGeometry().GetPixelSpacingY(); - originalPanX_ = accessor_.GetLayer().GetGeometry().GetPanX(); - originalPanY_ = accessor_.GetLayer().GetGeometry().GetPanY(); - - size_t oppositeControlPointType; - switch (startControlPoint.index) - { - case RadiographyControlPointType_TopLeftCorner: - oppositeControlPointType = RadiographyControlPointType_BottomRightCorner; - break; - - case RadiographyControlPointType_TopRightCorner: - oppositeControlPointType = RadiographyControlPointType_BottomLeftCorner; - break; - - case RadiographyControlPointType_BottomLeftCorner: - oppositeControlPointType = RadiographyControlPointType_TopRightCorner; - break; - - case RadiographyControlPointType_BottomRightCorner: - oppositeControlPointType = RadiographyControlPointType_TopLeftCorner; - break; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - - accessor_.GetLayer().GetControlPoint(startOppositeControlPoint_, oppositeControlPointType); - - double d = ComputeDistance(startControlPoint.x, startControlPoint.y, startOppositeControlPoint_.x, startOppositeControlPoint_.y); - if (d >= std::numeric_limits<float>::epsilon()) - { - baseScaling_ = 1.0 / d; - } - else - { - // Avoid division by zero in extreme cases - accessor_.Invalidate(); - } - } - } - - - void RadiographyLayerResizeTracker::Render(CairoContext& context, - double zoom) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - - - void RadiographyLayerResizeTracker::MouseUp() - { - if (accessor_.IsValid() && - accessor_.GetLayer().GetGeometry().IsResizeable()) - { - undoRedoStack_.Add(new UndoRedoCommand(*this)); - } - } - - - void RadiographyLayerResizeTracker::MouseMove(int displayX, - int displayY, - double sceneX, - double sceneY, - const std::vector<Deprecated::Touch>& displayTouches, - const std::vector<Deprecated::Touch>& sceneTouches) - { - static const double ROUND_SCALING = 0.1; - - if (accessor_.IsValid() && - accessor_.GetLayer().GetGeometry().IsResizeable()) - { - double scaling = ComputeDistance(startOppositeControlPoint_.x, startOppositeControlPoint_.y, sceneX, sceneY) * baseScaling_; - - if (roundScaling_) - { - scaling = boost::math::round<double>((scaling / ROUND_SCALING) * ROUND_SCALING); - } - - RadiographyLayer& layer = accessor_.GetLayer(); - layer.SetPixelSpacing(scaling * originalSpacingX_, - scaling * originalSpacingY_); - - // Keep the opposite corner at a fixed location - ControlPoint currentOppositeCorner; - layer.GetControlPoint(currentOppositeCorner, startOppositeControlPoint_.index); - layer.SetPan(layer.GetGeometry().GetPanX() + startOppositeControlPoint_.x - currentOppositeCorner.x, - layer.GetGeometry().GetPanY() + startOppositeControlPoint_.y - currentOppositeCorner.y); - } - } -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyLayerResizeTracker.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../Toolbox/UndoRedoStack.h" -#include "../Deprecated/Widgets/IWorldSceneMouseTracker.h" -#include "RadiographyScene.h" - -namespace OrthancStone -{ - class RadiographyLayerResizeTracker : public Deprecated::IWorldSceneMouseTracker - { - private: - class UndoRedoCommand; - - UndoRedoStack& undoRedoStack_; - RadiographyScene::LayerAccessor accessor_; - bool roundScaling_; - double originalSpacingX_; - double originalSpacingY_; - double originalPanX_; - double originalPanY_; - ControlPoint startOppositeControlPoint_; - double baseScaling_; - - public: - RadiographyLayerResizeTracker(UndoRedoStack& undoRedoStack, - RadiographyScene& scene, - size_t layer, - const ControlPoint& startControlPoint, - bool roundScaling); - - virtual bool HasRender() const - { - return false; - } - - virtual void Render(CairoContext& context, - double zoom); - - virtual void MouseUp(); - - virtual void MouseMove(int displayX, - int displayY, - double sceneX, - double sceneY, - const std::vector<Deprecated::Touch>& displayTouches, - const std::vector<Deprecated::Touch>& sceneTouches); - }; -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyLayerRotateTracker.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,156 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "RadiographyLayerRotateTracker.h" - -#include "RadiographySceneCommand.h" - -#include <OrthancException.h> - -#include <boost/math/constants/constants.hpp> -#include <boost/math/special_functions/round.hpp> - -namespace OrthancStone -{ - class RadiographyLayerRotateTracker::UndoRedoCommand : public RadiographySceneCommand - { - private: - double sourceAngle_; - double targetAngle_; - - static int ToDegrees(double angle) - { - return boost::math::iround(angle * 180.0 / boost::math::constants::pi<double>()); - } - - protected: - virtual void UndoInternal(RadiographyLayer& layer) const - { - LOG(INFO) << "Undo - Set angle to " << ToDegrees(sourceAngle_) << " degrees"; - layer.SetAngle(sourceAngle_); - } - - virtual void RedoInternal(RadiographyLayer& layer) const - { - LOG(INFO) << "Redo - Set angle to " << ToDegrees(sourceAngle_) << " degrees"; - layer.SetAngle(targetAngle_); - } - - public: - UndoRedoCommand(const RadiographyLayerRotateTracker& tracker) : - RadiographySceneCommand(tracker.accessor_), - sourceAngle_(tracker.originalAngle_), - targetAngle_(tracker.accessor_.GetLayer().GetGeometry().GetAngle()) - { - } - }; - - - bool RadiographyLayerRotateTracker::ComputeAngle(double& angle /* out */, - double sceneX, - double sceneY) const - { - Vector u; - LinearAlgebra::AssignVector(u, sceneX - centerX_, sceneY - centerY_); - - double nu = boost::numeric::ublas::norm_2(u); - - if (!LinearAlgebra::IsCloseToZero(nu)) - { - u /= nu; - angle = atan2(u[1], u[0]); - return true; - } - else - { - return false; - } - } - - - RadiographyLayerRotateTracker::RadiographyLayerRotateTracker(UndoRedoStack& undoRedoStack, - RadiographyScene& scene, - const Deprecated::ViewportGeometry& view, - size_t layer, - double x, - double y, - bool roundAngles) : - undoRedoStack_(undoRedoStack), - accessor_(scene, layer), - roundAngles_(roundAngles) - { - if (accessor_.IsValid()) - { - accessor_.GetLayer().GetCenter(centerX_, centerY_); - originalAngle_ = accessor_.GetLayer().GetGeometry().GetAngle(); - - double sceneX, sceneY; - view.MapDisplayToScene(sceneX, sceneY, x, y); - - if (!ComputeAngle(clickAngle_, x, y)) - { - accessor_.Invalidate(); - } - } - } - - - void RadiographyLayerRotateTracker::Render(CairoContext& context, - double zoom) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - - - void RadiographyLayerRotateTracker::MouseUp() - { - if (accessor_.IsValid()) - { - undoRedoStack_.Add(new UndoRedoCommand(*this)); - } - } - - - void RadiographyLayerRotateTracker::MouseMove(int displayX, - int displayY, - double sceneX, - double sceneY, - const std::vector<Deprecated::Touch>& displayTouches, - const std::vector<Deprecated::Touch>& sceneTouches) - { - static const double ROUND_ANGLE = 15.0 / 180.0 * boost::math::constants::pi<double>(); - - double angle; - - if (accessor_.IsValid() && - ComputeAngle(angle, sceneX, sceneY)) - { - angle = angle - clickAngle_ + originalAngle_; - - if (roundAngles_) - { - angle = boost::math::round<double>((angle / ROUND_ANGLE) * ROUND_ANGLE); - } - - accessor_.GetLayer().SetAngle(angle); - } - } -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyLayerRotateTracker.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../Toolbox/UndoRedoStack.h" -#include "../Deprecated/Toolbox/ViewportGeometry.h" -#include "../Deprecated/Widgets/IWorldSceneMouseTracker.h" -#include "RadiographyScene.h" - - -namespace OrthancStone -{ - class RadiographyLayerRotateTracker : public Deprecated::IWorldSceneMouseTracker - { - private: - class UndoRedoCommand; - - UndoRedoStack& undoRedoStack_; - RadiographyScene::LayerAccessor accessor_; - double centerX_; - double centerY_; - double originalAngle_; - double clickAngle_; - bool roundAngles_; - - bool ComputeAngle(double& angle /* out */, - double sceneX, - double sceneY) const; - - public: - RadiographyLayerRotateTracker(UndoRedoStack& undoRedoStack, - RadiographyScene& scene, - const Deprecated::ViewportGeometry& view, - size_t layer, - double x, - double y, - bool roundAngles); - - virtual bool HasRender() const - { - return false; - } - - virtual void Render(CairoContext& context, - double zoom); - - virtual void MouseUp(); - - virtual void MouseMove(int displayX, - int displayY, - double sceneX, - double sceneY, - const std::vector<Deprecated::Touch>& displayTouches, - const std::vector<Deprecated::Touch>& sceneTouches); - }; -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyMaskLayer.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,200 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "RadiographyMaskLayer.h" -#include "RadiographyDicomLayer.h" - -#include "RadiographyScene.h" -#include "../Toolbox/ImageGeometry.h" - -#include <Images/Image.h> -#include <Images/ImageProcessing.h> -#include <OrthancException.h> - -namespace OrthancStone -{ - const unsigned char IN_MASK_VALUE = 0x77; - const unsigned char OUT_MASK_VALUE = 0xFF; - - const AffineTransform2D& RadiographyMaskLayer::GetTransform() const - { - return dicomLayer_.GetTransform(); - } - - const AffineTransform2D& RadiographyMaskLayer::GetTransformInverse() const - { - return dicomLayer_.GetTransformInverse(); - } - - bool RadiographyMaskLayer::GetPixel(unsigned int& imageX, - unsigned int& imageY, - double sceneX, - double sceneY) const - { - return dicomLayer_.GetPixel(imageX, imageY, sceneX, sceneY); - } - - std::string RadiographyMaskLayer::GetInstanceId() const - { - return dicomLayer_.GetInstanceId(); - } - - void RadiographyMaskLayer::SetCorner(const Orthanc::ImageProcessing::ImagePoint& corner, size_t index) - { - if (index < corners_.size()) - corners_[index] = corner; - else - corners_.push_back(corner); - invalidated_ = true; - - BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this)); - } - - void RadiographyMaskLayer::SetCorners(const std::vector<Orthanc::ImageProcessing::ImagePoint>& corners) - { - corners_ = corners; - invalidated_ = true; - - BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this)); - } - - Extent2D RadiographyMaskLayer::GetSceneExtent(bool minimal) const - { - if (!minimal) - { - return RadiographyLayer::GetSceneExtent(minimal); - } - else - { // get the extent of the in-mask area - Extent2D sceneExtent; - - for (std::vector<Orthanc::ImageProcessing::ImagePoint>::const_iterator corner = corners_.begin(); corner != corners_.end(); ++corner) - { - double x = static_cast<double>(corner->GetX()); - double y = static_cast<double>(corner->GetY()); - - dicomLayer_.GetTransform().Apply(x, y); - sceneExtent.AddPoint(x, y); - } - return sceneExtent; - } - } - - - - void RadiographyMaskLayer::Render(Orthanc::ImageAccessor& buffer, - const AffineTransform2D& viewTransform, - ImageInterpolation interpolation, - float windowCenter, - float windowWidth, - bool applyWindowing) const - { - if (dicomLayer_.GetWidth() == 0 || dicomLayer_.GetSourceImage() == NULL) // nothing to do if the DICOM layer is not displayed (or not loaded) - return; - - if (invalidated_) - { - mask_.reset(new Orthanc::Image(Orthanc::PixelFormat_Grayscale8, dicomLayer_.GetWidth(), dicomLayer_.GetHeight(), false)); - - DrawMask(); - - invalidated_ = false; - } - - {// rendering - if (buffer.GetFormat() != Orthanc::PixelFormat_Float32) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); - } - - unsigned int cropX, cropY, cropWidth, cropHeight; - dicomLayer_.GetCrop(cropX, cropY, cropWidth, cropHeight); - - const AffineTransform2D t = AffineTransform2D::Combine( - viewTransform, dicomLayer_.GetTransform(), - AffineTransform2D::CreateOffset(cropX, cropY)); - - Orthanc::ImageAccessor cropped; - mask_->GetRegion(cropped, cropX, cropY, cropWidth, cropHeight); - - Orthanc::Image tmp(Orthanc::PixelFormat_Grayscale8, buffer.GetWidth(), buffer.GetHeight(), false); - - - unsigned int x1, y1, x2, y2; - if (!OrthancStone::GetProjectiveTransformExtent(x1, y1, x2, y2, - t.GetHomogeneousMatrix(), - cropped.GetWidth(), - cropped.GetHeight(), - buffer.GetWidth(), - buffer.GetHeight())) - { - return; // layer is outside the buffer - } - - t.Apply(tmp, cropped, ImageInterpolation_Nearest, true /* clear */); - - // we have observed vertical lines at the image border (probably due to bilinear filtering of the DICOM image when it is not aligned with the buffer pixels) - // -> draw the mask one line further on each side - if (x1 >= 1) - { - x1 = x1 - 1; - } - if (x2 < buffer.GetWidth() - 2) - { - x2 = x2 + 1; - } - - // Blit - for (unsigned int y = y1; y <= y2; y++) - { - float *q = reinterpret_cast<float*>(buffer.GetRow(y)) + x1; - const uint8_t *p = reinterpret_cast<uint8_t*>(tmp.GetRow(y)) + x1; - - for (unsigned int x = x1; x <= x2; x++, p++, q++) - { - if (*p != IN_MASK_VALUE) - *q = foreground_; - // else keep the underlying pixel value - } - } - - } - } - - void RadiographyMaskLayer::DrawMask() const - { - // first fill the complete image - Orthanc::ImageProcessing::Set(*mask_, OUT_MASK_VALUE); - - // clip corners - std::vector<Orthanc::ImageProcessing::ImagePoint> clippedCorners; - for (size_t i = 0; i < corners_.size(); i++) - { - clippedCorners.push_back(corners_[i]); - clippedCorners[i].ClipTo(0, mask_->GetWidth() - 1, 0, mask_->GetHeight() - 1); - } - - // fill mask - Orthanc::ImageProcessing::FillPolygon(*mask_, clippedCorners, IN_MASK_VALUE); - - } - -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyMaskLayer.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,146 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "RadiographyLayer.h" - -#include <Compatibility.h> -#include <Images/Image.h> -#include <Images/ImageProcessing.h> - -namespace OrthancStone -{ - class RadiographyScene; - class RadiographyDicomLayer; - - class RadiographyMaskLayer : public RadiographyLayer - { - private: - std::vector<Orthanc::ImageProcessing::ImagePoint> corners_; - const RadiographyDicomLayer& dicomLayer_; - mutable bool invalidated_; - float foreground_; - - mutable std::unique_ptr<Orthanc::ImageAccessor> mask_; - public: - RadiographyMaskLayer(const RadiographyScene& scene, const RadiographyDicomLayer& dicomLayer, - float foreground) : - RadiographyLayer(scene), - dicomLayer_(dicomLayer), - invalidated_(true), - foreground_(foreground) - { - } - - virtual size_t GetApproximateMemoryUsage() const - { - size_t size = 0; - if (mask_.get() != NULL) - { - size += mask_->GetPitch() * mask_->GetHeight(); - } - - return size; - } - - - void SetCorners(const std::vector<Orthanc::ImageProcessing::ImagePoint>& corners); - void SetCorner(const Orthanc::ImageProcessing::ImagePoint& corner, size_t index); - - const std::vector<Orthanc::ImageProcessing::ImagePoint>& GetCorners() const - { - return corners_; - } - - float GetForeground() const - { - return foreground_; - } - - virtual void Render(Orthanc::ImageAccessor& buffer, - const AffineTransform2D& viewTransform, - ImageInterpolation interpolation, - float windowCenter, - float windowWidth, - bool applyWindowing) const; - - std::string GetInstanceId() const; - - virtual size_t GetControlPointCount() const - { - return corners_.size(); - } - - virtual void GetControlPoint(ControlPoint& cpScene, - size_t index) const - { - ControlPoint cp(corners_[index].GetX(), corners_[index].GetY(), index); - - // transforms image coordinates into scene coordinates - GetTransform().Apply(cp.x, cp.y); - cpScene = cp; - } - - virtual Extent2D GetSceneExtent(bool minimal) const; - - virtual bool GetDefaultWindowing(float& center, - float& width) const - { - return false; - } - - virtual bool GetRange(float& minValue, - float& maxValue) const - { - minValue = 0; - maxValue = 0; - - if (foreground_ < 0) - { - minValue = foreground_; - } - - if (foreground_ > 0) - { - maxValue = foreground_; - } - - return true; - - } - - virtual bool GetPixel(unsigned int& imageX, - unsigned int& imageY, - double sceneX, - double sceneY) const; - - protected: - virtual const AffineTransform2D& GetTransform() const; - - virtual const AffineTransform2D& GetTransformInverse() const; - - - private: - void DrawMask() const; - - }; -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyScene.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,968 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "RadiographyScene.h" - -#include "RadiographyAlphaLayer.h" -#include "RadiographyDicomLayer.h" -#include "RadiographyTextLayer.h" -#include "RadiographyMaskLayer.h" -#include "../Deprecated/Toolbox/DicomFrameConverter.h" -#include "../Scene2D/CairoCompositor.h" -#include "../Scene2D/FloatTextureSceneLayer.h" -#include "../Scene2D/TextSceneLayer.h" - -#include <Images/Image.h> -#include <Images/ImageProcessing.h> -#include <Images/PamReader.h> -#include <Images/PamWriter.h> -#include <Images/PngWriter.h> -#include <OrthancException.h> -#include <Toolbox.h> -#include <DicomDatasetReader.h> -#include <FullOrthancDataset.h> - -#include <boost/math/special_functions/round.hpp> - - -namespace OrthancStone -{ - RadiographyScene::LayerAccessor::LayerAccessor(RadiographyScene& scene, - size_t index) : - scene_(scene), - index_(index) - { - Layers::iterator layer = scene.layers_.find(index); - if (layer == scene.layers_.end()) - { - layer_ = NULL; - } - else - { - assert(layer->second != NULL); - layer_ = layer->second; - } - } - - - RadiographyScene::LayerAccessor::LayerAccessor(RadiographyScene& scene, - double x, - double y) : - scene_(scene), - index_(0) // Dummy initialization - { - if (scene.LookupLayer(index_, x, y)) - { - Layers::iterator layer = scene.layers_.find(index_); - - if (layer == scene.layers_.end()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - else - { - assert(layer->second != NULL); - layer_ = layer->second; - } - } - else - { - layer_ = NULL; - } - } - - - RadiographyScene& RadiographyScene::LayerAccessor::GetScene() const - { - if (IsValid()) - { - return scene_; - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - } - - - size_t RadiographyScene::LayerAccessor::GetIndex() const - { - if (IsValid()) - { - return index_; - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - } - - - RadiographyLayer& RadiographyScene::LayerAccessor::GetLayer() const - { - if (IsValid()) - { - return *layer_; - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - } - - void RadiographyScene::_RegisterLayer(RadiographyLayer* layer) - { - std::unique_ptr<RadiographyLayer> raii(layer); - - // LOG(INFO) << "Registering layer: " << countLayers_; - - size_t index = nextLayerIndex_++; - raii->SetIndex(index); - layers_[index] = raii.release(); - } - - RadiographyLayer& RadiographyScene::RegisterLayer(RadiographyLayer* layer) - { - if (layer == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); - } - - _RegisterLayer(layer); - - BroadcastMessage(GeometryChangedMessage(*this, *layer)); - BroadcastMessage(ContentChangedMessage(*this, *layer)); - Register<RadiographyLayer::LayerEditedMessage>(*layer, &RadiographyScene::OnLayerEdited); - - return *layer; - } - - size_t RadiographyScene::GetApproximateMemoryUsage() const - { - size_t size = 0; - for (Layers::const_iterator it = layers_.begin(); it != layers_.end(); it++) - { - size += it->second->GetApproximateMemoryUsage(); - } - return size; - } - - void RadiographyScene::OnLayerEdited(const RadiographyLayer::LayerEditedMessage& message) - { - BroadcastMessage(RadiographyScene::LayerEditedMessage(*this, message.GetOrigin())); - } - - - RadiographyScene::RadiographyScene() : - nextLayerIndex_(0), - hasWindowing_(false), - windowingCenter_(0), // Dummy initialization - windowingWidth_(0) // Dummy initialization - { - } - - - RadiographyScene::~RadiographyScene() - { - for (Layers::iterator it = layers_.begin(); it != layers_.end(); it++) - { - assert(it->second != NULL); - delete it->second; - } - } - - RadiographyPhotometricDisplayMode RadiographyScene::GetPreferredPhotomotricDisplayMode() const - { - // return the mode of the first layer who "cares" about its display mode (normaly, the one and only layer that is a DicomLayer) - for (Layers::const_iterator it = layers_.begin(); it != layers_.end(); it++) - { - if (it->second->GetPreferredPhotomotricDisplayMode() != RadiographyPhotometricDisplayMode_Default) - { - return it->second->GetPreferredPhotomotricDisplayMode(); - } - } - - return RadiographyPhotometricDisplayMode_Default; - } - - - void RadiographyScene::GetLayersIndexes(std::vector<size_t>& output) const - { - for (Layers::const_iterator it = layers_.begin(); it != layers_.end(); it++) - { - output.push_back(it->first); - } - } - - void RadiographyScene::RemoveLayer(size_t layerIndex) - { - LOG(INFO) << "Removing layer: " << layerIndex; - - Layers::iterator found = layers_.find(layerIndex); - - if (found == layers_.end()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - else - { - assert(found->second != NULL); - delete found->second; - - layers_.erase(found); - - LOG(INFO) << "Removing layer, there are now : " << layers_.size() << " layers"; - - _OnLayerRemoved(); - - BroadcastMessage(RadiographyScene::LayerRemovedMessage(*this, layerIndex)); - } - } - - const RadiographyLayer& RadiographyScene::GetLayer(size_t layerIndex) const - { - Layers::const_iterator found = layers_.find(layerIndex); - - if (found == layers_.end()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - else - { - assert(found->second != NULL); - return *found->second; - } - } - - RadiographyLayer& RadiographyScene::GetLayer(size_t layerIndex) - { - Layers::const_iterator found = layers_.find(layerIndex); - - if (found == layers_.end()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - else - { - assert(found->second != NULL); - return *found->second; - } - } - - bool RadiographyScene::GetWindowing(float& center, - float& width) const - { - if (hasWindowing_) - { - center = windowingCenter_; - width = windowingWidth_; - return true; - } - else - { - return false; - } - } - - - void RadiographyScene::GetWindowingWithDefault(float& center, - float& width) const - { - if (!GetWindowing(center, width)) - { - center = 128; - width = 256; - } - } - - - void RadiographyScene::SetWindowing(float center, - float width) - { - hasWindowing_ = true; - windowingCenter_ = center; - windowingWidth_ = width; - - BroadcastMessage(RadiographyScene::WindowingChangedMessage(*this)); - } - - - RadiographyLayer& RadiographyScene::UpdateText(size_t layerIndex, - const std::string& utf8, - const std::string& font, - unsigned int fontSize, - uint8_t foreground) - { - RadiographyTextLayer& textLayer = dynamic_cast<RadiographyTextLayer&>(GetLayer(layerIndex)); - textLayer.SetText(utf8, font, fontSize, foreground); - - BroadcastMessage(RadiographyScene::ContentChangedMessage(*this, textLayer)); - BroadcastMessage(RadiographyScene::LayerEditedMessage(*this, textLayer)); - return textLayer; - } - - - RadiographyLayer& RadiographyScene::LoadText(const std::string& utf8, - const std::string& font, - unsigned int fontSize, - uint8_t foreground, - RadiographyLayer::Geometry* centerGeometry, - bool isCenterGeometry) - { - std::unique_ptr<RadiographyTextLayer> alpha(new RadiographyTextLayer(*this)); - alpha->SetText(utf8, font, fontSize, foreground); - if (centerGeometry != NULL) - { - if (isCenterGeometry) - { - // modify geometry to reference the top left corner - double tlx = centerGeometry->GetPanX(); - double tly = centerGeometry->GetPanY(); - Extent2D textExtent = alpha->GetSceneExtent(false); - tlx = tlx - (textExtent.GetWidth() / 2) * centerGeometry->GetPixelSpacingX(); - tly = tly - (textExtent.GetHeight() / 2) * centerGeometry->GetPixelSpacingY(); - centerGeometry->SetPan(tlx, tly); - } - alpha->SetGeometry(*centerGeometry); - } - - RadiographyLayer& registeredLayer = RegisterLayer(alpha.release()); - - BroadcastMessage(RadiographyScene::LayerEditedMessage(*this, registeredLayer)); - return registeredLayer; - } - - - RadiographyLayer& RadiographyScene::LoadTestBlock(unsigned int width, - unsigned int height, - RadiographyLayer::Geometry* geometry) - { - std::unique_ptr<Orthanc::Image> block(new Orthanc::Image(Orthanc::PixelFormat_Grayscale8, width, height, false)); - - for (unsigned int padding = 0; - (width > 2 * padding) && (height > 2 * padding); - padding++) - { - uint8_t color; - if (255 > 10 * padding) - { - color = 255 - 10 * padding; - } - else - { - color = 0; - } - - Orthanc::ImageAccessor region; - block->GetRegion(region, padding, padding, width - 2 * padding, height - 2 * padding); - Orthanc::ImageProcessing::Set(region, color); - } - - return LoadAlphaBitmap(block.release(), geometry); - } - - RadiographyLayer& RadiographyScene::LoadMask(const std::vector<Orthanc::ImageProcessing::ImagePoint>& corners, - const RadiographyDicomLayer& dicomLayer, - float foreground, - RadiographyLayer::Geometry* geometry) - { - std::unique_ptr<RadiographyMaskLayer> mask(new RadiographyMaskLayer(*this, dicomLayer, foreground)); - mask->SetCorners(corners); - if (geometry != NULL) - { - mask->SetGeometry(*geometry); - } - - return RegisterLayer(mask.release()); - } - - - RadiographyLayer& RadiographyScene::LoadAlphaBitmap(Orthanc::ImageAccessor* bitmap, RadiographyLayer::Geometry *geometry) - { - std::unique_ptr<RadiographyAlphaLayer> alpha(new RadiographyAlphaLayer(*this)); - alpha->SetAlpha(bitmap); - if (geometry != NULL) - { - alpha->SetGeometry(*geometry); - } - - return RegisterLayer(alpha.release()); - } - - RadiographyLayer& RadiographyScene::LoadDicomImage(Orthanc::ImageAccessor* dicomImage, // takes ownership - const std::string& instance, - unsigned int frame, - Deprecated::DicomFrameConverter* converter, // takes ownership - RadiographyPhotometricDisplayMode preferredPhotometricDisplayMode, - RadiographyLayer::Geometry* geometry) - { - RadiographyDicomLayer& layer = dynamic_cast<RadiographyDicomLayer&>(RegisterLayer(new RadiographyDicomLayer(*this))); - - layer.SetInstance(instance, frame); - - if (geometry != NULL) - { - layer.SetGeometry(*geometry); - } - - layer.SetDicomFrameConverter(converter); - layer.SetSourceImage(dicomImage); - layer.SetPreferredPhotomotricDisplayMode(preferredPhotometricDisplayMode); - - return layer; - } - - RadiographyLayer& RadiographyScene::LoadDicomFrame(Deprecated::OrthancApiClient& orthanc, - const std::string& instance, - unsigned int frame, - bool httpCompression, - RadiographyLayer::Geometry* geometry) - { - RadiographyDicomLayer& layer = dynamic_cast<RadiographyDicomLayer&>(RegisterLayer(new RadiographyDicomLayer( *this))); - layer.SetInstance(instance, frame); - - if (geometry != NULL) - { - layer.SetGeometry(*geometry); - } - - { - Deprecated::IWebService::HttpHeaders headers; - std::string uri = "/instances/" + instance + "/tags"; - - orthanc.GetBinaryAsync( - uri, headers, - new Deprecated::DeprecatedCallable<RadiographyScene, Deprecated::OrthancApiClient::BinaryResponseReadyMessage> - (GetSharedObserver(), &RadiographyScene::OnTagsReceived), NULL, - new Orthanc::SingleValueObject<size_t>(layer.GetIndex())); - } - - { - Deprecated::IWebService::HttpHeaders headers; - headers["Accept"] = "image/x-portable-arbitrarymap"; - - if (httpCompression) - { - headers["Accept-Encoding"] = "gzip"; - } - - std::string uri = ("/instances/" + instance + "/frames/" + - boost::lexical_cast<std::string>(frame) + "/image-uint16"); - - orthanc.GetBinaryAsync( - uri, headers, - new Deprecated::DeprecatedCallable<RadiographyScene, Deprecated::OrthancApiClient::BinaryResponseReadyMessage> - (GetSharedObserver(), &RadiographyScene::OnFrameReceived), NULL, - new Orthanc::SingleValueObject<size_t>(layer.GetIndex())); - } - - return layer; - } - - - RadiographyLayer& RadiographyScene::LoadDicomWebFrame(Deprecated::IWebService& web) - { - RadiographyLayer& layer = RegisterLayer(new RadiographyDicomLayer(*this)); - - - return layer; - } - - - - void RadiographyScene::OnTagsReceived(const Deprecated::OrthancApiClient::BinaryResponseReadyMessage& message) - { - size_t index = dynamic_cast<const Orthanc::SingleValueObject<size_t>&> - (message.GetPayload()).GetValue(); - - VLOG(1) << "JSON received: " << message.GetUri().c_str() - << " (" << message.GetAnswerSize() << " bytes) for layer " << index; - - Layers::iterator layer = layers_.find(index); - if (layer != layers_.end()) - { - assert(layer->second != NULL); - - OrthancPlugins::FullOrthancDataset dicom(message.GetAnswer(), message.GetAnswerSize()); - dynamic_cast<RadiographyDicomLayer*>(layer->second)->SetDicomTags(dicom); - - float c, w; - if (!hasWindowing_ && - layer->second->GetDefaultWindowing(c, w)) - { - hasWindowing_ = true; - windowingCenter_ = c; - windowingWidth_ = w; - } - - BroadcastMessage(GeometryChangedMessage(*this, *(layer->second))); - } - } - - - void RadiographyScene::OnFrameReceived(const Deprecated::OrthancApiClient::BinaryResponseReadyMessage& message) - { - size_t index = dynamic_cast<const Orthanc::SingleValueObject<size_t>&>(message.GetPayload()).GetValue(); - - VLOG(1) << "DICOM frame received: " << message.GetUri().c_str() - << " (" << message.GetAnswerSize() << " bytes) for layer " << index; - - Layers::iterator layer = layers_.find(index); - if (layer != layers_.end()) - { - assert(layer->second != NULL); - - std::string content; - if (message.GetAnswerSize() > 0) - { - content.assign(reinterpret_cast<const char*>(message.GetAnswer()), message.GetAnswerSize()); - } - - std::unique_ptr<Orthanc::PamReader> reader(new Orthanc::PamReader); - reader->ReadFromMemory(content); - dynamic_cast<RadiographyDicomLayer*>(layer->second)->SetSourceImage(reader.release()); - - BroadcastMessage(ContentChangedMessage(*this, *(layer->second))); - } - } - - - Extent2D RadiographyScene::GetSceneExtent(bool minimal) const - { - Extent2D extent; - - for (Layers::const_iterator it = layers_.begin(); - it != layers_.end(); ++it) - { - assert(it->second != NULL); - extent.Union(it->second->GetSceneExtent(minimal)); - } - - return extent; - } - - - void RadiographyScene::Render(Orthanc::ImageAccessor& buffer, - const AffineTransform2D& viewTransform, - ImageInterpolation interpolation, - bool applyWindowing) const - { - // Render layers in the background-to-foreground order - for (size_t index = 0; index < nextLayerIndex_; index++) - { - try - { - Layers::const_iterator it = layers_.find(index); - if (it != layers_.end()) - { - assert(it->second != NULL); - it->second->Render(buffer, viewTransform, interpolation, windowingCenter_, windowingWidth_, applyWindowing); - } - } - catch (Orthanc::OrthancException& ex) - { - LOG(ERROR) << "RadiographyScene::Render: " << index << ", OrthancException: " << ex.GetDetails(); - throw ex; // rethrow because we want it to crash to see there's a problem ! - } - catch (...) - { - LOG(ERROR) << "RadiographyScene::Render: " << index << ", unkown exception: "; - throw; // rethrow because we want it to crash to see there's a problem ! - } - } - } - - - bool RadiographyScene::LookupLayer(size_t& index /* out */, - double x, - double y) const - { - // Render layers in the foreground-to-background order - for (size_t i = nextLayerIndex_; i > 0; i--) - { - index = i - 1; - Layers::const_iterator it = layers_.find(index); - if (it != layers_.end()) - { - assert(it->second != NULL); - if (it->second->Contains(x, y)) - { - return true; - } - } - } - - return false; - } - - - void RadiographyScene::DrawBorder(CairoContext& context, - unsigned int layer, - double zoom) - { - Layers::const_iterator found = layers_.find(layer); - - if (found != layers_.end()) - { - context.SetSourceColor(255, 0, 0); - found->second->DrawBorders(context, zoom); - } - } - - - void RadiographyScene::GetRange(float& minValue, - float& maxValue) const - { - bool first = true; - - for (Layers::const_iterator it = layers_.begin(); - it != layers_.end(); it++) - { - assert(it->second != NULL); - - float a, b; - if (it->second->GetRange(a, b)) - { - if (first) - { - minValue = a; - maxValue = b; - first = false; - } - else - { - minValue = std::min(a, minValue); - maxValue = std::max(b, maxValue); - } - } - } - - if (first) - { - minValue = 0; - maxValue = 0; - } - } - - void RadiographyScene::ExtractLayerFromRenderedScene(Orthanc::ImageAccessor& layer, - const Orthanc::ImageAccessor& renderedScene, - size_t layerIndex, - bool isCropped, - ImageInterpolation interpolation) - { - Extent2D sceneExtent = GetSceneExtent(isCropped); - - double pixelSpacingX = sceneExtent.GetWidth() / renderedScene.GetWidth(); - double pixelSpacingY = sceneExtent.GetHeight() / renderedScene.GetHeight(); - - AffineTransform2D view = AffineTransform2D::Combine( - AffineTransform2D::CreateScaling(1.0 / pixelSpacingX, 1.0 / pixelSpacingY), - AffineTransform2D::CreateOffset(-sceneExtent.GetX1(), -sceneExtent.GetY1())); - - AffineTransform2D layerToSceneTransform = AffineTransform2D::Combine( - view, - GetLayer(layerIndex).GetTransform()); - - AffineTransform2D sceneToLayerTransform = AffineTransform2D::Invert(layerToSceneTransform); - sceneToLayerTransform.Apply(layer, renderedScene, interpolation, false); - } - - Orthanc::Image* RadiographyScene::ExportToImage(double pixelSpacingX, - double pixelSpacingY, - ImageInterpolation interpolation, - bool invert, - int64_t maxValue /* for inversion */, - bool autoCrop, - bool applyWindowing) - { - if (pixelSpacingX <= 0 || - pixelSpacingY <= 0) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - Extent2D extent = GetSceneExtent(autoCrop); - - int w = boost::math::iround(extent.GetWidth() / pixelSpacingX); - int h = boost::math::iround(extent.GetHeight() / pixelSpacingY); - - if (w < 0 || h < 0) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - - Orthanc::Image layers(Orthanc::PixelFormat_Float32, - static_cast<unsigned int>(w), - static_cast<unsigned int>(h), false); - - AffineTransform2D view = AffineTransform2D::Combine( - AffineTransform2D::CreateScaling(1.0 / pixelSpacingX, 1.0 / pixelSpacingY), - AffineTransform2D::CreateOffset(-extent.GetX1(), -extent.GetY1())); - - // wipe background before rendering - if (GetPreferredPhotomotricDisplayMode() == RadiographyPhotometricDisplayMode_Monochrome1) - { - Orthanc::ImageProcessing::Set(layers, 65535); - } - else - { - Orthanc::ImageProcessing::Set(layers, 0); - } - - Render(layers, view, interpolation, applyWindowing); - - std::unique_ptr<Orthanc::Image> rendered(new Orthanc::Image(Orthanc::PixelFormat_Grayscale16, - layers.GetWidth(), layers.GetHeight(), false)); - - Orthanc::ImageProcessing::Convert(*rendered, layers); - if (invert) - Orthanc::ImageProcessing::Invert(*rendered, maxValue); - - return rendered.release(); - } - - - Orthanc::Image* RadiographyScene::ExportToCreateDicomRequestAndImage(Json::Value& createDicomRequestContent, - const Json::Value& dicomTags, - const std::string& parentOrthancId, - double pixelSpacingX, - double pixelSpacingY, - bool invert, - bool autoCrop, - ImageInterpolation interpolation) - { - LOG(INFO) << "Exporting RadiographyScene to DICOM"; - - std::unique_ptr<Orthanc::Image> rendered(ExportToImage(pixelSpacingX, pixelSpacingY, interpolation, autoCrop, false)); // note: we don't invert the image in the pixels data because we'll set the PhotometricDisplayMode correctly in the DICOM tags - - createDicomRequestContent["Tags"] = dicomTags; - - RadiographyPhotometricDisplayMode photometricMode = GetPreferredPhotomotricDisplayMode(); - if ((invert && photometricMode != RadiographyPhotometricDisplayMode_Monochrome2) || - (!invert && photometricMode == RadiographyPhotometricDisplayMode_Monochrome1)) - { - createDicomRequestContent["Tags"]["PhotometricInterpretation"] = "MONOCHROME1"; - } - else - { - createDicomRequestContent["Tags"]["PhotometricInterpretation"] = "MONOCHROME2"; - } - - // WARNING: The order of PixelSpacing is Y/X. We use "%0.8f" to - // avoid floating-point numbers to grow over 16 characters, - // which would be invalid according to DICOM standard - // ("dciodvfy" would complain). - char buf[32]; - sprintf(buf, "%0.8f\\%0.8f", pixelSpacingY, pixelSpacingX); - - createDicomRequestContent["Tags"]["PixelSpacing"] = buf; - - float center, width; - if (GetWindowing(center, width)) - { - createDicomRequestContent["Tags"]["WindowCenter"] = - boost::lexical_cast<std::string>(boost::math::iround(center)); - - createDicomRequestContent["Tags"]["WindowWidth"] = - boost::lexical_cast<std::string>(boost::math::iround(width)); - } - - if (!parentOrthancId.empty()) - { - createDicomRequestContent["Parent"] = parentOrthancId; - } - - return rendered.release(); - } - - - void RadiographyScene::ExportToCreateDicomRequest(Json::Value& createDicomRequestContent, - const Json::Value& dicomTags, - const std::string& parentOrthancId, - double pixelSpacingX, - double pixelSpacingY, - bool invert, - bool autoCrop, - ImageInterpolation interpolation, - bool usePam) - { - LOG(INFO) << "Exporting RadiographyScene to DICOM"; - VLOG(1) << "Exporting RadiographyScene to: export to image"; - - std::unique_ptr<Orthanc::Image> rendered(ExportToCreateDicomRequestAndImage(createDicomRequestContent, dicomTags, parentOrthancId, pixelSpacingX, pixelSpacingY, invert, autoCrop, interpolation)); - - // convert the image into base64 for inclusing in the createDicomRequest - std::string base64; - - { - std::string content; - - if (usePam) - { - VLOG(1) << "Exporting RadiographyScene: convert to PAM"; - Orthanc::PamWriter writer; - writer.WriteToMemory(content, *rendered); - } - else - { - Orthanc::PngWriter writer; - writer.WriteToMemory(content, *rendered); - } - - VLOG(1) << "Exporting RadiographyScene: encoding to base64"; - Orthanc::Toolbox::EncodeBase64(base64, content); - } - - // This is Data URI scheme: https://en.wikipedia.org/wiki/Data_URI_scheme - createDicomRequestContent["Content"] = ("data:" + - std::string(usePam ? Orthanc::MIME_PAM : Orthanc::MIME_PNG) + - ";base64," + base64); - - VLOG(1) << "Exporting RadiographyScene: create-dicom request is ready"; - } - - - void RadiographyScene::ExportDicom(Deprecated::OrthancApiClient& orthanc, - const Json::Value& dicomTags, - const std::string& parentOrthancId, - double pixelSpacingX, - double pixelSpacingY, - bool invert, - bool autoCrop, - ImageInterpolation interpolation, - bool usePam) - { - Json::Value createDicomRequestContent; - - ExportToCreateDicomRequest(createDicomRequestContent, dicomTags, parentOrthancId, pixelSpacingX, pixelSpacingY, invert, autoCrop, interpolation, usePam); - - orthanc.PostJsonAsyncExpectJson( - "/tools/create-dicom", createDicomRequestContent, - new Deprecated::DeprecatedCallable<RadiographyScene, Deprecated::OrthancApiClient::JsonResponseReadyMessage> - (GetSharedObserver(), &RadiographyScene::OnDicomExported), - NULL, NULL); - - } - - - // Export using PAM is faster than using PNG, but requires Orthanc - // core >= 1.4.3 - void RadiographyScene::ExportDicom(Deprecated::OrthancApiClient& orthanc, - const Orthanc::DicomMap& dicom, - const std::string& parentOrthancId, - double pixelSpacingX, - double pixelSpacingY, - bool invert, - bool autoCrop, - ImageInterpolation interpolation, - bool usePam) - { - std::set<Orthanc::DicomTag> tags; - dicom.GetTags(tags); - - Json::Value jsonTags = Json::objectValue; - - for (std::set<Orthanc::DicomTag>::const_iterator - tag = tags.begin(); tag != tags.end(); ++tag) - { - const Orthanc::DicomValue& value = dicom.GetValue(*tag); - if (!value.IsNull() && - !value.IsBinary()) - { - jsonTags[tag->Format()] = value.GetContent(); - } - } - - ExportDicom(orthanc, jsonTags, parentOrthancId, pixelSpacingX, pixelSpacingY, invert, autoCrop, interpolation, usePam); - } - - void RadiographyScene::OnDicomExported(const Deprecated::OrthancApiClient::JsonResponseReadyMessage& message) - { - LOG(INFO) << "DICOM export was successful: " - << message.GetJson().toStyledString(); - } - - - void RadiographyScene::OnDicomWebReceived(const Deprecated::IWebService::HttpRequestSuccessMessage& message) - { - LOG(INFO) << "DICOMweb WADO-RS received: " << message.GetAnswerSize() << " bytes"; - - const Deprecated::IWebService::HttpHeaders& h = message.GetAnswerHttpHeaders(); - for (Deprecated::IWebService::HttpHeaders::const_iterator - it = h.begin(); it != h.end(); ++it) - { - printf("[%s] = [%s]\n", it->first.c_str(), it->second.c_str()); - } - } - - void RadiographyScene::ExportToScene2D(Scene2D& output) const - { - int depth = 0; - for (Layers::const_iterator it = layers_.begin(); - it != layers_.end(); ++it) - { - assert(it->second != NULL); - - std::unique_ptr<ISceneLayer> layer; - if (dynamic_cast<RadiographyDicomLayer*>(it->second)) - { - RadiographyDicomLayer* oldLayer = dynamic_cast<RadiographyDicomLayer*>(it->second); - - std::unique_ptr<FloatTextureSceneLayer> newLayer(new FloatTextureSceneLayer(*(oldLayer->GetSourceImage()))); - - newLayer->SetOrigin(oldLayer->GetGeometry().GetPanX(), - oldLayer->GetGeometry().GetPanY() - ); - newLayer->SetAngle(oldLayer->GetGeometry().GetAngle()); - - layer.reset(newLayer.release()); - - // TODO: windowing dynamic_cast - } - else if (dynamic_cast<RadiographyTextLayer*>(it->second)) - { - RadiographyTextLayer* oldLayer = dynamic_cast<RadiographyTextLayer*>(it->second); - - std::unique_ptr<TextSceneLayer> newLayer(new TextSceneLayer()); - - newLayer->SetText(oldLayer->GetText()); - newLayer->SetColor(oldLayer->GetForegroundGreyLevel(), - oldLayer->GetForegroundGreyLevel(), - oldLayer->GetForegroundGreyLevel() - ); - newLayer->SetPosition(oldLayer->GetGeometry().GetPanX(), - oldLayer->GetGeometry().GetPanY() - ); - newLayer->SetFontIndex(1); - newLayer->SetAnchor(BitmapAnchor_TopLeft); - //newLayer->SetAngle(oldLayer->GetGeometry().GetAngle()); - - layer.reset(newLayer.release()); - } - - output.SetLayer(depth++, layer.release()); - - } - - } - -} -
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyScene.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,371 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "RadiographyLayer.h" -#include "../Messages/ObserverBase.h" -#include "../Deprecated/Toolbox/DicomFrameConverter.h" -#include "../Deprecated/Toolbox/OrthancApiClient.h" -#include "../StoneEnumerations.h" -#include "../Scene2D/Scene2D.h" - -#include <Images/Image.h> -#include <Images/ImageProcessing.h> - - -namespace OrthancStone -{ - class RadiographyDicomLayer; - - class RadiographyScene : - public ObserverBase<RadiographyScene>, - public IObservable - { - friend class RadiographySceneGeometryReader; - public: - class GeometryChangedMessage : public OriginMessage<RadiographyScene> - { - ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); - - private: - RadiographyLayer& layer_; - - public: - GeometryChangedMessage(const RadiographyScene& origin, - RadiographyLayer& layer) : - OriginMessage(origin), - layer_(layer) - { - } - - RadiographyLayer& GetLayer() const - { - return layer_; - } - }; - - class ContentChangedMessage : public OriginMessage<RadiographyScene> - { - ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); - - private: - RadiographyLayer& layer_; - - public: - ContentChangedMessage(const RadiographyScene& origin, - RadiographyLayer& layer) : - OriginMessage(origin), - layer_(layer) - { - } - - RadiographyLayer& GetLayer() const - { - return layer_; - } - }; - - class LayerEditedMessage : public OriginMessage<RadiographyScene> - { - ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); - - private: - const RadiographyLayer& layer_; - - public: - LayerEditedMessage(const RadiographyScene& origin, - const RadiographyLayer& layer) : - OriginMessage(origin), - layer_(layer) - { - } - - const RadiographyLayer& GetLayer() const - { - return layer_; - } - }; - - class LayerRemovedMessage : public OriginMessage<RadiographyScene> - { - ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); - - private: - size_t& layerIndex_; - - public: - LayerRemovedMessage(const RadiographyScene& origin, - size_t& layerIndex) : - OriginMessage(origin), - layerIndex_(layerIndex) - { - } - - size_t& GetLayerIndex() const - { - return layerIndex_; - } - }; - - - ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, WindowingChangedMessage, RadiographyScene); - - - class LayerAccessor : public boost::noncopyable - { - private: - RadiographyScene& scene_; - size_t index_; - RadiographyLayer* layer_; - - public: - LayerAccessor(RadiographyScene& scene, - size_t index); - - LayerAccessor(RadiographyScene& scene, - double x, - double y); - - void Invalidate() - { - layer_ = NULL; - } - - bool IsValid() const - { - return layer_ != NULL; - } - - RadiographyScene& GetScene() const; - - size_t GetIndex() const; - - RadiographyLayer& GetLayer() const; - }; - - - protected: - typedef std::map<size_t, RadiographyLayer*> Layers; - - size_t nextLayerIndex_; - bool hasWindowing_; - float windowingCenter_; - float windowingWidth_; - Layers layers_; - - public: - RadiographyLayer& RegisterLayer(RadiographyLayer* layer); - - protected: - virtual void _RegisterLayer(RadiographyLayer* layer); - virtual void _OnLayerRemoved() {} - - void SetLayerIndex(RadiographyLayer* layer, size_t index) - { - layer->SetIndex(index); - } - - virtual void OnTagsReceived(const Deprecated::OrthancApiClient::BinaryResponseReadyMessage& message); - - virtual void OnFrameReceived(const Deprecated::OrthancApiClient::BinaryResponseReadyMessage& message); - - void OnDicomExported(const Deprecated::OrthancApiClient::JsonResponseReadyMessage& message); - - void OnDicomWebReceived(const Deprecated::IWebService::HttpRequestSuccessMessage& message); - - virtual void OnLayerEdited(const RadiographyLayer::LayerEditedMessage& message); - - public: - RadiographyScene(); - - virtual ~RadiographyScene(); - - virtual size_t GetApproximateMemoryUsage() const; - - bool GetWindowing(float& center, - float& width) const; - - void GetWindowingWithDefault(float& center, - float& width) const; - - virtual void SetWindowing(float center, - float width); - - RadiographyPhotometricDisplayMode GetPreferredPhotomotricDisplayMode() const; - - RadiographyLayer& LoadText(const std::string& utf8, - const std::string& font, - unsigned int fontSize, - uint8_t foreground, - RadiographyLayer::Geometry* geometry, - bool isCenterGeometry); - - RadiographyLayer& UpdateText(size_t layerIndex, - const std::string& font, - const std::string& utf8, - unsigned int fontSize, - uint8_t foreground); - - RadiographyLayer& LoadTestBlock(unsigned int width, - unsigned int height, - RadiographyLayer::Geometry* geometry); - - RadiographyLayer& LoadMask(const std::vector<Orthanc::ImageProcessing::ImagePoint>& corners, - const RadiographyDicomLayer& dicomLayer, - float foreground, - RadiographyLayer::Geometry* geometry); - - RadiographyLayer& LoadAlphaBitmap(Orthanc::ImageAccessor* bitmap, // takes ownership - RadiographyLayer::Geometry* geometry); - - virtual RadiographyLayer& LoadDicomImage(Orthanc::ImageAccessor* dicomImage, // takes ownership - const std::string& instance, - unsigned int frame, - Deprecated::DicomFrameConverter* converter, // takes ownership - RadiographyPhotometricDisplayMode preferredPhotometricDisplayMode, - RadiographyLayer::Geometry* geometry); - - virtual RadiographyLayer& LoadDicomFrame(Deprecated::OrthancApiClient& orthanc, - const std::string& instance, - unsigned int frame, - bool httpCompression, - RadiographyLayer::Geometry* geometry); // pass NULL if you want default geometry - - RadiographyLayer& LoadDicomWebFrame(Deprecated::IWebService& web); - - void RemoveLayer(size_t layerIndex); - - RadiographyLayer& GetLayer(size_t layerIndex); - - const RadiographyLayer& GetLayer(size_t layerIndex) const; - - template <typename TypeLayer> - TypeLayer* GetTypedLayer(size_t indexOfType = 0) - { - std::vector<size_t> layerIndexes; - GetLayersIndexes(layerIndexes); - - size_t count = 0; - - for (size_t i = 0; i < layerIndexes.size(); ++i) - { - TypeLayer* typedLayer = dynamic_cast<TypeLayer*>(layers_[layerIndexes[i]]); - if (typedLayer != NULL) - { - if (count == indexOfType) - { - return typedLayer; - } - count++; - } - } - - return NULL; - } - - void GetLayersIndexes(std::vector<size_t>& output) const; - - virtual Extent2D GetSceneExtent(bool minimal) const; - - virtual void Render(Orthanc::ImageAccessor& buffer, - const AffineTransform2D& viewTransform, - ImageInterpolation interpolation, - bool applyWindowing) const; - - bool LookupLayer(size_t& index /* out */, - double x, - double y) const; - - void DrawBorder(CairoContext& context, - unsigned int layer, - double zoom); - - void GetRange(float& minValue, - float& maxValue) const; - - void ExportToScene2D(Scene2D& output) const; - - // Export using PAM is faster than using PNG, but requires Orthanc - // core >= 1.4.3 - void ExportDicom(Deprecated::OrthancApiClient& orthanc, - const Orthanc::DicomMap& dicom, - const std::string& parentOrthancId, - double pixelSpacingX, - double pixelSpacingY, - bool invert, - bool autoCrop, - ImageInterpolation interpolation, - bool usePam); - - void ExportDicom(Deprecated::OrthancApiClient& orthanc, - const Json::Value& dicomTags, - const std::string& parentOrthancId, - double pixelSpacingX, - double pixelSpacingY, - bool invert, - bool autoCrop, - ImageInterpolation interpolation, - bool usePam); - - void ExportToCreateDicomRequest(Json::Value& createDicomRequestContent, - const Json::Value& dicomTags, - const std::string& parentOrthancId, - double pixelSpacingX, - double pixelSpacingY, - bool invert, - bool autoCrop, - ImageInterpolation interpolation, - bool usePam); - - Orthanc::Image* ExportToCreateDicomRequestAndImage(Json::Value& createDicomRequestContent, - const Json::Value& dicomTags, - const std::string& parentOrthancId, - double pixelSpacingX, - double pixelSpacingY, - bool invert, - bool autoCrop, - ImageInterpolation interpolation); - - Orthanc::Image* ExportToImage(double pixelSpacingX, - double pixelSpacingY, - ImageInterpolation interpolation, - bool autoCrop, - bool applyWindowing) - { - return ExportToImage(pixelSpacingX, pixelSpacingY, interpolation, false, 0, autoCrop, applyWindowing); - } - - Orthanc::Image* ExportToImage(double pixelSpacingX, - double pixelSpacingY, - ImageInterpolation interpolation, - bool invert, - int64_t maxValue /* for inversion */, - bool autoCrop, - bool applyWindowing); - - void ExtractLayerFromRenderedScene(Orthanc::ImageAccessor& layer, - const Orthanc::ImageAccessor& renderedScene, - size_t layerIndex, - bool isCropped, - ImageInterpolation interpolation); - }; -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographySceneCommand.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "RadiographySceneCommand.h" - - -namespace OrthancStone -{ - RadiographySceneCommand::RadiographySceneCommand(RadiographyScene& scene, - size_t layer) : - scene_(scene), - layer_(layer) - { - } - - - RadiographySceneCommand::RadiographySceneCommand(const RadiographyScene::LayerAccessor& accessor) : - scene_(accessor.GetScene()), - layer_(accessor.GetIndex()) - { - } - - - void RadiographySceneCommand::Undo() const - { - RadiographyScene::LayerAccessor accessor(scene_, layer_); - - if (accessor.IsValid()) - { - UndoInternal(accessor.GetLayer()); - } - } - - - void RadiographySceneCommand::Redo() const - { - RadiographyScene::LayerAccessor accessor(scene_, layer_); - - if (accessor.IsValid()) - { - RedoInternal(accessor.GetLayer()); - } - } -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographySceneCommand.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../Toolbox/UndoRedoStack.h" -#include "RadiographyScene.h" - -namespace OrthancStone -{ - class RadiographySceneCommand : public UndoRedoStack::ICommand - { - private: - RadiographyScene& scene_; - size_t layer_; - - protected: - virtual void UndoInternal(RadiographyLayer& layer) const = 0; - - virtual void RedoInternal(RadiographyLayer& layer) const = 0; - - public: - RadiographySceneCommand(RadiographyScene& scene, - size_t layer); - - RadiographySceneCommand(const RadiographyScene::LayerAccessor& accessor); - - virtual void Undo() const; - - virtual void Redo() const; - }; -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographySceneReader.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,189 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "RadiographySceneReader.h" - -#include "../Deprecated/Toolbox/DicomFrameConverter.h" - -#include <Images/FontRegistry.h> -#include <Images/PngReader.h> -#include <OrthancException.h> -#include <Toolbox.h> - -namespace OrthancStone -{ - - void RadiographySceneBuilder::Read(const Json::Value& input, Orthanc::ImageAccessor* dicomImage /* takes ownership */, - Deprecated::DicomFrameConverter* dicomFrameConverter /* takes ownership */, - RadiographyPhotometricDisplayMode preferredPhotometricDisplayMode - ) - { - dicomImage_.reset(dicomImage); - dicomFrameConverter_.reset(dicomFrameConverter); - preferredPhotometricDisplayMode_ = preferredPhotometricDisplayMode; - Read(input); - } - - RadiographyDicomLayer* RadiographySceneBuilder::LoadDicom(const std::string& instanceId, unsigned int frame, RadiographyLayer::Geometry* geometry) - { - return dynamic_cast<RadiographyDicomLayer*>(&(scene_.LoadDicomImage(dicomImage_.release(), instanceId, frame, dicomFrameConverter_.release(), preferredPhotometricDisplayMode_, geometry))); - } - - - RadiographyDicomLayer* RadiographySceneReader::LoadDicom(const std::string& instanceId, unsigned int frame, RadiographyLayer::Geometry* geometry) - { - return dynamic_cast<RadiographyDicomLayer*>(&(scene_.LoadDicomFrame(orthancApiClient_, instanceId, frame, false, geometry))); - } - - RadiographyDicomLayer* RadiographySceneGeometryReader::LoadDicom(const std::string& instanceId, unsigned int frame, RadiographyLayer::Geometry* geometry) - { - std::unique_ptr<RadiographyPlaceholderLayer> layer(new RadiographyPlaceholderLayer(scene_)); - layer->SetGeometry(*geometry); - layer->SetSize(dicomImageWidth_, dicomImageHeight_); - scene_.RegisterLayer(layer.get()); - - return layer.release(); - } - - void RadiographySceneBuilder::Read(const Json::Value& input) - { - unsigned int version = input["version"].asUInt(); - - if (version != 1) - throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); - - if (input.isMember("hasWindowing") && input["hasWindowing"].asBool()) - { - scene_.SetWindowing(input["windowCenter"].asFloat(), input["windowWidth"].asFloat()); - } - - RadiographyDicomLayer* dicomLayer = NULL; - for(size_t layerIndex = 0; layerIndex < input["layers"].size(); layerIndex++) - { - const Json::Value& jsonLayer = input["layers"][(int)layerIndex]; - RadiographyLayer::Geometry geometry; - - if (jsonLayer["type"].asString() == "dicom") - { - ReadLayerGeometry(geometry, jsonLayer); - dicomLayer = LoadDicom(jsonLayer["instanceId"].asString(), jsonLayer["frame"].asUInt(), &geometry); - } - else if (jsonLayer["type"].asString() == "mask") - { - if (dicomLayer == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); // we always assumed the dicom layer was read before the mask - } - ReadLayerGeometry(geometry, jsonLayer); - - float foreground = jsonLayer["foreground"].asFloat(); - std::vector<Orthanc::ImageProcessing::ImagePoint> corners; - for (size_t i = 0; i < jsonLayer["corners"].size(); i++) - { - Orthanc::ImageProcessing::ImagePoint corner(jsonLayer["corners"][(int)i]["x"].asInt(), - jsonLayer["corners"][(int)i]["y"].asInt()); - corners.push_back(corner); - } - - scene_.LoadMask(corners, *dicomLayer, foreground, &geometry); - } - else if (jsonLayer["type"].asString() == "text") - { - ReadLayerGeometry(geometry, jsonLayer); - scene_.LoadText(jsonLayer["text"].asString(), jsonLayer["font"].asString(), jsonLayer["fontSize"].asUInt(), static_cast<uint8_t>(jsonLayer["foreground"].asUInt()), &geometry, false); - } - else if (jsonLayer["type"].asString() == "alpha") - { - ReadLayerGeometry(geometry, jsonLayer); - - const std::string& pngContentBase64 = jsonLayer["content"].asString(); - std::string pngContent; - std::string mimeType; - Orthanc::Toolbox::DecodeDataUriScheme(mimeType, pngContent, pngContentBase64); - - std::unique_ptr<Orthanc::ImageAccessor> image; - if (mimeType == "image/png") - { - image.reset(new Orthanc::PngReader()); - dynamic_cast<Orthanc::PngReader*>(image.get())->ReadFromMemory(pngContent); - } - else - throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); - - RadiographyAlphaLayer& layer = dynamic_cast<RadiographyAlphaLayer&>(scene_.LoadAlphaBitmap(image.release(), &geometry)); - - if (!jsonLayer["isUsingWindowing"].asBool()) - { - layer.SetForegroundValue((float)(jsonLayer["foreground"].asDouble())); - } - } - else - throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); - } - } - - - - - void RadiographySceneBuilder::ReadDicomLayerGeometry(RadiographyLayer::Geometry& geometry, const Json::Value& input) - { - for(size_t layerIndex = 0; layerIndex < input["layers"].size(); layerIndex++) - { - const Json::Value& jsonLayer = input["layers"][(int)layerIndex]; - if (jsonLayer["type"].asString() == "dicom") - { - ReadLayerGeometry(geometry, jsonLayer); - return; - } - } - } - - void RadiographySceneBuilder::ReadLayerGeometry(RadiographyLayer::Geometry& geometry, const Json::Value& jsonLayer) - { - {// crop - unsigned int x, y, width, height; - if (jsonLayer["crop"]["hasCrop"].asBool()) - { - x = jsonLayer["crop"]["x"].asUInt(); - y = jsonLayer["crop"]["y"].asUInt(); - width = jsonLayer["crop"]["width"].asUInt(); - height = jsonLayer["crop"]["height"].asUInt(); - geometry.SetCrop(x, y, width, height); - } - } - - geometry.SetAngle(jsonLayer["angle"].asDouble()); - geometry.SetResizeable(jsonLayer["isResizable"].asBool()); - geometry.SetPan(jsonLayer["pan"]["x"].asDouble(), jsonLayer["pan"]["y"].asDouble()); - geometry.SetPixelSpacing(jsonLayer["pixelSpacing"]["x"].asDouble(), jsonLayer["pixelSpacing"]["y"].asDouble()); - - // these fields were introduced later -> they might not exist - if (jsonLayer.isMember("flipVertical")) - { - geometry.SetFlipVertical(jsonLayer["flipVertical"].asBool()); - } - if (jsonLayer.isMember("flipHorizontal")) - { - geometry.SetFlipHorizontal(jsonLayer["flipHorizontal"].asBool()); - } - - } -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographySceneReader.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "RadiographyScene.h" -#include "RadiographyAlphaLayer.h" -#include "RadiographyDicomLayer.h" -#include "RadiographyMaskLayer.h" -#include "RadiographyTextLayer.h" -#include "../Deprecated/Toolbox/OrthancApiClient.h" - -#include <json/value.h> -#include <Images/FontRegistry.h> - -namespace OrthancStone -{ - // a layer containing only the geometry of a DICOM layer (bit hacky !) - class RadiographyPlaceholderLayer : public RadiographyDicomLayer - { - public: - RadiographyPlaceholderLayer(const RadiographyScene& scene) : - RadiographyDicomLayer(scene) - { - } - - }; - - - // HACK: I had to introduce this builder class in order to be able to recreate a RadiographyScene - // from a serialized scene that is passed to web-workers. - // It needs some architecturing... - class RadiographySceneBuilder : public boost::noncopyable - { - protected: - RadiographyScene& scene_; - std::unique_ptr<Orthanc::ImageAccessor> dicomImage_; - std::unique_ptr<Deprecated::DicomFrameConverter> dicomFrameConverter_; - RadiographyPhotometricDisplayMode preferredPhotometricDisplayMode_; - - public: - RadiographySceneBuilder(RadiographyScene& scene) : - scene_(scene) - { - } - - void Read(const Json::Value& input); - void Read(const Json::Value& input, - Orthanc::ImageAccessor* dicomImage, // takes ownership - Deprecated::DicomFrameConverter* dicomFrameConverter, // takes ownership - RadiographyPhotometricDisplayMode preferredPhotometricDisplayMode - ); - - static void ReadLayerGeometry(RadiographyLayer::Geometry& geometry, const Json::Value& input); - static void ReadDicomLayerGeometry(RadiographyLayer::Geometry& geometry, const Json::Value& input); - - protected: - virtual RadiographyDicomLayer* LoadDicom(const std::string& instanceId, unsigned int frame, RadiographyLayer::Geometry* geometry); - - }; - - - class RadiographySceneReader : public RadiographySceneBuilder - { - Deprecated::OrthancApiClient& orthancApiClient_; - - public: - RadiographySceneReader(RadiographyScene& scene, Deprecated::OrthancApiClient& orthancApiClient) : - RadiographySceneBuilder(scene), - orthancApiClient_(orthancApiClient) - { - } - - protected: - virtual RadiographyDicomLayer* LoadDicom(const std::string& instanceId, unsigned int frame, RadiographyLayer::Geometry* geometry); - }; - - // reads the whole scene but the DICOM image such that we have the full geometry - class RadiographySceneGeometryReader : public RadiographySceneBuilder - { - unsigned int dicomImageWidth_; - unsigned int dicomImageHeight_; - - public: - RadiographySceneGeometryReader(RadiographyScene& scene, unsigned int dicomImageWidth, unsigned int dicomImageHeight) : - RadiographySceneBuilder(scene), - dicomImageWidth_(dicomImageWidth), - dicomImageHeight_(dicomImageHeight) - { - } - - protected: - virtual RadiographyDicomLayer* LoadDicom(const std::string& instanceId, unsigned int frame, RadiographyLayer::Geometry* geometry); - }; -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographySceneWriter.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,168 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "RadiographySceneWriter.h" - -#include <OrthancException.h> -#include <Images/PngWriter.h> -#include <Toolbox.h> - -namespace OrthancStone -{ - void RadiographySceneWriter::Write(Json::Value& output, const RadiographyScene& scene) - { - output["version"] = 1; - float windowCenter, windowWidth; - bool hasWindowing = scene.GetWindowing(windowCenter, windowWidth); - output["hasWindowing"] = hasWindowing; - if (hasWindowing) - { - output["windowCenter"] = windowCenter; - output["windowWidth"] = windowWidth; - } - output["layers"] = Json::arrayValue; - - std::vector<size_t> layersIndexes; - scene.GetLayersIndexes(layersIndexes); - - for (std::vector<size_t>::iterator itLayerIndex = layersIndexes.begin(); itLayerIndex < layersIndexes.end(); itLayerIndex++) - { - Json::Value layer; - WriteLayer(layer, scene.GetLayer(*itLayerIndex)); - output["layers"].append(layer); - } - } - - void RadiographySceneWriter::WriteLayer(Json::Value& output, const RadiographyDicomLayer& layer) - { - output["type"] = "dicom"; - output["instanceId"] = layer.GetInstanceId(); - output["frame"] = layer.GetFrame(); - } - - void RadiographySceneWriter::WriteLayer(Json::Value& output, const RadiographyTextLayer& layer) - { - output["type"] = "text"; - output["text"] = layer.GetText(); - output["font"] = layer.GetFont(); - output["fontSize"] = layer.GetFontSize(); - output["foreground"] = layer.GetForegroundGreyLevel(); - } - - void RadiographySceneWriter::WriteLayer(Json::Value& output, const RadiographyMaskLayer& layer) - { - output["type"] = "mask"; - output["instanceId"] = layer.GetInstanceId(); // the dicom layer it's being linked to - output["foreground"] = layer.GetForeground(); - output["corners"] = Json::arrayValue; - const std::vector<Orthanc::ImageProcessing::ImagePoint>& corners = layer.GetCorners(); - for (size_t i = 0; i < corners.size(); i++) - { - Json::Value corner; - corner["x"] = corners[i].GetX(); - corner["y"] = corners[i].GetY(); - output["corners"].append(corner); - } - } - - void RadiographySceneWriter::WriteLayer(Json::Value& output, const RadiographyAlphaLayer& layer) - { - output["type"] = "alpha"; - - //output["bitmap"] = - const Orthanc::ImageAccessor& alpha = layer.GetAlpha(); - - Orthanc::PngWriter pngWriter; - std::string pngContent; - std::string pngContentBase64; - pngWriter.WriteToMemory(pngContent, alpha); - - Orthanc::Toolbox::EncodeDataUriScheme(pngContentBase64, "image/png", pngContent); - output["content"] = pngContentBase64; - output["foreground"] = layer.GetForegroundValue(); - } - - void RadiographySceneWriter::WriteLayer(Json::Value& output, const RadiographyLayer& layer) - { - const RadiographyLayer::Geometry& geometry = layer.GetGeometry(); - - {// crop - Json::Value crop; - if (geometry.HasCrop()) - { - unsigned int x, y, width, height; - geometry.GetCrop(x, y, width, height); - crop["hasCrop"] = true; - crop["x"] = x; - crop["y"] = y; - crop["width"] = width; - crop["height"] = height; - } - else - { - crop["hasCrop"] = false; - } - - output["crop"] = crop; - } - - output["angle"] = geometry.GetAngle(); - output["isResizable"] = geometry.IsResizeable(); - - {// pan - Json::Value pan; - pan["x"] = geometry.GetPanX(); - pan["y"] = geometry.GetPanY(); - output["pan"] = pan; - } - - {// pixelSpacing - Json::Value pan; - pan["x"] = geometry.GetPixelSpacingX(); - pan["y"] = geometry.GetPixelSpacingY(); - output["pixelSpacing"] = pan; - } - - output["flipVertical"] = geometry.GetFlipVertical(); - output["flipHorizontal"] = geometry.GetFlipHorizontal(); - - if (dynamic_cast<const RadiographyTextLayer*>(&layer) != NULL) - { - WriteLayer(output, dynamic_cast<const RadiographyTextLayer&>(layer)); - } - else if (dynamic_cast<const RadiographyDicomLayer*>(&layer) != NULL) - { - WriteLayer(output, dynamic_cast<const RadiographyDicomLayer&>(layer)); - } - else if (dynamic_cast<const RadiographyAlphaLayer*>(&layer) != NULL) - { - WriteLayer(output, dynamic_cast<const RadiographyAlphaLayer&>(layer)); - } - else if (dynamic_cast<const RadiographyMaskLayer*>(&layer) != NULL) - { - WriteLayer(output, dynamic_cast<const RadiographyMaskLayer&>(layer)); - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); - } - } -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographySceneWriter.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "RadiographyScene.h" -#include "RadiographyAlphaLayer.h" -#include "RadiographyDicomLayer.h" -#include "RadiographyTextLayer.h" -#include "RadiographyMaskLayer.h" -#include <json/value.h> - -namespace OrthancStone -{ - class RadiographyScene; - - class RadiographySceneWriter : public boost::noncopyable - { - - public: - RadiographySceneWriter() - { - } - - void Write(Json::Value& output, const RadiographyScene& scene); - - private: - void WriteLayer(Json::Value& output, const RadiographyLayer& layer); - void WriteLayer(Json::Value& output, const RadiographyDicomLayer& layer); - void WriteLayer(Json::Value& output, const RadiographyTextLayer& layer); - void WriteLayer(Json::Value& output, const RadiographyAlphaLayer& layer); - void WriteLayer(Json::Value& output, const RadiographyMaskLayer& layer); - }; -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyTextLayer.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#include "RadiographyTextLayer.h" - -#include "RadiographyScene.h" -#include "../Toolbox/TextRenderer.h" - -#include <OrthancException.h> - -namespace OrthancStone -{ - std::map<std::string, Orthanc::EmbeddedResources::FileResourceId> RadiographyTextLayer::fonts_; - - void RadiographyTextLayer::SetText(const std::string& utf8, - const std::string& font, - unsigned int fontSize, - uint8_t foregroundGreyLevel) - { - if (fonts_.find(font) == fonts_.end()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls, "The font has not been registered"); - } - - text_ = utf8; - font_ = font; - fontSize_ = fontSize; - foregroundGreyLevel_ = foregroundGreyLevel; - - SetAlpha(TextRenderer::Render(fonts_[font_], - fontSize_, - text_)); - - SetForegroundValue(foregroundGreyLevel * 256.0f); - } - -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyTextLayer.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "RadiographyAlphaLayer.h" - -namespace OrthancStone -{ - class RadiographyScene; - - class RadiographyTextLayer : public RadiographyAlphaLayer - { - private: - std::string text_; - std::string font_; - unsigned int fontSize_; - uint8_t foregroundGreyLevel_; - - static std::map<std::string, Orthanc::EmbeddedResources::FileResourceId> fonts_; - public: - RadiographyTextLayer(const RadiographyScene& scene) : - RadiographyAlphaLayer(scene) - { - } - - void SetText(const std::string& utf8, const std::string& font, unsigned int fontSize, uint8_t foregroundGreyLevel); - - const std::string& GetText() const - { - return text_; - } - - const std::string& GetFont() const - { - return font_; - } - - unsigned int GetFontSize() const - { - return fontSize_; - } - - uint8_t GetForegroundGreyLevel() const - { - return foregroundGreyLevel_; - } - - static void RegisterFont(const std::string& name, Orthanc::EmbeddedResources::FileResourceId fontResourceId) - { - fonts_[name] = fontResourceId; - } - }; -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyWidget.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,284 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "RadiographyWidget.h" - -#include <OrthancException.h> -#include <Images/Image.h> -#include <Images/ImageProcessing.h> - -#include "RadiographyMaskLayer.h" - -namespace OrthancStone -{ - - bool RadiographyWidget::IsInvertedInternal() const - { - // MONOCHROME1 images must be inverted and the user can invert the - // image, too -> XOR the two - return (scene_->GetPreferredPhotomotricDisplayMode() == - RadiographyPhotometricDisplayMode_Monochrome1) ^ invert_; - } - - void RadiographyWidget::RenderBackground( - Orthanc::ImageAccessor& image, float minValue, float maxValue) - { - // wipe background before rendering - float backgroundValue = minValue; - - switch (scene_->GetPreferredPhotomotricDisplayMode()) - { - case RadiographyPhotometricDisplayMode_Monochrome1: - case RadiographyPhotometricDisplayMode_Default: - if (IsInvertedInternal()) - backgroundValue = maxValue; - else - backgroundValue = minValue; - break; - case RadiographyPhotometricDisplayMode_Monochrome2: - if (IsInvertedInternal()) - backgroundValue = minValue; - else - backgroundValue = maxValue; - break; - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); - } - - Orthanc::ImageProcessing::Set(image, static_cast<int64_t>(backgroundValue)); - } - - bool RadiographyWidget::RenderInternal(unsigned int width, - unsigned int height, - ImageInterpolation interpolation) - { - if (floatBuffer_.get() == NULL || - floatBuffer_->GetWidth() != width || - floatBuffer_->GetHeight() != height) - { - floatBuffer_.reset(new Orthanc::Image( - Orthanc::PixelFormat_Float32, width, height, false)); - - if (floatBuffer_.get() == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NotEnoughMemory, "RadiographyWidget::RenderInternal: unable to allocate float buffer"); - } - } - - if (cairoBuffer_.get() == NULL || - cairoBuffer_->GetWidth() != width || - cairoBuffer_->GetHeight() != height) - { - cairoBuffer_.reset(new CairoSurface(width, height, false /* no alpha */)); - - if (cairoBuffer_.get() == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NotEnoughMemory, "RadiographyWidget::RenderInternal: unable to allocate cairo buffer"); - } - } - - RenderBackground(*floatBuffer_, 0.0, 65535.0); - - scene_->Render(*floatBuffer_, GetView().GetMatrix(), interpolation, true); - - // Conversion from Float32 to BGRA32 (cairo). Very similar to - // GrayscaleFrameRenderer => TODO MERGE? - Orthanc::ImageAccessor target; - cairoBuffer_->GetWriteableAccessor(target); - - bool invert = IsInvertedInternal(); - - for (unsigned int y = 0; y < height; y++) - { - const float* p = reinterpret_cast<const float*>(floatBuffer_->GetConstRow(y)); - uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y)); - - for (unsigned int x = 0; x < width; x++, p++, q += 4) - { - uint8_t v = 0; - if (*p >= 65535.0) - { - v = 255; - } - else if (*p <= 0.0) - { - v = 0; - } - else - { - v = static_cast<uint8_t>(*p / 256.0); - } - - if (invert) - { - v = 255 - v; - } - - q[0] = v; - q[1] = v; - q[2] = v; - q[3] = 255; - } - } - - return true; - } - - - bool RadiographyWidget::RenderScene(CairoContext& context, - const Deprecated::ViewportGeometry& view) - { - cairo_t* cr = context.GetObject(); - - if (RenderInternal(context.GetWidth(), context.GetHeight(), interpolation_)) - { - // https://www.cairographics.org/FAQ/#paint_from_a_surface - cairo_save(cr); - cairo_identity_matrix(cr); - cairo_set_source_surface(cr, cairoBuffer_->GetObject(), 0, 0); - cairo_paint(cr); - cairo_restore(cr); - } - else - { - // https://www.cairographics.org/FAQ/#clear_a_surface - context.SetSourceColor(0, 0, 0); - cairo_paint(cr); - } - - if (hasSelection_) - { - scene_->DrawBorder( - context, static_cast<unsigned int>(selectedLayer_), view.GetZoom()); - } - - return true; - } - - - RadiographyWidget::RadiographyWidget(boost::shared_ptr<RadiographyScene> scene, - const std::string& name) : - WorldSceneWidget(name), - invert_(false), - interpolation_(ImageInterpolation_Nearest), - hasSelection_(false), - selectedLayer_(0) // Dummy initialization - { - SetScene(scene); - } - - - void RadiographyWidget::Select(size_t layer) - { - hasSelection_ = true; - selectedLayer_ = layer; - - NotifyContentChanged(); - BroadcastMessage(SelectionChangedMessage(*this)); - } - - void RadiographyWidget::Unselect() - { - hasSelection_ = false; - - NotifyContentChanged(); - BroadcastMessage(SelectionChangedMessage(*this)); - } - - bool RadiographyWidget::LookupSelectedLayer(size_t& layer) const - { - if (hasSelection_) - { - layer = selectedLayer_; - return true; - } - else - { - return false; - } - } - - - void RadiographyWidget::OnGeometryChanged(const RadiographyScene::GeometryChangedMessage& message) - { -// LOG(INFO) << "Scene geometry has changed"; - FitContent(); - } - - - void RadiographyWidget::OnContentChanged(const RadiographyScene::ContentChangedMessage& message) - { -// LOG(INFO) << "Scene content has changed"; - NotifyContentChanged(); - } - - void RadiographyWidget::OnLayerRemoved(const RadiographyScene::LayerRemovedMessage& message) - { - size_t removedLayerIndex = message.GetLayerIndex(); - if (hasSelection_ && selectedLayer_ == removedLayerIndex) - { - Unselect(); - } - NotifyContentChanged(); - } - - void RadiographyWidget::SetInvert(bool invert) - { - if (invert_ != invert) - { - invert_ = invert; - NotifyContentChanged(); - } - } - - - void RadiographyWidget::SwitchInvert() - { - invert_ = !invert_; - NotifyContentChanged(); - } - - - void RadiographyWidget::SetInterpolation(ImageInterpolation interpolation) - { - if (interpolation_ != interpolation) - { - interpolation_ = interpolation; - NotifyContentChanged(); - } - } - - void RadiographyWidget::SetScene(boost::shared_ptr<RadiographyScene> scene) - { - scene_ = scene; - - Register<RadiographyScene::GeometryChangedMessage>(*scene_, &RadiographyWidget::OnGeometryChanged); - Register<RadiographyScene::ContentChangedMessage>(*scene_, &RadiographyWidget::OnContentChanged); - Register<RadiographyScene::LayerRemovedMessage>(*scene_, &RadiographyWidget::OnLayerRemoved); - - Unselect(); - - NotifyContentChanged(); - - // force redraw - FitContent(); - } -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyWidget.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../Deprecated/Widgets/WorldSceneWidget.h" -#include "../Messages/ObserverBase.h" -#include "RadiographyScene.h" - - -namespace OrthancStone -{ - class RadiographyMaskLayer; - - class RadiographyWidget : - public Deprecated::WorldSceneWidget, - public ObserverBase<RadiographyWidget>, - public IObservable - { - public: - ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, SelectionChangedMessage, RadiographyWidget); - - private: - boost::shared_ptr<RadiographyScene> scene_; - std::unique_ptr<Orthanc::ImageAccessor> floatBuffer_; - std::unique_ptr<CairoSurface> cairoBuffer_; - bool invert_; - ImageInterpolation interpolation_; - bool hasSelection_; - size_t selectedLayer_; - - bool RenderInternal(unsigned int width, - unsigned int height, - ImageInterpolation interpolation); - - protected: - virtual Extent2D GetSceneExtent() - { - return scene_->GetSceneExtent(false); - } - - virtual bool RenderScene(CairoContext& context, - const Deprecated::ViewportGeometry& view); - - virtual void RenderBackground(Orthanc::ImageAccessor& image, float minValue, float maxValue); - - bool IsInvertedInternal() const; - - public: - RadiographyWidget(boost::shared_ptr<RadiographyScene> scene, // TODO: check how we can avoid boost::shared_ptr here since we don't want them in the public API (app is keeping a boost::shared_ptr to this right now) - const std::string& name); - - RadiographyScene& GetScene() const - { - return *scene_; - } - - void SetScene(boost::shared_ptr<RadiographyScene> scene); - - void Select(size_t layer); - - void Unselect(); - - template<typename LayerType> bool SelectLayerByType(size_t index = 0); - - bool LookupSelectedLayer(size_t& layer) const; - - void OnGeometryChanged(const RadiographyScene::GeometryChangedMessage& message); - - void OnContentChanged(const RadiographyScene::ContentChangedMessage& message); - - void OnLayerRemoved(const RadiographyScene::LayerRemovedMessage& message); - - void SetInvert(bool invert); - - void SwitchInvert(); - - bool IsInverted() const - { - return invert_; - } - - void SetInterpolation(ImageInterpolation interpolation); - - ImageInterpolation GetInterpolation() const - { - return interpolation_; - } - }; - - template<typename LayerType> bool RadiographyWidget::SelectLayerByType(size_t index) - { - std::vector<size_t> layerIndexes; - size_t count = 0; - scene_->GetLayersIndexes(layerIndexes); - - for (size_t i = 0; i < layerIndexes.size(); ++i) - { - const LayerType* typedLayer = dynamic_cast<const LayerType*>(&(scene_->GetLayer(layerIndexes[i]))); - if (typedLayer != NULL) - { - if (count == index) - { - Select(layerIndexes[i]); - return true; - } - count++; - } - } - - return false; - } -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyWindowingTracker.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,192 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "RadiographyWindowingTracker.h" -#include "RadiographyWidget.h" - -#include <OrthancException.h> - - -namespace OrthancStone -{ - class RadiographyWindowingTracker::UndoRedoCommand : public UndoRedoStack::ICommand - { - private: - RadiographyScene& scene_; - float sourceCenter_; - float sourceWidth_; - float targetCenter_; - float targetWidth_; - - public: - UndoRedoCommand(const RadiographyWindowingTracker& tracker) : - scene_(tracker.scene_), - sourceCenter_(tracker.sourceCenter_), - sourceWidth_(tracker.sourceWidth_) - { - scene_.GetWindowingWithDefault(targetCenter_, targetWidth_); - } - - virtual void Undo() const - { - scene_.SetWindowing(sourceCenter_, sourceWidth_); - } - - virtual void Redo() const - { - scene_.SetWindowing(targetCenter_, targetWidth_); - } - }; - - - void RadiographyWindowingTracker::ComputeAxisEffect(int& deltaCenter, - int& deltaWidth, - int delta, - Action actionNegative, - Action actionPositive) - { - if (delta < 0) - { - switch (actionNegative) - { - case Action_IncreaseWidth: - deltaWidth = -delta; - break; - - case Action_DecreaseWidth: - deltaWidth = delta; - break; - - case Action_IncreaseCenter: - deltaCenter = -delta; - break; - - case Action_DecreaseCenter: - deltaCenter = delta; - break; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - } - else if (delta > 0) - { - switch (actionPositive) - { - case Action_IncreaseWidth: - deltaWidth = delta; - break; - - case Action_DecreaseWidth: - deltaWidth = -delta; - break; - - case Action_IncreaseCenter: - deltaCenter = delta; - break; - - case Action_DecreaseCenter: - deltaCenter = -delta; - break; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - } - } - - - RadiographyWindowingTracker::RadiographyWindowingTracker(UndoRedoStack& undoRedoStack, - RadiographyScene& scene, - RadiographyWidget& widget, - ImageInterpolation interpolationDuringTracking, - int x, - int y, - Action leftAction, - Action rightAction, - Action upAction, - Action downAction) : - undoRedoStack_(undoRedoStack), - scene_(scene), - widget_(widget), - initialWidgetInterpolation_(widget.GetInterpolation()), - clickX_(x), - clickY_(y), - leftAction_(leftAction), - rightAction_(rightAction), - upAction_(upAction), - downAction_(downAction) - { - scene_.GetWindowingWithDefault(sourceCenter_, sourceWidth_); - widget_.SetInterpolation(interpolationDuringTracking); - - float minValue, maxValue; - scene.GetRange(minValue, maxValue); - - assert(minValue <= maxValue); - - float delta = (maxValue - minValue); - strength_ = delta / 1000.0f; // 1px move will change the ww/wc by 0.1% - - if (strength_ < 1) - { - strength_ = 1; - } - } - - - void RadiographyWindowingTracker::Render(CairoContext& context, - double zoom) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - - - void RadiographyWindowingTracker::MouseUp() - { - widget_.SetInterpolation(initialWidgetInterpolation_); - undoRedoStack_.Add(new UndoRedoCommand(*this)); - } - - - void RadiographyWindowingTracker::MouseMove(int displayX, - int displayY, - double sceneX, - double sceneY, - const std::vector<Deprecated::Touch>& displayTouches, - const std::vector<Deprecated::Touch>& sceneTouches) - { - // This follows the behavior of the Osimis Web viewer: - // https://bitbucket.org/osimis/osimis-webviewer-plugin/src/master/frontend/src/app/viewport/image-plugins/windowing-viewport-tool.class.js - - static const float SCALE = 1.0; - - int deltaCenter = 0; - int deltaWidth = 0; - - ComputeAxisEffect(deltaCenter, deltaWidth, displayX - clickX_, leftAction_, rightAction_); - ComputeAxisEffect(deltaCenter, deltaWidth, displayY - clickY_, upAction_, downAction_); - - float newCenter = sourceCenter_ + (deltaCenter / SCALE * strength_); - float newWidth = sourceWidth_ + (deltaWidth / SCALE * strength_); - scene_.SetWindowing(newCenter, newWidth); - } -}
--- a/OrthancStone/Sources/Deprecated/Radiography/RadiographyWindowingTracker.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../Toolbox/UndoRedoStack.h" -#include "../Deprecated/Widgets/IWorldSceneMouseTracker.h" -#include "RadiographyScene.h" - -namespace OrthancStone -{ - - class RadiographyWidget; - - class RadiographyWindowingTracker : public Deprecated::IWorldSceneMouseTracker - { - public: - enum Action - { - Action_IncreaseWidth, - Action_DecreaseWidth, - Action_IncreaseCenter, - Action_DecreaseCenter - }; - - private: - class UndoRedoCommand; - - UndoRedoStack& undoRedoStack_; - RadiographyScene& scene_; - RadiographyWidget& widget_; - ImageInterpolation initialWidgetInterpolation_; - int clickX_; - int clickY_; - Action leftAction_; - Action rightAction_; - Action upAction_; - Action downAction_; - float strength_; - float sourceCenter_; - float sourceWidth_; - - static void ComputeAxisEffect(int& deltaCenter, - int& deltaWidth, - int delta, - Action actionNegative, - Action actionPositive); - - public: - RadiographyWindowingTracker(UndoRedoStack& undoRedoStack, - RadiographyScene& scene, - RadiographyWidget& widget, - ImageInterpolation interpolationDuringTracking, - int x, - int y, - Action leftAction, - Action rightAction, - Action upAction, - Action downAction); - - virtual bool HasRender() const - { - return false; - } - - virtual void Render(CairoContext& context, - double zoom); - - virtual void MouseUp(); - - virtual void MouseMove(int displayX, - int displayY, - double sceneX, - double sceneY, - const std::vector<Deprecated::Touch>& displayTouches, - const std::vector<Deprecated::Touch>& sceneTouches); - }; -}
--- a/OrthancStone/Sources/Deprecated/SmartLoader.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,285 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "SmartLoader.h" - -#include "../StoneException.h" -#include "Layers/DicomSeriesVolumeSlicer.h" -#include "Layers/FrameRenderer.h" -#include "Widgets/SliceViewerWidget.h" - -#include <Images/Image.h> -#include <Logging.h> - -namespace Deprecated -{ - enum CachedSliceStatus - { - CachedSliceStatus_ScheduledToLoad, - CachedSliceStatus_GeometryLoaded, - CachedSliceStatus_ImageLoaded - }; - - class SmartLoader::CachedSlice : public IVolumeSlicer - { - public: - class RendererFactory : public LayerReadyMessage::IRendererFactory - { - private: - const CachedSlice& that_; - - public: - RendererFactory(const CachedSlice& that) : - that_(that) - { - } - - virtual ILayerRenderer* CreateRenderer() const - { - bool isFull = (that_.effectiveQuality_ == SliceImageQuality_FullPng || - that_.effectiveQuality_ == SliceImageQuality_FullPam); - - return FrameRenderer::CreateRenderer(*that_.image_, *that_.slice_, isFull); - } - }; - - unsigned int sliceIndex_; - std::unique_ptr<Slice> slice_; - boost::shared_ptr<Orthanc::ImageAccessor> image_; - SliceImageQuality effectiveQuality_; - CachedSliceStatus status_; - - public: - virtual ~CachedSlice() - { - } - - virtual bool GetExtent(std::vector<OrthancStone::Vector>& points, - const OrthancStone::CoordinateSystem3D& viewportSlice) - { - // TODO: viewportSlice is not used !!!! - slice_->GetExtent(points); - return true; - } - - virtual void ScheduleLayerCreation(const OrthancStone::CoordinateSystem3D& viewportSlice) - { - // TODO: viewportSlice is not used !!!! - - // it has already been loaded -> trigger the "layer ready" message immediately otherwise, do nothing now. The LayerReady will be triggered - // once the VolumeSlicer is ready - if (status_ == CachedSliceStatus_ImageLoaded) - { - LOG(WARNING) << "ScheduleLayerCreation for CachedSlice (image is loaded): " << slice_->GetOrthancInstanceId(); - - RendererFactory factory(*this); - BroadcastMessage(IVolumeSlicer::LayerReadyMessage(*this, factory, slice_->GetGeometry())); - } - else - { - LOG(WARNING) << "ScheduleLayerCreation for CachedSlice (image is not loaded yet): " << slice_->GetOrthancInstanceId(); - } - } - - CachedSlice* Clone() const - { - CachedSlice* output = new CachedSlice; - output->sliceIndex_ = sliceIndex_; - output->slice_.reset(slice_->Clone()); - output->image_ = image_; - output->effectiveQuality_ = effectiveQuality_; - output->status_ = status_; - - return output; - } - - }; - - - SmartLoader::SmartLoader(boost::shared_ptr<OrthancApiClient> orthancApiClient) : - imageQuality_(SliceImageQuality_FullPam), - orthancApiClient_(orthancApiClient) - { - } - - void SmartLoader::SetFrameInWidget(SliceViewerWidget& sliceViewer, - size_t layerIndex, - const std::string& instanceId, - unsigned int frame) - { - // TODO: check if this frame has already been loaded or is already being loaded. - // - if already loaded: create a "clone" that will emit the GeometryReady/ImageReady messages "immediately" - // (it can not be immediate because Observers needs to register first and this is done after this method returns) - // - if currently loading, we need to return an object that will observe the existing VolumeSlicer and forward - // the messages to its observables - // in both cases, we must be carefull about objects lifecycle !!! - - boost::shared_ptr<IVolumeSlicer> layerSource; - std::string sliceKeyId = instanceId + ":" + boost::lexical_cast<std::string>(frame); - SmartLoader::CachedSlice* cachedSlice = NULL; - - if (cachedSlices_.find(sliceKeyId) != cachedSlices_.end()) // && cachedSlices_[sliceKeyId]->status_ == CachedSliceStatus_Loaded) - { - layerSource.reset(cachedSlices_[sliceKeyId]->Clone()); - cachedSlice = dynamic_cast<SmartLoader::CachedSlice*>(layerSource.get()); - } - else - { - layerSource.reset(new DicomSeriesVolumeSlicer); - dynamic_cast<DicomSeriesVolumeSlicer*>(layerSource.get())->Connect(orthancApiClient_); - dynamic_cast<DicomSeriesVolumeSlicer*>(layerSource.get())->SetImageQuality(imageQuality_); - Register<IVolumeSlicer::GeometryReadyMessage>(*layerSource, &SmartLoader::OnLayerGeometryReady); - Register<DicomSeriesVolumeSlicer::FrameReadyMessage>(*layerSource, &SmartLoader::OnFrameReady); - Register<IVolumeSlicer::LayerReadyMessage>(*layerSource, &SmartLoader::OnLayerReady); - dynamic_cast<DicomSeriesVolumeSlicer*>(layerSource.get())->LoadFrame(instanceId, frame); - } - - // make sure that the widget registers the events before we trigger them - if (sliceViewer.GetLayerCount() == layerIndex) - { - sliceViewer.AddLayer(layerSource); - } - else if (sliceViewer.GetLayerCount() > layerIndex) - { - sliceViewer.ReplaceLayer(layerIndex, layerSource); - } - else - { - throw OrthancStone::StoneException(OrthancStone::ErrorCode_CanOnlyAddOneLayerAtATime); - } - - if (cachedSlice != NULL) - { - BroadcastMessage(IVolumeSlicer::GeometryReadyMessage(*cachedSlice)); - } - - } - - void SmartLoader::PreloadSlice(const std::string instanceId, - unsigned int frame) - { - // TODO: reactivate -> need to be able to ScheduleLayerLoading in IVolumeSlicer without calling ScheduleLayerCreation - return; - // TODO: check if it is already in the cache - - - - // create the slice in the cache with "empty" data - boost::shared_ptr<CachedSlice> cachedSlice(new CachedSlice); - cachedSlice->slice_.reset(new Slice(instanceId, frame)); - cachedSlice->status_ = CachedSliceStatus_ScheduledToLoad; - std::string sliceKeyId = instanceId + ":" + boost::lexical_cast<std::string>(frame); - - LOG(WARNING) << "Will preload: " << sliceKeyId; - - cachedSlices_[sliceKeyId] = boost::shared_ptr<CachedSlice>(cachedSlice); - - std::unique_ptr<IVolumeSlicer> layerSource(new DicomSeriesVolumeSlicer); - dynamic_cast<DicomSeriesVolumeSlicer*>(layerSource.get())->Connect(orthancApiClient_); - dynamic_cast<DicomSeriesVolumeSlicer*>(layerSource.get())->SetImageQuality(imageQuality_); - Register<IVolumeSlicer::GeometryReadyMessage>(*layerSource, &SmartLoader::OnLayerGeometryReady); - Register<DicomSeriesVolumeSlicer::FrameReadyMessage>(*layerSource, &SmartLoader::OnFrameReady); - Register<IVolumeSlicer::LayerReadyMessage>(*layerSource, &SmartLoader::OnLayerReady); - dynamic_cast<DicomSeriesVolumeSlicer*>(layerSource.get())->LoadFrame(instanceId, frame); - - // keep a ref to the VolumeSlicer until the slice is fully loaded and saved to cache - preloadingInstances_[sliceKeyId] = boost::shared_ptr<IVolumeSlicer>(layerSource.release()); - } - - -// void PreloadStudy(const std::string studyId) -// { -// /* TODO */ -// } - -// void PreloadSeries(const std::string seriesId) -// { -// /* TODO */ -// } - - - void SmartLoader::OnLayerGeometryReady(const IVolumeSlicer::GeometryReadyMessage& message) - { - const DicomSeriesVolumeSlicer& source = - dynamic_cast<const DicomSeriesVolumeSlicer&>(message.GetOrigin()); - - // save/replace the slice in cache - const Slice& slice = source.GetSlice(0); // TODO handle GetSliceCount() - std::string sliceKeyId = (slice.GetOrthancInstanceId() + ":" + - boost::lexical_cast<std::string>(slice.GetFrame())); - - LOG(WARNING) << "Geometry ready: " << sliceKeyId; - - boost::shared_ptr<CachedSlice> cachedSlice(new CachedSlice); - cachedSlice->slice_.reset(slice.Clone()); - cachedSlice->effectiveQuality_ = source.GetImageQuality(); - cachedSlice->status_ = CachedSliceStatus_GeometryLoaded; - - cachedSlices_[sliceKeyId] = boost::shared_ptr<CachedSlice>(cachedSlice); - - // re-emit original Layer message to observers - BroadcastMessage(message); - } - - - void SmartLoader::OnFrameReady(const DicomSeriesVolumeSlicer::FrameReadyMessage& message) - { - // save/replace the slice in cache - const Slice& slice = message.GetSlice(); - std::string sliceKeyId = (slice.GetOrthancInstanceId() + ":" + - boost::lexical_cast<std::string>(slice.GetFrame())); - - LOG(WARNING) << "Image ready: " << sliceKeyId; - - boost::shared_ptr<CachedSlice> cachedSlice(new CachedSlice); - cachedSlice->image_.reset(Orthanc::Image::Clone(message.GetFrame())); - cachedSlice->effectiveQuality_ = message.GetImageQuality(); - cachedSlice->slice_.reset(message.GetSlice().Clone()); - cachedSlice->status_ = CachedSliceStatus_ImageLoaded; - - cachedSlices_[sliceKeyId] = cachedSlice; - - // re-emit original Layer message to observers - BroadcastMessage(message); - } - - - void SmartLoader::OnLayerReady(const IVolumeSlicer::LayerReadyMessage& message) - { - const DicomSeriesVolumeSlicer& source = - dynamic_cast<const DicomSeriesVolumeSlicer&>(message.GetOrigin()); - - const Slice& slice = source.GetSlice(0); // TODO handle GetSliceCount() ? - std::string sliceKeyId = (slice.GetOrthancInstanceId() + ":" + - boost::lexical_cast<std::string>(slice.GetFrame())); - - LOG(WARNING) << "Layer ready: " << sliceKeyId; - - // remove the slice from the preloading slices now that it has been fully loaded and it is referenced in the cache - if (preloadingInstances_.find(sliceKeyId) != preloadingInstances_.end()) - { - preloadingInstances_.erase(sliceKeyId); - } - - // re-emit original Layer message to observers - BroadcastMessage(message); - } -}
--- a/OrthancStone/Sources/Deprecated/SmartLoader.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once -#include <map> - -#include "Layers/DicomSeriesVolumeSlicer.h" -#include "../Messages/IObservable.h" -#include "Toolbox/OrthancApiClient.h" - -namespace Deprecated -{ - class SliceViewerWidget; - - class SmartLoader : public OrthancStone::IObservable, public OrthancStone::ObserverBase<SmartLoader> - { - class CachedSlice; - - protected: - typedef std::map<std::string, boost::shared_ptr<SmartLoader::CachedSlice> > CachedSlices; - CachedSlices cachedSlices_; - - typedef std::map<std::string, boost::shared_ptr<IVolumeSlicer> > PreloadingInstances; - PreloadingInstances preloadingInstances_; - - SliceImageQuality imageQuality_; - boost::shared_ptr<OrthancApiClient> orthancApiClient_; - - public: - SmartLoader(boost::shared_ptr<OrthancApiClient> orthancApiClient); // TODO: add maxPreloadStorageSizeInBytes - -// void PreloadStudy(const std::string studyId); -// void PreloadSeries(const std::string seriesId); - void PreloadSlice(const std::string instanceId, unsigned int frame); - - void SetImageQuality(SliceImageQuality imageQuality) { imageQuality_ = imageQuality; } - - void SetFrameInWidget(SliceViewerWidget& sliceViewer, size_t layerIndex, const std::string& instanceId, unsigned int frame); - - void GetFirstInstanceIdForSeries(std::string& output, const std::string& seriesId); - - private: - void OnLayerGeometryReady(const IVolumeSlicer::GeometryReadyMessage& message); - void OnFrameReady(const DicomSeriesVolumeSlicer::FrameReadyMessage& message); - void OnLayerReady(const IVolumeSlicer::LayerReadyMessage& message); - - }; - -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/BaseWebService.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,178 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "BaseWebService.h" - -#include "../../Messages/IObservable.h" -#include "../../../Platforms/Generic/IOracleCommand.h" - -#include <OrthancException.h> - -#include <boost/shared_ptr.hpp> -#include <algorithm> -#include <Logging.h> - -namespace Deprecated -{ - - - class BaseWebService::BaseWebServicePayload : public Orthanc::IDynamicObject - { - private: - std::unique_ptr< MessageHandler<IWebService::HttpRequestSuccessMessage> > userSuccessHandler_; - std::unique_ptr< MessageHandler<IWebService::HttpRequestErrorMessage> > userFailureHandler_; - std::unique_ptr< Orthanc::IDynamicObject> userPayload_; - - public: - BaseWebServicePayload(MessageHandler<IWebService::HttpRequestSuccessMessage>* userSuccessHandler, - MessageHandler<IWebService::HttpRequestErrorMessage>* userFailureHandler, - Orthanc::IDynamicObject* userPayload) : - userSuccessHandler_(userSuccessHandler), - userFailureHandler_(userFailureHandler), - userPayload_(userPayload) - { - } - - void HandleSuccess(const IWebService::HttpRequestSuccessMessage& message) const - { - if (userSuccessHandler_.get() != NULL) - { - // recreate a success message with the user payload - IWebService::HttpRequestSuccessMessage successMessage(message.GetUri(), - message.GetAnswer(), - message.GetAnswerSize(), - message.GetAnswerHttpHeaders(), - userPayload_.get()); - userSuccessHandler_->Apply(successMessage); - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - } - - void HandleFailure(const IWebService::HttpRequestErrorMessage& message) const - { - if (userFailureHandler_.get() != NULL) - { - // recreate a failure message with the user payload - IWebService::HttpRequestErrorMessage failureMessage(message.GetUri(), - message.GetHttpStatus(), - userPayload_.get()); - - userFailureHandler_->Apply(failureMessage); - } - } - - }; - - - void BaseWebService::GetAsync(const std::string& uri, - const HttpHeaders& headers, - Orthanc::IDynamicObject* payload /* takes ownership */, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, - unsigned int timeoutInSeconds) - { - if (!cacheEnabled_ || cache_.find(uri) == cache_.end()) - { - GetAsyncInternal(uri, headers, - new BaseWebService::BaseWebServicePayload(successCallback, failureCallback, payload), // ownership is transfered - new DeprecatedCallable<BaseWebService, IWebService::HttpRequestSuccessMessage> - (GetSharedObserver(), &BaseWebService::CacheAndNotifyHttpSuccess), - new DeprecatedCallable<BaseWebService, IWebService::HttpRequestErrorMessage> - (GetSharedObserver(), &BaseWebService::NotifyHttpError), - timeoutInSeconds); - } - else - { - // put the uri on top of the most recently accessed list - std::deque<std::string>::iterator it = std::find(orderedCacheKeys_.begin(), orderedCacheKeys_.end(), uri); - if (it != orderedCacheKeys_.end()) - { - std::string uri = *it; - orderedCacheKeys_.erase(it); - orderedCacheKeys_.push_front(uri); - } - - // create a command and "post" it to the Oracle so it is executed and commited "later" - NotifyHttpSuccessLater(cache_[uri], payload, successCallback); - } - - } - - - - void BaseWebService::NotifyHttpSuccess(const IWebService::HttpRequestSuccessMessage& message) - { - if (message.HasPayload()) - { - dynamic_cast<const BaseWebServicePayload&>(message.GetPayload()).HandleSuccess(message); - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - } - - void BaseWebService::CacheAndNotifyHttpSuccess(const IWebService::HttpRequestSuccessMessage& message) - { - if (cacheEnabled_) - { - while (cacheCurrentSize_ + message.GetAnswerSize() > cacheMaxSize_ && orderedCacheKeys_.size() > 0) - { - VLOG(1) << "BaseWebService: clearing cache: " << cacheCurrentSize_ << "/" << cacheMaxSize_ << "(" << message.GetAnswerSize() << ")"; - const std::string& oldestUri = orderedCacheKeys_.back(); - HttpCache::iterator it = cache_.find(oldestUri); - if (it != cache_.end()) - { - cacheCurrentSize_ -= it->second->GetAnswerSize(); - cache_.erase(it); - } - orderedCacheKeys_.pop_back(); - - } - - boost::shared_ptr<CachedHttpRequestSuccessMessage> cachedMessage(new CachedHttpRequestSuccessMessage(message)); - cache_[message.GetUri()] = cachedMessage; - orderedCacheKeys_.push_front(message.GetUri()); - cacheCurrentSize_ += message.GetAnswerSize(); - } - - NotifyHttpSuccess(message); - } - - void BaseWebService::NotifyHttpError(const IWebService::HttpRequestErrorMessage& message) - { - if (message.HasPayload()) - { - dynamic_cast<const BaseWebServicePayload&>(message.GetPayload()).HandleFailure(message); - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - } - - - - -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/BaseWebService.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,137 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "IWebService.h" -#include "../../Messages/ObserverBase.h" - -#include <string> -#include <map> -#include <deque> - -namespace Deprecated -{ - // This is an intermediate of IWebService that implements some caching on - // the HTTP GET requests - class BaseWebService : public IWebService, public OrthancStone::ObserverBase<BaseWebService> - { - public: - class CachedHttpRequestSuccessMessage - { - protected: - std::string uri_; - void* answer_; - size_t answerSize_; - IWebService::HttpHeaders answerHeaders_; - - public: - CachedHttpRequestSuccessMessage(const IWebService::HttpRequestSuccessMessage& message) : - uri_(message.GetUri()), - answerSize_(message.GetAnswerSize()), - answerHeaders_(message.GetAnswerHttpHeaders()) - { - answer_ = malloc(answerSize_); - memcpy(answer_, message.GetAnswer(), answerSize_); - } - - ~CachedHttpRequestSuccessMessage() - { - free(answer_); - } - - const std::string& GetUri() const - { - return uri_; - } - - const void* GetAnswer() const - { - return answer_; - } - - size_t GetAnswerSize() const - { - return answerSize_; - } - - const IWebService::HttpHeaders& GetAnswerHttpHeaders() const - { - return answerHeaders_; - } - - }; - protected: - class BaseWebServicePayload; - - bool cacheEnabled_; - size_t cacheCurrentSize_; - size_t cacheMaxSize_; - - typedef std::map<std::string, boost::shared_ptr<CachedHttpRequestSuccessMessage> > HttpCache; - HttpCache cache_; - std::deque<std::string> orderedCacheKeys_; - - public: - BaseWebService() : - cacheEnabled_(false), - cacheCurrentSize_(0), - cacheMaxSize_(100*1024*1024) - { - } - - virtual ~BaseWebService() - { - } - - virtual void EnableCache(bool enable) - { - cacheEnabled_ = enable; - } - - virtual void GetAsync(const std::string& uri, - const HttpHeaders& headers, - Orthanc::IDynamicObject* payload /* takes ownership */, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, - unsigned int timeoutInSeconds = 60); - - protected: - virtual void GetAsyncInternal(const std::string& uri, - const HttpHeaders& headers, - Orthanc::IDynamicObject* payload /* takes ownership */, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, - unsigned int timeoutInSeconds = 60) = 0; - - virtual void NotifyHttpSuccessLater(boost::shared_ptr<BaseWebService::CachedHttpRequestSuccessMessage> cachedHttpMessage, - Orthanc::IDynamicObject* payload, // takes ownership - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback) = 0; - - private: - void NotifyHttpSuccess(const IWebService::HttpRequestSuccessMessage& message); - - void NotifyHttpError(const IWebService::HttpRequestErrorMessage& message); - - void CacheAndNotifyHttpSuccess(const IWebService::HttpRequestSuccessMessage& message); - - }; -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/DicomFrameConverter.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,282 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "DicomFrameConverter.h" - -#include "../../Toolbox/LinearAlgebra.h" - -#include <Images/Image.h> -#include <Images/ImageProcessing.h> -#include <OrthancException.h> -#include <Toolbox.h> - -namespace Deprecated -{ - static const Orthanc::DicomTag IMAGE_TAGS[] = - { - Orthanc::DICOM_TAG_BITS_STORED, - Orthanc::DICOM_TAG_DOSE_GRID_SCALING, - Orthanc::DICOM_TAG_PHOTOMETRIC_INTERPRETATION, - Orthanc::DICOM_TAG_PIXEL_REPRESENTATION, - Orthanc::DICOM_TAG_RESCALE_INTERCEPT, - Orthanc::DICOM_TAG_RESCALE_SLOPE, - Orthanc::DICOM_TAG_WINDOW_CENTER, - Orthanc::DICOM_TAG_WINDOW_WIDTH - }; - - - void DicomFrameConverter::SetDefaultParameters() - { - isSigned_ = true; - isColor_ = false; - hasRescale_ = false; - rescaleIntercept_ = 0; - rescaleSlope_ = 1; - hasDefaultWindow_ = false; - defaultWindowCenter_ = 128; - defaultWindowWidth_ = 256; - expectedPixelFormat_ = Orthanc::PixelFormat_Grayscale16; - } - - - void DicomFrameConverter::ReadParameters(const Orthanc::DicomMap& dicom) - { - SetDefaultParameters(); - - OrthancStone::Vector c, w; - if (OrthancStone::LinearAlgebra::ParseVector(c, dicom, Orthanc::DICOM_TAG_WINDOW_CENTER) && - OrthancStone::LinearAlgebra::ParseVector(w, dicom, Orthanc::DICOM_TAG_WINDOW_WIDTH) && - c.size() > 0 && - w.size() > 0) - { - hasDefaultWindow_ = true; - defaultWindowCenter_ = static_cast<float>(c[0]); - defaultWindowWidth_ = static_cast<float>(w[0]); - } - - int32_t tmp; - if (!dicom.ParseInteger32(tmp, Orthanc::DICOM_TAG_PIXEL_REPRESENTATION)) - { - // Type 1 tag, must be present - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); - } - - isSigned_ = (tmp == 1); - - double doseGridScaling; - bool isRTDose = false; - - if (dicom.ParseDouble(rescaleIntercept_, Orthanc::DICOM_TAG_RESCALE_INTERCEPT) && - dicom.ParseDouble(rescaleSlope_, Orthanc::DICOM_TAG_RESCALE_SLOPE)) - { - hasRescale_ = true; - } - else if (dicom.ParseDouble(doseGridScaling, Orthanc::DICOM_TAG_DOSE_GRID_SCALING)) - { - // This is for RT-DOSE - hasRescale_ = true; - isRTDose = true; - rescaleIntercept_ = 0; - rescaleSlope_ = doseGridScaling; - - if (!dicom.ParseInteger32(tmp, Orthanc::DICOM_TAG_BITS_STORED)) - { - // Type 1 tag, must be present - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); - } - - switch (tmp) - { - case 16: - expectedPixelFormat_ = Orthanc::PixelFormat_Grayscale16; - break; - - case 32: - expectedPixelFormat_ = Orthanc::PixelFormat_Grayscale32; - break; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); - } - } - - std::string photometric; - if (dicom.LookupStringValue(photometric, Orthanc::DICOM_TAG_PHOTOMETRIC_INTERPRETATION, false)) - { - photometric = Orthanc::Toolbox::StripSpaces(photometric); - } - else - { - // Type 1 tag, must be present - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); - } - - photometric_ = Orthanc::StringToPhotometricInterpretation(photometric.c_str()); - - isColor_ = (photometric != "MONOCHROME1" && - photometric != "MONOCHROME2"); - - // TODO Add more checks, e.g. on the number of bytes per value - // (cf. DicomImageInformation.h in Orthanc) - - if (!isRTDose) - { - if (isColor_) - { - expectedPixelFormat_ = Orthanc::PixelFormat_RGB24; - } - else if (isSigned_) - { - expectedPixelFormat_ = Orthanc::PixelFormat_SignedGrayscale16; - } - else - { - expectedPixelFormat_ = Orthanc::PixelFormat_Grayscale16; - } - } - } - - - void DicomFrameConverter::ReadParameters(const OrthancPlugins::IDicomDataset& dicom) - { - Orthanc::DicomMap converted; - - for (size_t i = 0; i < sizeof(IMAGE_TAGS) / sizeof(Orthanc::DicomTag); i++) - { - OrthancPlugins::DicomTag tag(IMAGE_TAGS[i].GetGroup(), IMAGE_TAGS[i].GetElement()); - - std::string value; - if (dicom.GetStringValue(value, tag)) - { - converted.SetValue(IMAGE_TAGS[i], value, false); - } - } - - ReadParameters(converted); - } - - - void DicomFrameConverter::ConvertFrameInplace(std::unique_ptr<Orthanc::ImageAccessor>& source) const - { - assert(sizeof(float) == 4); - - if (source.get() == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - if (source->GetFormat() == GetExpectedPixelFormat() && - source->GetFormat() == Orthanc::PixelFormat_RGB24) - { - // No conversion has to be done, check out (*) - return; - } - else - { - source.reset(ConvertFrame(*source)); - } - } - - - Orthanc::ImageAccessor* DicomFrameConverter::ConvertFrame(const Orthanc::ImageAccessor& source) const - { - assert(sizeof(float) == 4); - - Orthanc::PixelFormat sourceFormat = source.GetFormat(); - - if (sourceFormat != GetExpectedPixelFormat()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); - } - - if (sourceFormat == Orthanc::PixelFormat_RGB24) - { - // This is the case of a color image. No conversion has to be done (*) - std::unique_ptr<Orthanc::Image> converted(new Orthanc::Image(Orthanc::PixelFormat_RGB24, - source.GetWidth(), - source.GetHeight(), - false)); - Orthanc::ImageProcessing::Copy(*converted, source); - return converted.release(); - } - else - { - assert(sourceFormat == Orthanc::PixelFormat_Grayscale16 || - sourceFormat == Orthanc::PixelFormat_Grayscale32 || - sourceFormat == Orthanc::PixelFormat_SignedGrayscale16); - - // This is the case of a grayscale frame. Convert it to Float32. - std::unique_ptr<Orthanc::Image> converted(new Orthanc::Image(Orthanc::PixelFormat_Float32, - source.GetWidth(), - source.GetHeight(), - false)); - Orthanc::ImageProcessing::Convert(*converted, source); - - // Correct rescale slope/intercept if need be - ApplyRescale(*converted, sourceFormat != Orthanc::PixelFormat_Grayscale32); - - return converted.release(); - } - } - - - void DicomFrameConverter::ApplyRescale(Orthanc::ImageAccessor& image, - bool useDouble) const - { - if (image.GetFormat() != Orthanc::PixelFormat_Float32) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); - } - - if (hasRescale_) - { - for (unsigned int y = 0; y < image.GetHeight(); y++) - { - float* p = reinterpret_cast<float*>(image.GetRow(y)); - - if (useDouble) - { - // Slower, accurate implementation using double - for (unsigned int x = 0; x < image.GetWidth(); x++, p++) - { - double value = static_cast<double>(*p); - *p = static_cast<float>(value * rescaleSlope_ + rescaleIntercept_); - } - } - else - { - // Fast, approximate implementation using float - for (unsigned int x = 0; x < image.GetWidth(); x++, p++) - { - *p = (*p) * static_cast<float>(rescaleSlope_) + static_cast<float>(rescaleIntercept_); - } - } - } - } - } - - - double DicomFrameConverter::Apply(double x) const - { - return x * rescaleSlope_ + rescaleIntercept_; - } - -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/DicomFrameConverter.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,170 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include <IDicomDataset.h> -#include <Compatibility.h> -#include <DicomFormat/DicomMap.h> -#include <Images/ImageAccessor.h> - -#include <memory> - -namespace Deprecated -{ - /** - * This class is responsible for converting the pixel format of a - * DICOM frame coming from Orthanc, into a pixel format that is - * suitable for Stone, given the relevant DICOM tags: - * - Color frames will stay in the RGB24 format. - * - Grayscale frames will be converted to the Float32 format. - **/ - class DicomFrameConverter - { - private: - bool isSigned_; - bool isColor_; - bool hasRescale_; - double rescaleIntercept_; - double rescaleSlope_; - bool hasDefaultWindow_; - double defaultWindowCenter_; - double defaultWindowWidth_; - - Orthanc::PhotometricInterpretation photometric_; - Orthanc::PixelFormat expectedPixelFormat_; - - void SetDefaultParameters(); - - public: - DicomFrameConverter() - { - SetDefaultParameters(); - } - - ~DicomFrameConverter() - { - // TODO: check whether this dtor is called or not - // An MSVC warning explains that declaring an - // std::unique_ptr with a forward-declared type - // prevents its dtor from being called. Does not - // seem an issue here (only POD types inside), but - // definitely something to keep an eye on. - (void)0; - } - - // AM: this is required to serialize/deserialize it - DicomFrameConverter( - bool isSigned, - bool isColor, - bool hasRescale, - double rescaleIntercept, - double rescaleSlope, - bool hasDefaultWindow, - double defaultWindowCenter, - double defaultWindowWidth, - Orthanc::PhotometricInterpretation photometric, - Orthanc::PixelFormat expectedPixelFormat - ): - isSigned_(isSigned), - isColor_(isColor), - hasRescale_(hasRescale), - rescaleIntercept_(rescaleIntercept), - rescaleSlope_(rescaleSlope), - hasDefaultWindow_(hasDefaultWindow), - defaultWindowCenter_(defaultWindowCenter), - defaultWindowWidth_(defaultWindowWidth), - photometric_(photometric), - expectedPixelFormat_(expectedPixelFormat) - {} - - void GetParameters(bool& isSigned, - bool& isColor, - bool& hasRescale, - double& rescaleIntercept, - double& rescaleSlope, - bool& hasDefaultWindow, - double& defaultWindowCenter, - double& defaultWindowWidth, - Orthanc::PhotometricInterpretation& photometric, - Orthanc::PixelFormat& expectedPixelFormat) const - { - isSigned = isSigned_; - isColor = isColor_; - hasRescale = hasRescale_; - rescaleIntercept = rescaleIntercept_; - rescaleSlope = rescaleSlope_; - hasDefaultWindow = hasDefaultWindow_; - defaultWindowCenter = defaultWindowCenter_; - defaultWindowWidth = defaultWindowWidth_; - photometric = photometric_; - expectedPixelFormat = expectedPixelFormat_; - } - - Orthanc::PixelFormat GetExpectedPixelFormat() const - { - return expectedPixelFormat_; - } - - Orthanc::PhotometricInterpretation GetPhotometricInterpretation() const - { - return photometric_; - } - - void ReadParameters(const Orthanc::DicomMap& dicom); - - void ReadParameters(const OrthancPlugins::IDicomDataset& dicom); - - bool HasDefaultWindow() const - { - return hasDefaultWindow_; - } - - double GetDefaultWindowCenter() const - { - return defaultWindowCenter_; - } - - double GetDefaultWindowWidth() const - { - return defaultWindowWidth_; - } - - double GetRescaleIntercept() const - { - return rescaleIntercept_; - } - - double GetRescaleSlope() const - { - return rescaleSlope_; - } - - void ConvertFrameInplace(std::unique_ptr<Orthanc::ImageAccessor>& source) const; - - Orthanc::ImageAccessor* ConvertFrame(const Orthanc::ImageAccessor& source) const; - - void ApplyRescale(Orthanc::ImageAccessor& image, - bool useDouble) const; - - double Apply(double x) const; - }; -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/DownloadStack.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,196 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "DownloadStack.h" - -#include <OrthancException.h> - -#include <cassert> - -namespace Deprecated -{ - bool DownloadStack::CheckInvariants() const - { - std::vector<bool> dequeued(nodes_.size(), true); - - int i = firstNode_; - while (i != NIL) - { - const Node& node = nodes_[i]; - - dequeued[i] = false; - - if (node.next_ != NIL && - nodes_[node.next_].prev_ != i) - { - return false; - } - - if (node.prev_ != NIL && - nodes_[node.prev_].next_ != i) - { - return false; - } - - i = nodes_[i].next_; - } - - for (size_t i = 0; i < nodes_.size(); i++) - { - if (nodes_[i].dequeued_ != dequeued[i]) - { - return false; - } - } - - return true; - } - - - DownloadStack::DownloadStack(unsigned int size) - { - nodes_.resize(size); - - if (size == 0) - { - firstNode_ = NIL; - } - else - { - for (size_t i = 0; i < size; i++) - { - nodes_[i].prev_ = static_cast<int>(i - 1); - nodes_[i].next_ = static_cast<int>(i + 1); - nodes_[i].dequeued_ = false; - } - - nodes_.front().prev_ = NIL; - nodes_.back().next_ = NIL; - firstNode_ = 0; - } - - assert(CheckInvariants()); - } - - - DownloadStack::~DownloadStack() - { - assert(CheckInvariants()); - } - - - bool DownloadStack::Pop(unsigned int& value) - { - assert(CheckInvariants()); - - if (firstNode_ == NIL) - { - for (size_t i = 0; i < nodes_.size(); i++) - { - assert(nodes_[i].dequeued_); - } - - return false; - } - else - { - assert(firstNode_ >= 0 && firstNode_ < static_cast<int>(nodes_.size())); - value = firstNode_; - - Node& node = nodes_[firstNode_]; - assert(node.prev_ == NIL); - assert(!node.dequeued_); - - node.dequeued_ = true; - firstNode_ = node.next_; - - if (firstNode_ != NIL) - { - nodes_[firstNode_].prev_ = NIL; - } - - return true; - } - } - - - void DownloadStack::SetTopNodeInternal(unsigned int value) - { - assert(CheckInvariants()); - - Node& node = nodes_[value]; - - if (node.dequeued_) - { - // This node has already been processed by the download thread, nothing to do - return; - } - - // Remove the node from the list - if (node.prev_ == NIL) - { - assert(firstNode_ == static_cast<int>(value)); - - // This is already the top node in the list, nothing to do - return; - } - - nodes_[node.prev_].next_ = node.next_; - - if (node.next_ != NIL) - { - nodes_[node.next_].prev_ = node.prev_; - } - - // Add back the node at the top of the list - assert(firstNode_ != NIL); - - Node& old = nodes_[firstNode_]; - assert(old.prev_ == NIL); - assert(!old.dequeued_); - node.prev_ = NIL; - node.next_ = firstNode_; - old.prev_ = value; - - firstNode_ = value; - } - - - void DownloadStack::SetTopNode(unsigned int value) - { - if (value >= nodes_.size()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - SetTopNodeInternal(value); - } - - - void DownloadStack::SetTopNodePermissive(int value) - { - if (value >= 0 && - value < static_cast<int>(nodes_.size())) - { - SetTopNodeInternal(value); - } - } -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/DownloadStack.h Thu Sep 17 15:39:33 2020 +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-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include <vector> -#include <boost/noncopyable.hpp> - -namespace Deprecated -{ - class DownloadStack : public boost::noncopyable - { - private: - static const int NIL = -1; - - // This is a doubly-linked list - struct Node - { - int next_; - int prev_; - bool dequeued_; - }; - - std::vector<Node> nodes_; - int firstNode_; - - bool CheckInvariants() const; - - void SetTopNodeInternal(unsigned int value); - - public: - DownloadStack(unsigned int size); - - ~DownloadStack(); - - bool Pop(unsigned int& value); - - void SetTopNode(unsigned int value); - - void SetTopNodePermissive(int value); - }; -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/IDelayedCallExecutor.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "IWebService.h" -#include "../../Messages/IObserver.h" -#include "../../Messages/ICallable.h" - -#include <IDynamicObject.h> -#include <Logging.h> - -#include <string> -#include <map> - -namespace Deprecated -{ - // The IDelayedCall executes a callback after a delay (equivalent to timeout() function in javascript). - class IDelayedCallExecutor : public boost::noncopyable - { - public: - ORTHANC_STONE_DEFINE_EMPTY_MESSAGE(__FILE__, __LINE__, TimeoutMessage); - - virtual ~IDelayedCallExecutor() - { - } - - virtual void Schedule(MessageHandler<IDelayedCallExecutor::TimeoutMessage>* callback, - unsigned int timeoutInMs = 1000) = 0; - }; -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/ISeriesLoader.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "ParallelSlices.h" - -#include <Images/ImageAccessor.h> -#include <IDicomDataset.h> - -namespace Deprecated -{ - class ISeriesLoader : public boost::noncopyable - { - public: - virtual ~ISeriesLoader() - { - } - - virtual ParallelSlices& GetGeometry() = 0; - - virtual Orthanc::PixelFormat GetPixelFormat() = 0; - - virtual unsigned int GetWidth() = 0; - - virtual unsigned int GetHeight() = 0; - - virtual OrthancPlugins::IDicomDataset* DownloadDicom(size_t index) = 0; - - // This downloads the frame from Orthanc. The resulting pixel - // format must be Grayscale8, Grayscale16, SignedGrayscale16 or - // RGB24. Orthanc Stone assumes the conversion of the photometric - // interpretation is done by Orthanc. - virtual Orthanc::ImageAccessor* DownloadFrame(size_t index) = 0; - - virtual Orthanc::ImageAccessor* DownloadJpegFrame(size_t index, - unsigned int quality) = 0; - - virtual bool IsJpegAvailable() = 0; - }; -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/IWebService.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "IWebService.h" - -#include <OrthancException.h> - - -namespace Deprecated -{ - const Orthanc::IDynamicObject& - IWebService::HttpRequestSuccessMessage::GetPayload() const - { - if (HasPayload()) - { - return *payload_; - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - } - - - const Orthanc::IDynamicObject& - IWebService::HttpRequestErrorMessage::GetPayload() const - { - if (HasPayload()) - { - return *payload_; - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - } -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/IWebService.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,213 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../Messages/IObserver.h" -#include "../../Messages/ICallable.h" - -#include <Enumerations.h> -#include <IDynamicObject.h> -#include <Logging.h> - -#include <string> -#include <map> - -namespace Deprecated -{ - template <typename TMessage> - class MessageHandler : public OrthancStone::ICallable - { - }; - - - template <typename TObserver, - typename TMessage> - class DeprecatedCallable : public MessageHandler<TMessage> - { - private: - typedef void (TObserver::* MemberMethod) (const TMessage&); - - boost::weak_ptr<OrthancStone::IObserver> observer_; - MemberMethod function_; - - public: - DeprecatedCallable(boost::shared_ptr<TObserver> observer, - MemberMethod function) : - observer_(observer), - function_(function) - { - } - - virtual void Apply(const OrthancStone::IMessage& message) - { - boost::shared_ptr<OrthancStone::IObserver> lock(observer_); - if (lock) - { - TObserver& observer = dynamic_cast<TObserver&>(*lock); - const TMessage& typedMessage = dynamic_cast<const TMessage&>(message); - (observer.*function_) (typedMessage); - } - } - - virtual const OrthancStone::MessageIdentifier& GetMessageIdentifier() - { - return TMessage::GetStaticIdentifier(); - } - - virtual boost::weak_ptr<OrthancStone::IObserver> GetObserver() const - { - return observer_; - } - }; - - - // The IWebService performs HTTP requests. - // Since applications can run in native or WASM environment and, since - // in a WASM environment, the WebService is asynchronous, the IWebservice - // also implements an asynchronous interface: you must schedule a request - // and you'll be notified when the response/error is ready. - class IWebService : public boost::noncopyable - { - public: - typedef std::map<std::string, std::string> HttpHeaders; - - class HttpRequestSuccessMessage : public OrthancStone::IMessage - { - ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); - - private: - const std::string& uri_; - const void* answer_; - size_t answerSize_; - const HttpHeaders& answerHeaders_; - const Orthanc::IDynamicObject* payload_; - - public: - HttpRequestSuccessMessage(const std::string& uri, - const void* answer, - size_t answerSize, - const HttpHeaders& answerHeaders, - const Orthanc::IDynamicObject* payload) : - uri_(uri), - answer_(answer), - answerSize_(answerSize), - answerHeaders_(answerHeaders), - payload_(payload) - { - } - - const std::string& GetUri() const - { - return uri_; - } - - const void* GetAnswer() const - { - return answer_; - } - - size_t GetAnswerSize() const - { - return answerSize_; - } - - const HttpHeaders& GetAnswerHttpHeaders() const - { - return answerHeaders_; - } - - bool HasPayload() const - { - return payload_ != NULL; - } - - const Orthanc::IDynamicObject& GetPayload() const; - }; - - - class HttpRequestErrorMessage : public OrthancStone::IMessage - { - ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); - - private: - const std::string& uri_; - const Orthanc::IDynamicObject* payload_; - Orthanc::HttpStatus httpStatus_; - - public: - HttpRequestErrorMessage(const std::string& uri, - Orthanc::HttpStatus httpStatus, - const Orthanc::IDynamicObject* payload) : - uri_(uri), - payload_(payload), - httpStatus_(httpStatus) - { - } - - const std::string& GetUri() const - { - return uri_; - } - - Orthanc::HttpStatus GetHttpStatus() const - { - return httpStatus_; - } - - bool HasPayload() const - { - return payload_ != NULL; - } - - const Orthanc::IDynamicObject& GetPayload() const; - }; - - - virtual ~IWebService() - { - } - - virtual void EnableCache(bool enable) = 0; - - virtual void GetAsync(const std::string& uri, - const HttpHeaders& headers, - Orthanc::IDynamicObject* payload /* takes ownership */, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, - unsigned int timeoutInSeconds = 60) = 0; - - virtual void PostAsync(const std::string& uri, - const HttpHeaders& headers, - const std::string& body, - Orthanc::IDynamicObject* payload /* takes ownership */, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, - unsigned int timeoutInSeconds = 60) = 0; - - virtual void DeleteAsync(const std::string& uri, - const HttpHeaders& headers, - Orthanc::IDynamicObject* payload /* takes ownership */, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, - unsigned int timeoutInSeconds = 60) = 0; - }; -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/MessagingToolbox.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,462 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#include "MessagingToolbox.h" - -#include <Images/Image.h> -#include <Images/ImageProcessing.h> -#include <Images/JpegReader.h> -#include <Images/PngReader.h> -#include <OrthancException.h> -#include <Toolbox.h> -#include <Logging.h> - -#include <boost/lexical_cast.hpp> - -#ifdef _MSC_VER -// 'Json::Reader': Use CharReader and CharReaderBuilder instead -#pragma warning(disable:4996) -#endif - -#include <json/reader.h> -#include <json/writer.h> - - -namespace Deprecated -{ - namespace MessagingToolbox - { - static bool ParseVersion(std::string& version, - unsigned int& major, - unsigned int& minor, - unsigned int& patch, - const Json::Value& info) - { - if (info.type() != Json::objectValue || - !info.isMember("Version") || - info["Version"].type() != Json::stringValue) - { - return false; - } - - version = info["Version"].asString(); - if (version == "mainline") - { - // Some arbitrary high values Orthanc versions will never reach ;) - major = 999; - minor = 999; - patch = 999; - return true; - } - - std::vector<std::string> tokens; - Orthanc::Toolbox::TokenizeString(tokens, version, '.'); - - if (tokens.size() != 2 && - tokens.size() != 3) - { - return false; - } - - int a, b, c; - try - { - a = boost::lexical_cast<int>(tokens[0]); - b = boost::lexical_cast<int>(tokens[1]); - - if (tokens.size() == 3) - { - c = boost::lexical_cast<int>(tokens[2]); - } - else - { - c = 0; - } - } - catch (boost::bad_lexical_cast&) - { - return false; - } - - if (a < 0 || - b < 0 || - c < 0) - { - return false; - } - else - { - major = static_cast<unsigned int>(a); - minor = static_cast<unsigned int>(b); - patch = static_cast<unsigned int>(c); - return true; - } - } - - - bool ParseJson(Json::Value& target, - const void* content, - size_t size) - { - Json::Reader reader; - return reader.parse(reinterpret_cast<const char*>(content), - reinterpret_cast<const char*>(content) + size, - target); - } - - void JsonToString(std::string& target, - const Json::Value& source) - { - Json::FastWriter writer; - target = writer.write(source); - } - - static void ParseJsonException(Json::Value& target, - const std::string& source) - { - Json::Reader reader; - if (!reader.parse(source, target)) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); - } - } - - - void RestApiGet(Json::Value& target, - OrthancPlugins::IOrthancConnection& orthanc, - const std::string& uri) - { - std::string tmp; - orthanc.RestApiGet(tmp, uri); - ParseJsonException(target, tmp); - } - - - void RestApiPost(Json::Value& target, - OrthancPlugins::IOrthancConnection& orthanc, - const std::string& uri, - const std::string& body) - { - std::string tmp; - orthanc.RestApiPost(tmp, uri, body); - ParseJsonException(target, tmp); - } - - - bool HasWebViewerInstalled(OrthancPlugins::IOrthancConnection& orthanc) - { - try - { - Json::Value json; - RestApiGet(json, orthanc, "/plugins/web-viewer"); - return json.type() == Json::objectValue; - } - catch (Orthanc::OrthancException&) - { - return false; - } - } - - - bool CheckOrthancVersion(OrthancPlugins::IOrthancConnection& orthanc) - { - Json::Value json; - std::string version; - unsigned int major, minor, patch; - - try - { - RestApiGet(json, orthanc, "/system"); - } - catch (Orthanc::OrthancException&) - { - LOG(ERROR) << "Cannot connect to your Orthanc server"; - throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol); - } - - if (!ParseVersion(version, major, minor, patch, json)) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol); - } - - LOG(WARNING) << "Version of the Orthanc core (must be above 1.3.1): " << version; - - // Stone is only compatible with Orthanc >= 1.3.1 - if (major < 1 || - (major == 1 && minor < 3) || - (major == 1 && minor == 3 && patch < 1)) - { - return false; - } - - try - { - RestApiGet(json, orthanc, "/plugins/web-viewer"); - } - catch (Orthanc::OrthancException&) - { - // The Web viewer is not installed, this is OK - LOG(WARNING) << "The Web viewer plugin is not installed, progressive download is disabled"; - return true; - } - - if (!ParseVersion(version, major, minor, patch, json)) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol); - } - - LOG(WARNING) << "Version of the Web viewer plugin (must be above 2.2): " << version; - - return (major >= 3 || - (major == 2 && minor >= 2)); - } - - - Orthanc::ImageAccessor* DecodeFrame(OrthancPlugins::IOrthancConnection& orthanc, - const std::string& instance, - unsigned int frame, - Orthanc::PixelFormat targetFormat) - { - std::string uri = ("instances/" + instance + "/frames/" + - boost::lexical_cast<std::string>(frame)); - - std::string compressed; - - switch (targetFormat) - { - case Orthanc::PixelFormat_RGB24: - orthanc.RestApiGet(compressed, uri + "/preview"); - break; - - case Orthanc::PixelFormat_Grayscale16: - orthanc.RestApiGet(compressed, uri + "/image-uint16"); - break; - - case Orthanc::PixelFormat_SignedGrayscale16: - orthanc.RestApiGet(compressed, uri + "/image-int16"); - break; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - std::unique_ptr<Orthanc::PngReader> result(new Orthanc::PngReader); - result->ReadFromMemory(compressed); - - if (targetFormat == Orthanc::PixelFormat_SignedGrayscale16) - { - if (result->GetFormat() == Orthanc::PixelFormat_Grayscale16) - { - result->SetFormat(Orthanc::PixelFormat_SignedGrayscale16); - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol); - } - } - - return result.release(); - } - - - Orthanc::ImageAccessor* DecodeJpegFrame(OrthancPlugins::IOrthancConnection& orthanc, - const std::string& instance, - unsigned int frame, - unsigned int quality, - Orthanc::PixelFormat targetFormat) - { - if (quality <= 0 || - quality > 100) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - // This requires the official Web viewer plugin to be installed! - std::string uri = ("web-viewer/instances/jpeg" + - boost::lexical_cast<std::string>(quality) + - "-" + instance + "_" + - boost::lexical_cast<std::string>(frame)); - - Json::Value encoded; - RestApiGet(encoded, orthanc, uri); - - if (encoded.type() != Json::objectValue || - !encoded.isMember("Orthanc") || - encoded["Orthanc"].type() != Json::objectValue) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol); - } - - Json::Value& info = encoded["Orthanc"]; - if (!info.isMember("PixelData") || - !info.isMember("Stretched") || - !info.isMember("Compression") || - info["Compression"].type() != Json::stringValue || - info["PixelData"].type() != Json::stringValue || - info["Stretched"].type() != Json::booleanValue || - info["Compression"].asString() != "Jpeg") - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol); - } - - bool isSigned = false; - bool isStretched = info["Stretched"].asBool(); - - if (info.isMember("IsSigned")) - { - if (info["IsSigned"].type() != Json::booleanValue) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol); - } - else - { - isSigned = info["IsSigned"].asBool(); - } - } - - std::string jpeg; - Orthanc::Toolbox::DecodeBase64(jpeg, info["PixelData"].asString()); - - std::unique_ptr<Orthanc::JpegReader> reader(new Orthanc::JpegReader); - reader->ReadFromMemory(jpeg); - - if (reader->GetFormat() == Orthanc::PixelFormat_RGB24) // This is a color image - { - if (targetFormat != Orthanc::PixelFormat_RGB24) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol); - } - - if (isSigned || isStretched) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); - } - else - { - return reader.release(); - } - } - - if (reader->GetFormat() != Orthanc::PixelFormat_Grayscale8) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); - } - - if (!isStretched) - { - if (targetFormat != reader->GetFormat()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol); - } - - return reader.release(); - } - - int32_t stretchLow = 0; - int32_t stretchHigh = 0; - - if (!info.isMember("StretchLow") || - !info.isMember("StretchHigh") || - info["StretchLow"].type() != Json::intValue || - info["StretchHigh"].type() != Json::intValue) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol); - } - - stretchLow = info["StretchLow"].asInt(); - stretchHigh = info["StretchHigh"].asInt(); - - if (stretchLow < -32768 || - stretchHigh > 65535 || - (stretchLow < 0 && stretchHigh > 32767)) - { - // This range cannot be represented with a uint16_t or an int16_t - throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); - } - - // Decode a grayscale JPEG 8bpp image coming from the Web viewer - std::unique_ptr<Orthanc::ImageAccessor> image - (new Orthanc::Image(targetFormat, reader->GetWidth(), reader->GetHeight(), false)); - - float scaling = static_cast<float>(stretchHigh - stretchLow) / 255.0f; - float offset = static_cast<float>(stretchLow) / scaling; - - Orthanc::ImageProcessing::Convert(*image, *reader); - Orthanc::ImageProcessing::ShiftScale(*image, offset, scaling, true); - -#if 0 - /*info.removeMember("PixelData"); - std::cout << info.toStyledString();*/ - - int64_t a, b; - Orthanc::ImageProcessing::GetMinMaxValue(a, b, *image); - std::cout << stretchLow << "->" << stretchHigh << " = " << a << "->" << b << std::endl; -#endif - - return image.release(); - } - - - static void AddTag(Orthanc::DicomMap& target, - const OrthancPlugins::IDicomDataset& source, - const Orthanc::DicomTag& tag) - { - OrthancPlugins::DicomTag key(tag.GetGroup(), tag.GetElement()); - - std::string value; - if (source.GetStringValue(value, key)) - { - target.SetValue(tag, value, false); - } - } - - - void ConvertDataset(Orthanc::DicomMap& target, - const OrthancPlugins::IDicomDataset& source) - { - target.Clear(); - - AddTag(target, source, Orthanc::DICOM_TAG_BITS_ALLOCATED); - AddTag(target, source, Orthanc::DICOM_TAG_BITS_STORED); - AddTag(target, source, Orthanc::DICOM_TAG_COLUMNS); - AddTag(target, source, Orthanc::DICOM_TAG_DOSE_GRID_SCALING); - AddTag(target, source, Orthanc::DICOM_TAG_FRAME_INCREMENT_POINTER); - AddTag(target, source, Orthanc::DICOM_TAG_GRID_FRAME_OFFSET_VECTOR); - AddTag(target, source, Orthanc::DICOM_TAG_HIGH_BIT); - AddTag(target, source, Orthanc::DICOM_TAG_IMAGE_ORIENTATION_PATIENT); - AddTag(target, source, Orthanc::DICOM_TAG_IMAGE_POSITION_PATIENT); - AddTag(target, source, Orthanc::DICOM_TAG_NUMBER_OF_FRAMES); - AddTag(target, source, Orthanc::DICOM_TAG_PHOTOMETRIC_INTERPRETATION); - AddTag(target, source, Orthanc::DICOM_TAG_PIXEL_REPRESENTATION); - AddTag(target, source, Orthanc::DICOM_TAG_PIXEL_SPACING); - AddTag(target, source, Orthanc::DICOM_TAG_PLANAR_CONFIGURATION); - AddTag(target, source, Orthanc::DICOM_TAG_RESCALE_INTERCEPT); - AddTag(target, source, Orthanc::DICOM_TAG_RESCALE_SLOPE); - AddTag(target, source, Orthanc::DICOM_TAG_ROWS); - AddTag(target, source, Orthanc::DICOM_TAG_SAMPLES_PER_PIXEL); - AddTag(target, source, Orthanc::DICOM_TAG_SERIES_INSTANCE_UID); - AddTag(target, source, Orthanc::DICOM_TAG_SLICE_THICKNESS); - AddTag(target, source, Orthanc::DICOM_TAG_SOP_CLASS_UID); - AddTag(target, source, Orthanc::DICOM_TAG_SOP_INSTANCE_UID); - AddTag(target, source, Orthanc::DICOM_TAG_WINDOW_CENTER); - AddTag(target, source, Orthanc::DICOM_TAG_WINDOW_WIDTH); - } - } -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/MessagingToolbox.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../StoneEnumerations.h" - -#include <DicomFormat/DicomMap.h> -#include <Images/ImageAccessor.h> -#include <IDicomDataset.h> -#include <IOrthancConnection.h> - -#include <json/value.h> - -namespace Deprecated -{ - namespace MessagingToolbox - { - bool ParseJson(Json::Value& target, - const void* content, - size_t size); - - void JsonToString(std::string& target, - const Json::Value& source); - - - void RestApiGet(Json::Value& target, - OrthancPlugins::IOrthancConnection& orthanc, - const std::string& uri); - - void RestApiPost(Json::Value& target, - OrthancPlugins::IOrthancConnection& orthanc, - const std::string& uri, - const std::string& body); - - bool HasWebViewerInstalled(OrthancPlugins::IOrthancConnection& orthanc); - - bool CheckOrthancVersion(OrthancPlugins::IOrthancConnection& orthanc); - - // This downloads the image from Orthanc and keeps its pixel - // format unchanged (will be either Grayscale8, Grayscale16, - // SignedGrayscale16, or RGB24) - Orthanc::ImageAccessor* DecodeFrame(OrthancPlugins::IOrthancConnection& orthanc, - const std::string& instance, - unsigned int frame, - Orthanc::PixelFormat targetFormat); - - Orthanc::ImageAccessor* DecodeJpegFrame(OrthancPlugins::IOrthancConnection& orthanc, - const std::string& instance, - unsigned int frame, - unsigned int quality, - Orthanc::PixelFormat targetFormat); - - void ConvertDataset(Orthanc::DicomMap& target, - const OrthancPlugins::IDicomDataset& source); - } -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/OrthancApiClient.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,334 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - -#include "OrthancApiClient.h" - -#include "../Toolbox/MessagingToolbox.h" - -#include <OrthancException.h> - -namespace Deprecated -{ - const Orthanc::IDynamicObject& OrthancApiClient::JsonResponseReadyMessage::GetPayload() const - { - if (HasPayload()) - { - return *payload_; - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - } - - - const Orthanc::IDynamicObject& OrthancApiClient::BinaryResponseReadyMessage::GetPayload() const - { - if (HasPayload()) - { - return *payload_; - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - } - - - const Orthanc::IDynamicObject& OrthancApiClient::EmptyResponseReadyMessage::GetPayload() const - { - if (HasPayload()) - { - return *payload_; - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - } - - - class OrthancApiClient::WebServicePayload : public Orthanc::IDynamicObject - { - private: - std::unique_ptr< MessageHandler<EmptyResponseReadyMessage> > emptyHandler_; - std::unique_ptr< MessageHandler<JsonResponseReadyMessage> > jsonHandler_; - std::unique_ptr< MessageHandler<BinaryResponseReadyMessage> > binaryHandler_; - std::unique_ptr< MessageHandler<IWebService::HttpRequestErrorMessage> > failureHandler_; - std::unique_ptr< Orthanc::IDynamicObject > userPayload_; - - void NotifyConversionError(const IWebService::HttpRequestSuccessMessage& message) const - { - if (failureHandler_.get() != NULL) - { - failureHandler_->Apply(IWebService::HttpRequestErrorMessage - (message.GetUri(), Orthanc::HttpStatus_None, userPayload_.get())); - } - } - - public: - WebServicePayload(MessageHandler<EmptyResponseReadyMessage>* handler, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureHandler, - Orthanc::IDynamicObject* userPayload) : - emptyHandler_(handler), - failureHandler_(failureHandler), - userPayload_(userPayload) - - { - if (handler == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); - } - } - - WebServicePayload(MessageHandler<BinaryResponseReadyMessage>* handler, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureHandler, - Orthanc::IDynamicObject* userPayload) : - binaryHandler_(handler), - failureHandler_(failureHandler), - userPayload_(userPayload) - { - if (handler == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); - } - } - - WebServicePayload(MessageHandler<JsonResponseReadyMessage>* handler, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureHandler, - Orthanc::IDynamicObject* userPayload) : - jsonHandler_(handler), - failureHandler_(failureHandler), - userPayload_(userPayload) - { - if (handler == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); - } - } - - void HandleSuccess(const IWebService::HttpRequestSuccessMessage& message) const - { - if (emptyHandler_.get() != NULL) - { - emptyHandler_->Apply(OrthancApiClient::EmptyResponseReadyMessage - (message.GetUri(), userPayload_.get())); - } - else if (binaryHandler_.get() != NULL) - { - binaryHandler_->Apply(OrthancApiClient::BinaryResponseReadyMessage - (message.GetUri(), message.GetAnswer(), - message.GetAnswerSize(), userPayload_.get())); - } - else if (jsonHandler_.get() != NULL) - { - Json::Value response; - if (MessagingToolbox::ParseJson(response, message.GetAnswer(), message.GetAnswerSize())) - { - jsonHandler_->Apply(OrthancApiClient::JsonResponseReadyMessage - (message.GetUri(), response, userPayload_.get())); - } - else - { - NotifyConversionError(message); - } - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - } - - void HandleFailure(const IWebService::HttpRequestErrorMessage& message) const - { - if (failureHandler_.get() != NULL) - { - failureHandler_->Apply(IWebService::HttpRequestErrorMessage - (message.GetUri(), message.GetHttpStatus(), userPayload_.get())); - } - } - }; - - - OrthancApiClient::OrthancApiClient(IWebService& web, - const std::string& baseUrl) : - web_(web), - baseUrl_(baseUrl) - { - } - - - void OrthancApiClient::GetJsonAsync( - const std::string& uri, - MessageHandler<JsonResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, - Orthanc::IDynamicObject* payload) - { - IWebService::HttpHeaders emptyHeaders; - web_.GetAsync(baseUrl_ + uri, - emptyHeaders, - new WebServicePayload(successCallback, failureCallback, payload), - new DeprecatedCallable<OrthancApiClient, IWebService::HttpRequestSuccessMessage> - (GetSharedObserver(), &OrthancApiClient::NotifyHttpSuccess), - new DeprecatedCallable<OrthancApiClient, IWebService::HttpRequestErrorMessage> - (GetSharedObserver(), &OrthancApiClient::NotifyHttpError)); - } - - - void OrthancApiClient::GetBinaryAsync( - const std::string& uri, - const std::string& contentType, - MessageHandler<BinaryResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, - Orthanc::IDynamicObject* payload) - { - IWebService::HttpHeaders headers; - headers["Accept"] = contentType; - GetBinaryAsync(uri, headers, successCallback, failureCallback, payload); - } - - void OrthancApiClient::GetBinaryAsync( - const std::string& uri, - const IWebService::HttpHeaders& headers, - MessageHandler<BinaryResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, - Orthanc::IDynamicObject* payload) - { - // printf("GET [%s] [%s]\n", baseUrl_.c_str(), uri.c_str()); - - web_.GetAsync(baseUrl_ + uri, headers, - new WebServicePayload(successCallback, failureCallback, payload), - new DeprecatedCallable<OrthancApiClient, IWebService::HttpRequestSuccessMessage> - (GetSharedObserver(), &OrthancApiClient::NotifyHttpSuccess), - new DeprecatedCallable<OrthancApiClient, IWebService::HttpRequestErrorMessage> - (GetSharedObserver(), &OrthancApiClient::NotifyHttpError)); - } - - - void OrthancApiClient::PostBinaryAsyncExpectJson( - const std::string& uri, - const std::string& body, - MessageHandler<JsonResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, - Orthanc::IDynamicObject* payload) - { - web_.PostAsync(baseUrl_ + uri, IWebService::HttpHeaders(), body, - new WebServicePayload(successCallback, failureCallback, payload), - new DeprecatedCallable<OrthancApiClient, IWebService::HttpRequestSuccessMessage> - (GetSharedObserver(), &OrthancApiClient::NotifyHttpSuccess), - new DeprecatedCallable<OrthancApiClient, IWebService::HttpRequestErrorMessage> - (GetSharedObserver(), &OrthancApiClient::NotifyHttpError)); - - } - - void OrthancApiClient::PostBinaryAsync( - const std::string& uri, - const std::string& body) - { - web_.PostAsync(baseUrl_ + uri, IWebService::HttpHeaders(), body, NULL, NULL, NULL); - } - - void OrthancApiClient::PostBinaryAsync( - const std::string& uri, - const std::string& body, - MessageHandler<EmptyResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, - Orthanc::IDynamicObject* payload /* takes ownership */) - { - web_.PostAsync(baseUrl_ + uri, IWebService::HttpHeaders(), body, - new WebServicePayload(successCallback, failureCallback, payload), - new DeprecatedCallable<OrthancApiClient, IWebService::HttpRequestSuccessMessage> - (GetSharedObserver(), &OrthancApiClient::NotifyHttpSuccess), - new DeprecatedCallable<OrthancApiClient, IWebService::HttpRequestErrorMessage> - (GetSharedObserver(), &OrthancApiClient::NotifyHttpError)); - } - - void OrthancApiClient::PostJsonAsyncExpectJson( - const std::string& uri, - const Json::Value& data, - MessageHandler<JsonResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, - Orthanc::IDynamicObject* payload) - { - std::string body; - MessagingToolbox::JsonToString(body, data); - return PostBinaryAsyncExpectJson(uri, body, successCallback, failureCallback, payload); - } - - void OrthancApiClient::PostJsonAsync( - const std::string& uri, - const Json::Value& data) - { - std::string body; - MessagingToolbox::JsonToString(body, data); - return PostBinaryAsync(uri, body); - } - - void OrthancApiClient::PostJsonAsync( - const std::string& uri, - const Json::Value& data, - MessageHandler<EmptyResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, - Orthanc::IDynamicObject* payload /* takes ownership */) - { - std::string body; - MessagingToolbox::JsonToString(body, data); - return PostBinaryAsync(uri, body, successCallback, failureCallback, payload); - } - - void OrthancApiClient::DeleteAsync( - const std::string& uri, - MessageHandler<EmptyResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, - Orthanc::IDynamicObject* payload) - { - web_.DeleteAsync(baseUrl_ + uri, IWebService::HttpHeaders(), - new WebServicePayload(successCallback, failureCallback, payload), - new DeprecatedCallable<OrthancApiClient, IWebService::HttpRequestSuccessMessage> - (GetSharedObserver(), &OrthancApiClient::NotifyHttpSuccess), - new DeprecatedCallable<OrthancApiClient, IWebService::HttpRequestErrorMessage> - (GetSharedObserver(), &OrthancApiClient::NotifyHttpError)); - } - - - void OrthancApiClient::NotifyHttpSuccess(const IWebService::HttpRequestSuccessMessage& message) - { - if (message.HasPayload()) - { - dynamic_cast<const WebServicePayload&>(message.GetPayload()).HandleSuccess(message); - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - } - - void OrthancApiClient::NotifyHttpError(const IWebService::HttpRequestErrorMessage& message) - { - if (message.HasPayload()) - { - dynamic_cast<const WebServicePayload&>(message.GetPayload()).HandleFailure(message); - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - } -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/OrthancApiClient.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,252 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include <boost/shared_ptr.hpp> -#include <json/json.h> - -#include "IWebService.h" -#include "../../Messages/ObserverBase.h" - -namespace Deprecated -{ - enum SliceImageQuality - { - SliceImageQuality_FullPng, // smaller to transmit but longer to generate on Orthanc side (better choice when on low bandwidth) - SliceImageQuality_FullPam, // bigger to transmit but faster to generate on Orthanc side (better choice when on localhost or LAN) - SliceImageQuality_Jpeg50, - SliceImageQuality_Jpeg90, - SliceImageQuality_Jpeg95, - - SliceImageQuality_InternalRaw // downloads the raw pixels data as they are stored in the DICOM file (internal use only) - }; - - class OrthancApiClient : - public OrthancStone::IObservable, - public OrthancStone::ObserverBase<OrthancApiClient> - { - public: - class JsonResponseReadyMessage : public OrthancStone::IMessage - { - ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); - - private: - const std::string& uri_; - const Json::Value& json_; - const Orthanc::IDynamicObject* payload_; - - public: - JsonResponseReadyMessage(const std::string& uri, - const Json::Value& json, - const Orthanc::IDynamicObject* payload) : - uri_(uri), - json_(json), - payload_(payload) - { - } - - const std::string& GetUri() const - { - return uri_; - } - - const Json::Value& GetJson() const - { - return json_; - } - - bool HasPayload() const - { - return payload_ != NULL; - } - - const Orthanc::IDynamicObject& GetPayload() const; - }; - - - class BinaryResponseReadyMessage : public OrthancStone::IMessage - { - ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); - - private: - const std::string& uri_; - const void* answer_; - size_t answerSize_; - const Orthanc::IDynamicObject* payload_; - - public: - BinaryResponseReadyMessage(const std::string& uri, - const void* answer, - size_t answerSize, - const Orthanc::IDynamicObject* payload) : - uri_(uri), - answer_(answer), - answerSize_(answerSize), - payload_(payload) - { - } - - const std::string& GetUri() const - { - return uri_; - } - - const void* GetAnswer() const - { - return answer_; - } - - size_t GetAnswerSize() const - { - return answerSize_; - } - - bool HasPayload() const - { - return payload_ != NULL; - } - - const Orthanc::IDynamicObject& GetPayload() const; - }; - - - class EmptyResponseReadyMessage : public OrthancStone::IMessage - { - ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); - - private: - const std::string& uri_; - const Orthanc::IDynamicObject* payload_; - - public: - EmptyResponseReadyMessage(const std::string& uri, - const Orthanc::IDynamicObject* payload) : - uri_(uri), - payload_(payload) - { - } - - const std::string& GetUri() const - { - return uri_; - } - - bool HasPayload() const - { - return payload_ != NULL; - } - - const Orthanc::IDynamicObject& GetPayload() const; - }; - - - - private: - class WebServicePayload; - - protected: - IWebService& web_; - std::string baseUrl_; - - public: - OrthancApiClient(IWebService& web, - const std::string& baseUrl); - - virtual ~OrthancApiClient() - { - } - - const std::string& GetBaseUrl() const {return baseUrl_;} - - // schedule a GET request expecting a JSON response. - void GetJsonAsync(const std::string& uri, - MessageHandler<JsonResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, - Orthanc::IDynamicObject* payload = NULL /* takes ownership */); - - // schedule a GET request expecting a binary response. - void GetBinaryAsync(const std::string& uri, - const std::string& contentType, - MessageHandler<BinaryResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, - Orthanc::IDynamicObject* payload = NULL /* takes ownership */); - - // schedule a GET request expecting a binary response. - void GetBinaryAsync(const std::string& uri, - const IWebService::HttpHeaders& headers, - MessageHandler<BinaryResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, - Orthanc::IDynamicObject* payload = NULL /* takes ownership */); - - // schedule a POST request expecting a JSON response. - void PostBinaryAsyncExpectJson(const std::string& uri, - const std::string& body, - MessageHandler<JsonResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, - Orthanc::IDynamicObject* payload = NULL /* takes ownership */); - - // schedule a POST request expecting a JSON response. - void PostJsonAsyncExpectJson(const std::string& uri, - const Json::Value& data, - MessageHandler<JsonResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, - Orthanc::IDynamicObject* payload = NULL /* takes ownership */); - - // schedule a POST request and don't mind the response. - void PostJsonAsync(const std::string& uri, - const Json::Value& data); - - // schedule a POST request and don't expect any response. - void PostJsonAsync(const std::string& uri, - const Json::Value& data, - MessageHandler<EmptyResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, - Orthanc::IDynamicObject* payload = NULL /* takes ownership */); - - - // schedule a POST request and don't mind the response. - void PostBinaryAsync(const std::string& uri, - const std::string& body); - - // schedule a POST request and don't expect any response. - void PostBinaryAsync(const std::string& uri, - const std::string& body, - MessageHandler<EmptyResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, - Orthanc::IDynamicObject* payload = NULL /* takes ownership */); - - // schedule a DELETE request expecting an empty response. - void DeleteAsync(const std::string& uri, - MessageHandler<EmptyResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, - Orthanc::IDynamicObject* payload = NULL /* takes ownership */); - - void NotifyHttpSuccess(const IWebService::HttpRequestSuccessMessage& message); - - void NotifyHttpError(const IWebService::HttpRequestErrorMessage& message); - - private: - void HandleFromCache(const std::string& uri, - const IWebService::HttpHeaders& headers, - Orthanc::IDynamicObject* payload /* takes ownership */); - }; -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/OrthancSlicesLoader.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,901 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "OrthancSlicesLoader.h" - -#include "../Toolbox/MessagingToolbox.h" - -#include <Compression/GzipCompressor.h> -#include <Endianness.h> -#include <Images/Image.h> -#include <Images/ImageProcessing.h> -#include <Images/JpegReader.h> -#include <Images/PngReader.h> -#include <Images/PamReader.h> -#include <Logging.h> -#include <OrthancException.h> -#include <Toolbox.h> -#include <FullOrthancDataset.h> - -#include <boost/lexical_cast.hpp> - - - -/** - * TODO This is a SLOW implementation of base64 decoding, because - * "Orthanc::Toolbox::DecodeBase64()" does not work properly with - * WASM. UNDERSTAND WHY. - * https://stackoverflow.com/a/34571089/881731 - **/ -static std::string base64_decode(const std::string &in) -{ - std::string out; - - std::vector<int> T(256,-1); - for (int i=0; i<64; i++) T["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]] = i; - - int val=0, valb=-8; - for (size_t i = 0; i < in.size(); i++) { - unsigned char c = in[i]; - if (T[c] == -1) break; - val = (val<<6) + T[c]; - valb += 6; - if (valb>=0) { - out.push_back(char((val>>valb)&0xFF)); - valb-=8; - } - } - return out; -} - - - -namespace Deprecated -{ - class OrthancSlicesLoader::Operation : public Orthanc::IDynamicObject - { - private: - Mode mode_; - unsigned int frame_; - unsigned int sliceIndex_; - const Slice* slice_; - std::string instanceId_; - SliceImageQuality quality_; - - Operation(Mode mode) : - mode_(mode) - { - } - - public: - Mode GetMode() const - { - return mode_; - } - - SliceImageQuality GetQuality() const - { - assert(mode_ == Mode_LoadImage || - mode_ == Mode_LoadRawImage); - return quality_; - } - - unsigned int GetSliceIndex() const - { - assert(mode_ == Mode_LoadImage || - mode_ == Mode_LoadRawImage); - return sliceIndex_; - } - - const Slice& GetSlice() const - { - assert(mode_ == Mode_LoadImage || - mode_ == Mode_LoadRawImage); - assert(slice_ != NULL); - return *slice_; - } - - unsigned int GetFrame() const - { - assert(mode_ == Mode_FrameGeometry); - return frame_; - } - - const std::string& GetInstanceId() const - { - assert(mode_ == Mode_FrameGeometry || - mode_ == Mode_InstanceGeometry); - return instanceId_; - } - - static Operation* DownloadInstanceGeometry(const std::string& instanceId) - { - std::unique_ptr<Operation> operation(new Operation(Mode_InstanceGeometry)); - operation->instanceId_ = instanceId; - return operation.release(); - } - - static Operation* DownloadFrameGeometry(const std::string& instanceId, - unsigned int frame) - { - std::unique_ptr<Operation> operation(new Operation(Mode_FrameGeometry)); - operation->instanceId_ = instanceId; - operation->frame_ = frame; - return operation.release(); - } - - static Operation* DownloadSliceImage(unsigned int sliceIndex, - const Slice& slice, - SliceImageQuality quality) - { - std::unique_ptr<Operation> tmp(new Operation(Mode_LoadImage)); - tmp->sliceIndex_ = sliceIndex; - tmp->slice_ = &slice; - tmp->quality_ = quality; - return tmp.release(); - } - - static Operation* DownloadSliceRawImage(unsigned int sliceIndex, - const Slice& slice) - { - std::unique_ptr<Operation> tmp(new Operation(Mode_LoadRawImage)); - tmp->sliceIndex_ = sliceIndex; - tmp->slice_ = &slice; - tmp->quality_ = SliceImageQuality_InternalRaw; - return tmp.release(); - } - - static Operation* DownloadDicomFile(const Slice& slice) - { - std::unique_ptr<Operation> tmp(new Operation(Mode_LoadDicomFile)); - tmp->slice_ = &slice; - return tmp.release(); - } - - }; - - void OrthancSlicesLoader::NotifySliceImageSuccess(const Operation& operation, - const Orthanc::ImageAccessor& image) - { - OrthancSlicesLoader::SliceImageReadyMessage msg - (*this, operation.GetSliceIndex(), operation.GetSlice(), image, operation.GetQuality()); - BroadcastMessage(msg); - } - - - void OrthancSlicesLoader::NotifySliceImageError(const Operation& operation) - { - OrthancSlicesLoader::SliceImageErrorMessage msg - (*this, operation.GetSliceIndex(), operation.GetSlice(), operation.GetQuality()); - BroadcastMessage(msg); - } - - - void OrthancSlicesLoader::SortAndFinalizeSlices() - { - bool ok = slices_.Sort(); - - state_ = State_GeometryReady; - - if (ok) - { - LOG(INFO) << "Loaded a series with " << slices_.GetSlicesCount() << " slice(s)"; - BroadcastMessage(SliceGeometryReadyMessage(*this)); - } - else - { - LOG(ERROR) << "This series is empty"; - BroadcastMessage(SliceGeometryErrorMessage(*this)); - } - } - - void OrthancSlicesLoader::OnGeometryError(const IWebService::HttpRequestErrorMessage& message) - { - BroadcastMessage(SliceGeometryErrorMessage(*this)); - state_ = State_Error; - } - - void OrthancSlicesLoader::OnSliceImageError(const IWebService::HttpRequestErrorMessage& message) - { - NotifySliceImageError(dynamic_cast<const Operation&>(message.GetPayload())); - state_ = State_Error; - } - - void OrthancSlicesLoader::ParseSeriesGeometry(const OrthancApiClient::JsonResponseReadyMessage& message) - { - const Json::Value& series = message.GetJson(); - Json::Value::Members instances = series.getMemberNames(); - - slices_.Reserve(instances.size()); - - for (size_t i = 0; i < instances.size(); i++) - { - OrthancPlugins::FullOrthancDataset dataset(series[instances[i]]); - - Orthanc::DicomMap dicom; - MessagingToolbox::ConvertDataset(dicom, dataset); - - unsigned int frames; - if (!dicom.ParseUnsignedInteger32(frames, Orthanc::DICOM_TAG_NUMBER_OF_FRAMES)) - { - frames = 1; - } - - for (unsigned int frame = 0; frame < frames; frame++) - { - std::unique_ptr<Slice> slice(new Slice); - if (slice->ParseOrthancFrame(dicom, instances[i], frame)) - { - OrthancStone::CoordinateSystem3D geometry = slice->GetGeometry(); - slices_.AddSlice(geometry, slice.release()); - } - else - { - LOG(WARNING) << "Skipping invalid frame " << frame << " within instance " << instances[i]; - } - } - } - - SortAndFinalizeSlices(); - } - - void OrthancSlicesLoader::ParseInstanceGeometry(const OrthancApiClient::JsonResponseReadyMessage& message) - { - const Json::Value& tags = message.GetJson(); - const std::string& instanceId = dynamic_cast<const OrthancSlicesLoader::Operation&>(message.GetPayload()).GetInstanceId(); - - OrthancPlugins::FullOrthancDataset dataset(tags); - - Orthanc::DicomMap dicom; - MessagingToolbox::ConvertDataset(dicom, dataset); - - unsigned int frames; - if (!dicom.ParseUnsignedInteger32(frames, Orthanc::DICOM_TAG_NUMBER_OF_FRAMES)) - { - frames = 1; - } - - LOG(INFO) << "Instance " << instanceId << " contains " << frames << " frame(s)"; - - for (unsigned int frame = 0; frame < frames; frame++) - { - std::unique_ptr<Slice> slice(new Slice); - if (slice->ParseOrthancFrame(dicom, instanceId, frame)) - { - OrthancStone::CoordinateSystem3D geometry = slice->GetGeometry(); - slices_.AddSlice(geometry, slice.release()); - } - else - { - LOG(WARNING) << "Skipping invalid multi-frame instance " << instanceId; - BroadcastMessage(SliceGeometryErrorMessage(*this)); - return; - } - } - - SortAndFinalizeSlices(); - } - - - void OrthancSlicesLoader::ParseFrameGeometry(const OrthancApiClient::JsonResponseReadyMessage& message) - { - const Json::Value& tags = message.GetJson(); - const std::string& instanceId = dynamic_cast<const OrthancSlicesLoader::Operation&>(message.GetPayload()).GetInstanceId(); - unsigned int frame = dynamic_cast<const OrthancSlicesLoader::Operation&>(message.GetPayload()).GetFrame(); - - OrthancPlugins::FullOrthancDataset dataset(tags); - - state_ = State_GeometryReady; - - Orthanc::DicomMap dicom; - MessagingToolbox::ConvertDataset(dicom, dataset); - - std::unique_ptr<Slice> slice(new Slice); - if (slice->ParseOrthancFrame(dicom, instanceId, frame)) - { - LOG(INFO) << "Loaded instance geometry " << instanceId; - - OrthancStone::CoordinateSystem3D geometry = slice->GetGeometry(); - slices_.AddSlice(geometry, slice.release()); - - BroadcastMessage(SliceGeometryReadyMessage(*this)); - } - else - { - LOG(WARNING) << "Skipping invalid instance " << instanceId; - BroadcastMessage(SliceGeometryErrorMessage(*this)); - } - } - - - void OrthancSlicesLoader::ParseSliceImagePng(const OrthancApiClient::BinaryResponseReadyMessage& message) - { - const Operation& operation = dynamic_cast<const OrthancSlicesLoader::Operation&>(message.GetPayload()); - std::unique_ptr<Orthanc::ImageAccessor> image; - - try - { - image.reset(new Orthanc::PngReader); - dynamic_cast<Orthanc::PngReader&>(*image).ReadFromMemory(message.GetAnswer(), message.GetAnswerSize()); - } - catch (Orthanc::OrthancException&) - { - NotifySliceImageError(operation); - return; - } - - if (image->GetWidth() != operation.GetSlice().GetWidth() || - image->GetHeight() != operation.GetSlice().GetHeight()) - { - NotifySliceImageError(operation); - return; - } - - if (operation.GetSlice().GetConverter().GetExpectedPixelFormat() == - Orthanc::PixelFormat_SignedGrayscale16) - { - if (image->GetFormat() == Orthanc::PixelFormat_Grayscale16) - { - image->SetFormat(Orthanc::PixelFormat_SignedGrayscale16); - } - else - { - NotifySliceImageError(operation); - return; - } - } - - NotifySliceImageSuccess(operation, *image); - } - - void OrthancSlicesLoader::ParseSliceImagePam(const OrthancApiClient::BinaryResponseReadyMessage& message) - { - const Operation& operation = dynamic_cast<const OrthancSlicesLoader::Operation&>(message.GetPayload()); - std::unique_ptr<Orthanc::ImageAccessor> image; - - try - { - image.reset(new Orthanc::PamReader); - dynamic_cast<Orthanc::PamReader&>(*image).ReadFromMemory(message.GetAnswer(), message.GetAnswerSize()); - } - catch (Orthanc::OrthancException&) - { - NotifySliceImageError(operation); - return; - } - - if (image->GetWidth() != operation.GetSlice().GetWidth() || - image->GetHeight() != operation.GetSlice().GetHeight()) - { - NotifySliceImageError(operation); - return; - } - - if (operation.GetSlice().GetConverter().GetExpectedPixelFormat() == - Orthanc::PixelFormat_SignedGrayscale16) - { - if (image->GetFormat() == Orthanc::PixelFormat_Grayscale16) - { - image->SetFormat(Orthanc::PixelFormat_SignedGrayscale16); - } - else - { - NotifySliceImageError(operation); - return; - } - } - - NotifySliceImageSuccess(operation, *image); - } - - - void OrthancSlicesLoader::ParseSliceImageJpeg(const OrthancApiClient::JsonResponseReadyMessage& message) - { - const Operation& operation = dynamic_cast<const OrthancSlicesLoader::Operation&>(message.GetPayload()); - - const Json::Value& encoded = message.GetJson(); - if (encoded.type() != Json::objectValue || - !encoded.isMember("Orthanc") || - encoded["Orthanc"].type() != Json::objectValue) - { - NotifySliceImageError(operation); - return; - } - - const Json::Value& info = encoded["Orthanc"]; - if (!info.isMember("PixelData") || - !info.isMember("Stretched") || - !info.isMember("Compression") || - info["Compression"].type() != Json::stringValue || - info["PixelData"].type() != Json::stringValue || - info["Stretched"].type() != Json::booleanValue || - info["Compression"].asString() != "Jpeg") - { - NotifySliceImageError(operation); - return; - } - - bool isSigned = false; - bool isStretched = info["Stretched"].asBool(); - - if (info.isMember("IsSigned")) - { - if (info["IsSigned"].type() != Json::booleanValue) - { - NotifySliceImageError(operation); - return; - } - else - { - isSigned = info["IsSigned"].asBool(); - } - } - - std::unique_ptr<Orthanc::ImageAccessor> reader; - - { - std::string jpeg; - //Orthanc::Toolbox::DecodeBase64(jpeg, info["PixelData"].asString()); - jpeg = base64_decode(info["PixelData"].asString()); - - try - { - reader.reset(new Orthanc::JpegReader); - dynamic_cast<Orthanc::JpegReader&>(*reader).ReadFromMemory(jpeg); - } - catch (Orthanc::OrthancException&) - { - NotifySliceImageError(operation); - return; - } - } - - Orthanc::PixelFormat expectedFormat = - operation.GetSlice().GetConverter().GetExpectedPixelFormat(); - - if (reader->GetFormat() == Orthanc::PixelFormat_RGB24) // This is a color image - { - if (expectedFormat != Orthanc::PixelFormat_RGB24) - { - NotifySliceImageError(operation); - return; - } - - if (isSigned || isStretched) - { - NotifySliceImageError(operation); - return; - } - else - { - NotifySliceImageSuccess(operation, *reader); - return; - } - } - - if (reader->GetFormat() != Orthanc::PixelFormat_Grayscale8) - { - NotifySliceImageError(operation); - return; - } - - if (!isStretched) - { - if (expectedFormat != reader->GetFormat()) - { - NotifySliceImageError(operation); - return; - } - else - { - NotifySliceImageSuccess(operation, *reader); - return; - } - } - - int32_t stretchLow = 0; - int32_t stretchHigh = 0; - - if (!info.isMember("StretchLow") || - !info.isMember("StretchHigh") || - info["StretchLow"].type() != Json::intValue || - info["StretchHigh"].type() != Json::intValue) - { - NotifySliceImageError(operation); - return; - } - - stretchLow = info["StretchLow"].asInt(); - stretchHigh = info["StretchHigh"].asInt(); - - if (stretchLow < -32768 || - stretchHigh > 65535 || - (stretchLow < 0 && stretchHigh > 32767)) - { - // This range cannot be represented with a uint16_t or an int16_t - NotifySliceImageError(operation); - return; - } - - // Decode a grayscale JPEG 8bpp image coming from the Web viewer - std::unique_ptr<Orthanc::ImageAccessor> image - (new Orthanc::Image(expectedFormat, reader->GetWidth(), reader->GetHeight(), false)); - - Orthanc::ImageProcessing::Convert(*image, *reader); - reader.reset(); - - float scaling = static_cast<float>(stretchHigh - stretchLow) / 255.0f; - - if (!OrthancStone::LinearAlgebra::IsCloseToZero(scaling)) - { - float offset = static_cast<float>(stretchLow) / scaling; - Orthanc::ImageProcessing::ShiftScale(*image, offset, scaling, true); - } - - NotifySliceImageSuccess(operation, *image); - } - - - class StringImage : public Orthanc::ImageAccessor - { - private: - std::string buffer_; - - public: - StringImage(Orthanc::PixelFormat format, - unsigned int width, - unsigned int height, - std::string& buffer) - { - if (buffer.size() != Orthanc::GetBytesPerPixel(format) * width * height) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); - } - - buffer_.swap(buffer); // The source buffer is now empty - - void* data = (buffer_.empty() ? NULL : &buffer_[0]); - - AssignWritable(format, width, height, - Orthanc::GetBytesPerPixel(format) * width, data); - } - }; - - void OrthancSlicesLoader::ParseSliceRawImage(const OrthancApiClient::BinaryResponseReadyMessage& message) - { - const Operation& operation = dynamic_cast<const OrthancSlicesLoader::Operation&>(message.GetPayload()); - Orthanc::GzipCompressor compressor; - - std::string raw; - compressor.Uncompress(raw, message.GetAnswer(), message.GetAnswerSize()); - - const Orthanc::DicomImageInformation& info = operation.GetSlice().GetImageInformation(); - - if (info.GetBitsAllocated() == 32 && - info.GetBitsStored() == 32 && - info.GetHighBit() == 31 && - info.GetChannelCount() == 1 && - !info.IsSigned() && - info.GetPhotometricInterpretation() == Orthanc::PhotometricInterpretation_Monochrome2 && - raw.size() == info.GetWidth() * info.GetHeight() * 4) - { - // This is the case of RT-DOSE (uint32_t values) - - std::unique_ptr<Orthanc::ImageAccessor> image - (new StringImage(Orthanc::PixelFormat_Grayscale32, info.GetWidth(), - info.GetHeight(), raw)); - - // TODO - Only for big endian - for (unsigned int y = 0; y < image->GetHeight(); y++) - { - uint32_t *p = reinterpret_cast<uint32_t*>(image->GetRow(y)); - for (unsigned int x = 0; x < image->GetWidth(); x++, p++) - { - *p = le32toh(*p); - } - } - - NotifySliceImageSuccess(operation, *image); - } - else if (info.GetBitsAllocated() == 16 && - info.GetBitsStored() == 16 && - info.GetHighBit() == 15 && - info.GetChannelCount() == 1 && - !info.IsSigned() && - info.GetPhotometricInterpretation() == Orthanc::PhotometricInterpretation_Monochrome2 && - raw.size() == info.GetWidth() * info.GetHeight() * 2) - { - std::unique_ptr<Orthanc::ImageAccessor> image - (new StringImage(Orthanc::PixelFormat_Grayscale16, info.GetWidth(), - info.GetHeight(), raw)); - - // TODO - Big endian ? - - NotifySliceImageSuccess(operation, *image); - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); - } - - } - - - OrthancSlicesLoader::OrthancSlicesLoader(boost::shared_ptr<OrthancApiClient> orthanc) : - orthanc_(orthanc), - state_(State_Initialization) - { - } - - - void OrthancSlicesLoader::ScheduleLoadSeries(const std::string& seriesId) - { - if (state_ != State_Initialization) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - else - { - state_ = State_LoadingGeometry; - orthanc_->GetJsonAsync("/series/" + seriesId + "/instances-tags", - new DeprecatedCallable<OrthancSlicesLoader, OrthancApiClient::JsonResponseReadyMessage>(GetSharedObserver(), &OrthancSlicesLoader::ParseSeriesGeometry), - new DeprecatedCallable<OrthancSlicesLoader, IWebService::HttpRequestErrorMessage>(GetSharedObserver(), &OrthancSlicesLoader::OnGeometryError), - NULL); - } - } - - void OrthancSlicesLoader::ScheduleLoadInstance(const std::string& instanceId) - { - if (state_ != State_Initialization) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - else - { - state_ = State_LoadingGeometry; - - // Tag "3004-000c" is "Grid Frame Offset Vector", which is - // mandatory to read RT DOSE, but is too long to be returned by default - orthanc_->GetJsonAsync("/instances/" + instanceId + "/tags?ignore-length=3004-000c", - new DeprecatedCallable<OrthancSlicesLoader, OrthancApiClient::JsonResponseReadyMessage>(GetSharedObserver(), &OrthancSlicesLoader::ParseInstanceGeometry), - new DeprecatedCallable<OrthancSlicesLoader, IWebService::HttpRequestErrorMessage>(GetSharedObserver(), &OrthancSlicesLoader::OnGeometryError), - Operation::DownloadInstanceGeometry(instanceId)); - } - } - - - void OrthancSlicesLoader::ScheduleLoadFrame(const std::string& instanceId, - unsigned int frame) - { - if (state_ != State_Initialization) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - else - { - state_ = State_LoadingGeometry; - - orthanc_->GetJsonAsync("/instances/" + instanceId + "/tags", - new DeprecatedCallable<OrthancSlicesLoader, OrthancApiClient::JsonResponseReadyMessage>(GetSharedObserver(), &OrthancSlicesLoader::ParseFrameGeometry), - new DeprecatedCallable<OrthancSlicesLoader, IWebService::HttpRequestErrorMessage>(GetSharedObserver(), &OrthancSlicesLoader::OnGeometryError), - Operation::DownloadFrameGeometry(instanceId, frame)); - } - } - - - bool OrthancSlicesLoader::IsGeometryReady() const - { - return state_ == State_GeometryReady; - } - - - size_t OrthancSlicesLoader::GetSlicesCount() const - { - if (state_ != State_GeometryReady) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - return slices_.GetSlicesCount(); - } - - - const Slice& OrthancSlicesLoader::GetSlice(size_t index) const - { - if (state_ != State_GeometryReady) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - return dynamic_cast<const Slice&>(slices_.GetSlicePayload(index)); - } - - - bool OrthancSlicesLoader::LookupSlice(size_t& index, - const OrthancStone::CoordinateSystem3D& plane) const - { - if (state_ != State_GeometryReady) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - double distance; - return (slices_.LookupClosestSlice(index, distance, plane) && - distance <= GetSlice(index).GetThickness() / 2.0); - } - - - void OrthancSlicesLoader::ScheduleSliceImagePng(const Slice& slice, - size_t index) - { - std::string uri = ("/instances/" + slice.GetOrthancInstanceId() + "/frames/" + - boost::lexical_cast<std::string>(slice.GetFrame())); - - switch (slice.GetConverter().GetExpectedPixelFormat()) - { - case Orthanc::PixelFormat_RGB24: - uri += "/preview"; - break; - - case Orthanc::PixelFormat_Grayscale16: - uri += "/image-uint16"; - break; - - case Orthanc::PixelFormat_SignedGrayscale16: - uri += "/image-int16"; - break; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - orthanc_->GetBinaryAsync(uri, "image/png", - new DeprecatedCallable<OrthancSlicesLoader, - OrthancApiClient::BinaryResponseReadyMessage> - (GetSharedObserver(), &OrthancSlicesLoader::ParseSliceImagePng), - new DeprecatedCallable<OrthancSlicesLoader, - IWebService::HttpRequestErrorMessage> - (GetSharedObserver(), &OrthancSlicesLoader::OnSliceImageError), - Operation::DownloadSliceImage( - static_cast<unsigned int>(index), slice, SliceImageQuality_FullPng)); - } - - void OrthancSlicesLoader::ScheduleSliceImagePam(const Slice& slice, - size_t index) - { - std::string uri = - ("/instances/" + slice.GetOrthancInstanceId() + "/frames/" + - boost::lexical_cast<std::string>(slice.GetFrame())); - - switch (slice.GetConverter().GetExpectedPixelFormat()) - { - case Orthanc::PixelFormat_RGB24: - uri += "/preview"; - break; - - case Orthanc::PixelFormat_Grayscale16: - uri += "/image-uint16"; - break; - - case Orthanc::PixelFormat_SignedGrayscale16: - uri += "/image-int16"; - break; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - orthanc_->GetBinaryAsync(uri, "image/x-portable-arbitrarymap", - new DeprecatedCallable<OrthancSlicesLoader, - OrthancApiClient::BinaryResponseReadyMessage> - (GetSharedObserver(), &OrthancSlicesLoader::ParseSliceImagePam), - new DeprecatedCallable<OrthancSlicesLoader, - IWebService::HttpRequestErrorMessage> - (GetSharedObserver(), &OrthancSlicesLoader::OnSliceImageError), - Operation::DownloadSliceImage(static_cast<unsigned int>(index), - slice, SliceImageQuality_FullPam)); - } - - - - void OrthancSlicesLoader::ScheduleSliceImageJpeg(const Slice& slice, - size_t index, - SliceImageQuality quality) - { - unsigned int value; - - switch (quality) - { - case SliceImageQuality_Jpeg50: - value = 50; - break; - - case SliceImageQuality_Jpeg90: - value = 90; - break; - - case SliceImageQuality_Jpeg95: - value = 95; - break; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - // This requires the official Web viewer plugin to be installed! - std::string uri = ("/web-viewer/instances/jpeg" + - boost::lexical_cast<std::string>(value) + - "-" + slice.GetOrthancInstanceId() + "_" + - boost::lexical_cast<std::string>(slice.GetFrame())); - - orthanc_->GetJsonAsync(uri, - new DeprecatedCallable<OrthancSlicesLoader, - OrthancApiClient::JsonResponseReadyMessage> - (GetSharedObserver(), &OrthancSlicesLoader::ParseSliceImageJpeg), - new DeprecatedCallable<OrthancSlicesLoader, - IWebService::HttpRequestErrorMessage> - (GetSharedObserver(), &OrthancSlicesLoader::OnSliceImageError), - Operation::DownloadSliceImage( - static_cast<unsigned int>(index), slice, quality)); - } - - - - void OrthancSlicesLoader::ScheduleLoadSliceImage(size_t index, - SliceImageQuality quality) - { - if (state_ != State_GeometryReady) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - const Slice& slice = GetSlice(index); - - if (slice.HasOrthancDecoding()) - { - switch (quality) - { - case SliceImageQuality_FullPng: - ScheduleSliceImagePng(slice, index); - break; - case SliceImageQuality_FullPam: - ScheduleSliceImagePam(slice, index); - break; - default: - ScheduleSliceImageJpeg(slice, index, quality); - } - } - else - { - std::string uri = ("/instances/" + slice.GetOrthancInstanceId() + "/frames/" + - boost::lexical_cast<std::string>(slice.GetFrame()) + "/raw.gz"); - orthanc_->GetBinaryAsync(uri, IWebService::HttpHeaders(), - new DeprecatedCallable<OrthancSlicesLoader, - OrthancApiClient::BinaryResponseReadyMessage> - (GetSharedObserver(), &OrthancSlicesLoader::ParseSliceRawImage), - new DeprecatedCallable<OrthancSlicesLoader, - IWebService::HttpRequestErrorMessage> - (GetSharedObserver(), &OrthancSlicesLoader::OnSliceImageError), - Operation::DownloadSliceRawImage( - static_cast<unsigned int>(index), slice)); - } - } -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/OrthancSlicesLoader.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,211 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../Messages/IObservable.h" -#include "../../Messages/ObserverBase.h" -#include "../../StoneEnumerations.h" -#include "../../Toolbox/SlicesSorter.h" -#include "IWebService.h" -#include "OrthancApiClient.h" -#include "Slice.h" - -#include <Images/Image.h> - - -namespace Deprecated -{ - class OrthancSlicesLoader : - public OrthancStone::IObservable, - public OrthancStone::ObserverBase<OrthancSlicesLoader> - { - public: - ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, SliceGeometryReadyMessage, OrthancSlicesLoader); - ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, SliceGeometryErrorMessage, OrthancSlicesLoader); - - - class SliceImageReadyMessage : public OrthancStone::OriginMessage<OrthancSlicesLoader> - { - ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); - - private: - unsigned int sliceIndex_; - const Slice& slice_; - const Orthanc::ImageAccessor& image_; - SliceImageQuality effectiveQuality_; - - public: - SliceImageReadyMessage(const OrthancSlicesLoader& origin, - unsigned int sliceIndex, - const Slice& slice, - const Orthanc::ImageAccessor& image, - SliceImageQuality effectiveQuality) : - OriginMessage(origin), - sliceIndex_(sliceIndex), - slice_(slice), - image_(image), - effectiveQuality_(effectiveQuality) - { - } - - unsigned int GetSliceIndex() const - { - return sliceIndex_; - } - - const Slice& GetSlice() const - { - return slice_; - } - - const Orthanc::ImageAccessor& GetImage() const - { - return image_; - } - - SliceImageQuality GetEffectiveQuality() const - { - return effectiveQuality_; - } - }; - - - class SliceImageErrorMessage : public OrthancStone::OriginMessage<OrthancSlicesLoader> - { - ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); - - private: - const Slice& slice_; - unsigned int sliceIndex_; - SliceImageQuality effectiveQuality_; - - public: - SliceImageErrorMessage(const OrthancSlicesLoader& origin, - unsigned int sliceIndex, - const Slice& slice, - SliceImageQuality effectiveQuality) : - OriginMessage(origin), - slice_(slice), - sliceIndex_(sliceIndex), - effectiveQuality_(effectiveQuality) - { - } - unsigned int GetSliceIndex() const - { - return sliceIndex_; - } - - const Slice& GetSlice() const - { - return slice_; - } - - SliceImageQuality GetEffectiveQuality() const - { - return effectiveQuality_; - } - }; - - private: - enum State - { - State_Error, - State_Initialization, - State_LoadingGeometry, - State_GeometryReady - }; - - enum Mode - { - Mode_SeriesGeometry, - Mode_InstanceGeometry, - Mode_FrameGeometry, - Mode_LoadImage, - Mode_LoadRawImage, - Mode_LoadDicomFile - }; - - class Operation; - - boost::shared_ptr<OrthancApiClient> orthanc_; - State state_; - OrthancStone::SlicesSorter slices_; - - void NotifySliceImageSuccess(const Operation& operation, - const Orthanc::ImageAccessor& image); - - void NotifySliceImageError(const Operation& operation); - - void OnGeometryError(const IWebService::HttpRequestErrorMessage& message); - - void OnSliceImageError(const IWebService::HttpRequestErrorMessage& message); - - void ParseSeriesGeometry(const OrthancApiClient::JsonResponseReadyMessage& message); - - void ParseInstanceGeometry(const OrthancApiClient::JsonResponseReadyMessage& message); - - void ParseFrameGeometry(const OrthancApiClient::JsonResponseReadyMessage& message); - - void ParseSliceImagePng(const OrthancApiClient::BinaryResponseReadyMessage& message); - - void ParseSliceImagePam(const OrthancApiClient::BinaryResponseReadyMessage& message); - - void ParseSliceImageJpeg(const OrthancApiClient::JsonResponseReadyMessage& message); - - void ParseSliceRawImage(const OrthancApiClient::BinaryResponseReadyMessage& message); - - void ScheduleSliceImagePng(const Slice& slice, - size_t index); - - void ScheduleSliceImagePam(const Slice& slice, - size_t index); - - void ScheduleSliceImageJpeg(const Slice& slice, - size_t index, - SliceImageQuality quality); - - void SortAndFinalizeSlices(); - - public: - OrthancSlicesLoader(//ISliceLoaderObserver& callback, - boost::shared_ptr<OrthancApiClient> orthancApi); - - void ScheduleLoadSeries(const std::string& seriesId); - - void ScheduleLoadInstance(const std::string& instanceId); - - void ScheduleLoadFrame(const std::string& instanceId, - unsigned int frame); - - bool IsGeometryReady() const; - - size_t GetSlicesCount() const; - - const Slice& GetSlice(size_t index) const; - - bool LookupSlice(size_t& index, - const OrthancStone::CoordinateSystem3D& plane) const; - - void ScheduleLoadSliceImage(size_t index, - SliceImageQuality requestedQuality); - }; -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/ParallelSlices.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,215 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "ParallelSlices.h" - -#include "../../Toolbox/GeometryToolbox.h" -#include "../../Volumes/ImageBuffer3D.h" - -#include <Logging.h> -#include <OrthancException.h> - -namespace Deprecated -{ - ParallelSlices::ParallelSlices() - { - Clear(); - } - - - ParallelSlices::ParallelSlices(const ParallelSlices& other) - { - normal_ = other.normal_; - - slices_.resize(other.slices_.size()); - - for (size_t i = 0; i < slices_.size(); i++) - { - assert(other.slices_[i] != NULL); - slices_[i] = new OrthancStone::CoordinateSystem3D(*other.slices_[i]); - } - } - - - void ParallelSlices::Clear() - { - for (size_t i = 0; i < slices_.size(); i++) - { - if (slices_[i] != NULL) - { - delete slices_[i]; - slices_[i] = NULL; - } - } - - slices_.clear(); - OrthancStone::LinearAlgebra::AssignVector(normal_, 0, 0, 1); - } - - - ParallelSlices::~ParallelSlices() - { - Clear(); - } - - - void ParallelSlices::AddSlice(const OrthancStone::CoordinateSystem3D& slice) - { - if (slices_.empty()) - { - normal_ = slice.GetNormal(); - slices_.push_back(new OrthancStone::CoordinateSystem3D(slice)); - } - else if (OrthancStone::GeometryToolbox::IsParallel(slice.GetNormal(), normal_)) - { - slices_.push_back(new OrthancStone::CoordinateSystem3D(slice)); - } - else - { - LOG(ERROR) << "Trying to add a slice that is not parallel to the previous ones"; - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - } - - - void ParallelSlices::AddSlice(const OrthancStone::Vector& origin, - const OrthancStone::Vector& axisX, - const OrthancStone::Vector& axisY) - { - OrthancStone::CoordinateSystem3D slice(origin, axisX, axisY); - AddSlice(slice); - } - - - const OrthancStone::CoordinateSystem3D& ParallelSlices::GetSlice(size_t index) const - { - if (index >= slices_.size()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - else - { - return *slices_[index]; - } - } - - - bool ParallelSlices::ComputeClosestSlice(size_t& closestSlice, - double& closestDistance, - const OrthancStone::Vector& origin) const - { - if (slices_.empty()) - { - return false; - } - - double reference = boost::numeric::ublas::inner_prod(origin, normal_); - - closestSlice = 0; - closestDistance = std::numeric_limits<double>::infinity(); - - for (size_t i = 0; i < slices_.size(); i++) - { - double distance = fabs(boost::numeric::ublas::inner_prod(slices_[i]->GetOrigin(), normal_) - reference); - - if (distance < closestDistance) - { - closestSlice = i; - closestDistance = distance; - } - } - - return true; - } - - - ParallelSlices* ParallelSlices::Reverse() const - { - std::unique_ptr<ParallelSlices> reversed(new ParallelSlices); - - for (size_t i = slices_.size(); i > 0; i--) - { - const OrthancStone::CoordinateSystem3D& slice = *slices_[i - 1]; - - reversed->AddSlice(slice.GetOrigin(), - -slice.GetAxisX(), - slice.GetAxisY()); - } - - return reversed.release(); - } - - - ParallelSlices* ParallelSlices::FromVolumeImage(const OrthancStone::VolumeImageGeometry& geometry, - OrthancStone::VolumeProjection projection) - { - const OrthancStone::Vector dimensions = geometry.GetVoxelDimensions(OrthancStone::VolumeProjection_Axial); - const OrthancStone::CoordinateSystem3D& axial = geometry.GetAxialGeometry(); - - std::unique_ptr<ParallelSlices> result(new ParallelSlices); - - switch (projection) - { - case OrthancStone::VolumeProjection_Axial: - for (unsigned int z = 0; z < geometry.GetDepth(); z++) - { - OrthancStone::Vector origin = axial.GetOrigin(); - origin += static_cast<double>(z) * dimensions[2] * axial.GetNormal(); - - result->AddSlice(origin, - axial.GetAxisX(), - axial.GetAxisY()); - } - break; - - case OrthancStone::VolumeProjection_Coronal: - for (unsigned int y = 0; y < geometry.GetHeight(); y++) - { - OrthancStone::Vector origin = axial.GetOrigin(); - origin += static_cast<double>(y) * dimensions[1] * axial.GetAxisY(); - origin += static_cast<double>(geometry.GetDepth() - 1) * dimensions[2] * axial.GetNormal(); - - result->AddSlice(origin, - axial.GetAxisX(), - -axial.GetNormal()); - } - break; - - case OrthancStone::VolumeProjection_Sagittal: - for (unsigned int x = 0; x < geometry.GetWidth(); x++) - { - OrthancStone::Vector origin = axial.GetOrigin(); - origin += static_cast<double>(x) * dimensions[0] * axial.GetAxisX(); - origin += static_cast<double>(geometry.GetDepth() - 1) * dimensions[2] * axial.GetNormal(); - - result->AddSlice(origin, - axial.GetAxisY(), - -axial.GetNormal()); - } - break; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - return result.release(); - } -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/ParallelSlices.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../Toolbox/CoordinateSystem3D.h" -#include "../../Volumes/VolumeImageGeometry.h" - -namespace Deprecated -{ - class ParallelSlices : public boost::noncopyable - { - private: - OrthancStone::Vector normal_; - std::vector<OrthancStone::CoordinateSystem3D*> slices_; - - ParallelSlices& operator= (const ParallelSlices& other); // Forbidden - - void Clear(); - - public: - ParallelSlices(); - - ParallelSlices(const ParallelSlices& other); - - ~ParallelSlices(); - - const OrthancStone::Vector& GetNormal() const - { - return normal_; - } - - void AddSlice(const OrthancStone::CoordinateSystem3D& slice); - - void AddSlice(const OrthancStone::Vector& origin, - const OrthancStone::Vector& axisX, - const OrthancStone::Vector& axisY); - - size_t GetSliceCount() const - { - return slices_.size(); - } - - const OrthancStone::CoordinateSystem3D& GetSlice(size_t index) const; - - bool ComputeClosestSlice(size_t& closestSlice, - double& closestDistance, - const OrthancStone::Vector& origin) const; - - ParallelSlices* Reverse() const; - - static ParallelSlices* FromVolumeImage(const OrthancStone::VolumeImageGeometry& geometry, - OrthancStone::VolumeProjection projection); - }; -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/ParallelSlicesCursor.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,221 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "ParallelSlicesCursor.h" - -#include <OrthancException.h> - -namespace Deprecated -{ - size_t ParallelSlicesCursor::GetDefaultSlice() - { - if (slices_.get() == NULL) - { - return 0; - } - else - { - return slices_->GetSliceCount() / 2; - } - } - - - size_t ParallelSlicesCursor::GetSliceCount() - { - if (slices_.get() == NULL) - { - return 0; - } - else - { - return slices_->GetSliceCount(); - } - } - - - OrthancStone::CoordinateSystem3D ParallelSlicesCursor::GetSlice(size_t slice) - { - if (slices_.get() == NULL) - { - return OrthancStone::CoordinateSystem3D(); - } - else - { - return slices_->GetSlice(slice); - } - } - - - void ParallelSlicesCursor::SetGeometry(const ParallelSlices& slices) - { - slices_.reset(new ParallelSlices(slices)); - - currentSlice_ = GetDefaultSlice(); - } - - - OrthancStone::CoordinateSystem3D ParallelSlicesCursor::GetCurrentSlice() - { - if (slices_.get() != NULL && - currentSlice_ < slices_->GetSliceCount()) - { - return slices_->GetSlice(currentSlice_); - } - else - { - return OrthancStone::CoordinateSystem3D(); // No slice is available, return the canonical geometry - } - } - - - bool ParallelSlicesCursor::SetDefaultSlice() - { - size_t slice = GetDefaultSlice(); - - if (currentSlice_ != slice) - { - currentSlice_ = slice; - return true; - } - else - { - return false; - } - } - - - bool ParallelSlicesCursor::ApplyOffset(OrthancStone::SliceOffsetMode mode, - int offset) - { - if (slices_.get() == NULL) - { - return false; - } - - int count = static_cast<int>(slices_->GetSliceCount()); - if (count == 0) - { - return false; - } - - int slice; - if (static_cast<int>(currentSlice_) >= count) - { - slice = count - 1; - } - else - { - slice = static_cast<int>(currentSlice_); - } - - switch (mode) - { - case OrthancStone::SliceOffsetMode_Absolute: - { - slice = offset; - break; - } - - case OrthancStone::SliceOffsetMode_Relative: - { - slice += offset; - break; - } - - case OrthancStone::SliceOffsetMode_Loop: - { - slice += offset; - while (slice < 0) - { - slice += count; - } - - while (slice >= count) - { - slice -= count; - } - - break; - } - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - if (slice < 0) - { - slice = 0; - } - - if (slice >= count) - { - slice = count - 1; - } - - if (slice != static_cast<int>(currentSlice_)) - { - currentSlice_ = static_cast<int>(slice); - return true; - } - else - { - return false; - } - } - - - bool ParallelSlicesCursor::ApplyWheelEvent(OrthancStone::MouseWheelDirection direction, - OrthancStone::KeyboardModifiers modifiers) - { - int offset = (modifiers & OrthancStone::KeyboardModifiers_Control ? 10 : 1); - - switch (direction) - { - case OrthancStone::MouseWheelDirection_Down: - return ApplyOffset(OrthancStone::SliceOffsetMode_Relative, -offset); - - case OrthancStone::MouseWheelDirection_Up: - return ApplyOffset(OrthancStone::SliceOffsetMode_Relative, offset); - - default: - return false; - } - } - - - bool ParallelSlicesCursor::LookupSliceContainingPoint(const OrthancStone::Vector& p) - { - size_t slice; - double distance; - - if (slices_.get() != NULL && - slices_->ComputeClosestSlice(slice, distance, p)) - { - if (currentSlice_ != slice) - { - currentSlice_ = slice; - return true; - } - } - - return false; - } -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/ParallelSlicesCursor.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "ParallelSlices.h" -#include "../../StoneEnumerations.h" - -#include <Compatibility.h> - -namespace Deprecated -{ - class ParallelSlicesCursor : public boost::noncopyable - { - private: - std::unique_ptr<ParallelSlices> slices_; - size_t currentSlice_; - - size_t GetDefaultSlice(); - - public: - ParallelSlicesCursor() : - currentSlice_(0) - { - } - - void SetGeometry(const ParallelSlices& slices); - - size_t GetSliceCount(); - - OrthancStone::CoordinateSystem3D GetSlice(size_t slice); - - OrthancStone::CoordinateSystem3D GetCurrentSlice(); - - // Returns "true" iff. the slice has actually changed - bool SetDefaultSlice(); - - // Returns "true" iff. the slice has actually changed - bool ApplyOffset(OrthancStone::SliceOffsetMode mode, - int offset); - - // Returns "true" iff. the slice has actually changed - bool ApplyWheelEvent(OrthancStone::MouseWheelDirection direction, - OrthancStone::KeyboardModifiers modifiers); - - // Returns "true" iff. the slice has actually changed - bool LookupSliceContainingPoint(const OrthancStone::Vector& p); - }; -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/Slice.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,367 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "Slice.h" - -#include "../../StoneEnumerations.h" -#include "../../Toolbox/GeometryToolbox.h" - -#include <Logging.h> -#include <OrthancException.h> -#include <Toolbox.h> - -#include <boost/lexical_cast.hpp> - -namespace Deprecated -{ - static bool ParseDouble(double& target, - const std::string& source) - { - try - { - target = boost::lexical_cast<double>(source); - return true; - } - catch (boost::bad_lexical_cast&) - { - return false; - } - } - - Slice* Slice::Clone() const - { - std::unique_ptr<Slice> target(new Slice()); - - target->type_ = type_; - target->orthancInstanceId_ = orthancInstanceId_; - target->sopClassUid_ = sopClassUid_; - target->frame_ = frame_; - target->frameCount_ = frameCount_; - target->geometry_ = geometry_; - target->pixelSpacingX_ = pixelSpacingX_; - target->pixelSpacingY_ = pixelSpacingY_; - target->thickness_ = thickness_; - target->width_ = width_; - target->height_ = height_; - target->converter_ = converter_; - if (imageInformation_.get() != NULL) - target->imageInformation_.reset(imageInformation_->Clone()); - - return target.release(); - } - - bool Slice::ComputeRTDoseGeometry(const Orthanc::DicomMap& dataset, - unsigned int frame) - { - // http://dicom.nema.org/medical/Dicom/2016a/output/chtml/part03/sect_C.8.8.3.2.html - - { - std::string increment; - - if (dataset.LookupStringValue(increment, Orthanc::DICOM_TAG_FRAME_INCREMENT_POINTER, false)) - { - Orthanc::Toolbox::ToUpperCase(increment); - if (increment != "3004,000C") // This is the "Grid Frame Offset Vector" tag - { - LOG(ERROR) << "Bad value for the \"FrameIncrementPointer\" tag"; - return false; - } - } - } - - std::string offsetTag; - - if (!dataset.LookupStringValue(offsetTag, Orthanc::DICOM_TAG_GRID_FRAME_OFFSET_VECTOR, false) || - offsetTag.empty()) - { - LOG(ERROR) << "Cannot read the \"GridFrameOffsetVector\" tag, check you are using Orthanc >= 1.3.1"; - return false; - } - - std::vector<std::string> offsets; - Orthanc::Toolbox::TokenizeString(offsets, offsetTag, '\\'); - - if (frameCount_ <= 1 || - offsets.size() < frameCount_ || - offsets.size() < 2 || - frame >= frameCount_) - { - LOG(ERROR) << "No information about the 3D location of some slice(s) in a RT DOSE"; - return false; - } - - double offset0, offset1, z; - - if (!ParseDouble(offset0, offsets[0]) || - !ParseDouble(offset1, offsets[1]) || - !ParseDouble(z, offsets[frame])) - { - LOG(ERROR) << "Invalid syntax"; - return false; - } - - if (!OrthancStone::LinearAlgebra::IsCloseToZero(offset0)) - { - LOG(ERROR) << "Invalid syntax"; - return false; - } - - geometry_ = OrthancStone::CoordinateSystem3D(geometry_.GetOrigin() + z * geometry_.GetNormal(), - //+ 650 * geometry_.GetAxisX(), - geometry_.GetAxisX(), - geometry_.GetAxisY()); - - thickness_ = offset1 - offset0; - if (thickness_ < 0) - { - thickness_ = -thickness_; - } - - return true; - } - - - bool Slice::ParseOrthancFrame(const Orthanc::DicomMap& dataset, - const std::string& instanceId, - unsigned int frame) - { - orthancInstanceId_ = instanceId; - frame_ = frame; - type_ = Type_OrthancDecodableFrame; - imageInformation_.reset(new Orthanc::DicomImageInformation(dataset)); - - if (!dataset.LookupStringValue(sopClassUid_, Orthanc::DICOM_TAG_SOP_CLASS_UID, false) || - sopClassUid_.empty()) - { - LOG(ERROR) << "Instance without a SOP class UID"; - return false; - } - - if (!dataset.ParseUnsignedInteger32(frameCount_, Orthanc::DICOM_TAG_NUMBER_OF_FRAMES)) - { - frameCount_ = 1; // Assume instance with one frame - } - - if (frame >= frameCount_) - { - return false; - } - - if (!dataset.ParseUnsignedInteger32(width_, Orthanc::DICOM_TAG_COLUMNS) || - !dataset.ParseUnsignedInteger32(height_, Orthanc::DICOM_TAG_ROWS)) - { - return false; - } - - thickness_ = 100.0 * std::numeric_limits<double>::epsilon(); - - std::string tmp; - if (dataset.LookupStringValue(tmp, Orthanc::DICOM_TAG_SLICE_THICKNESS, false)) - { - if (!tmp.empty() && - !ParseDouble(thickness_, tmp)) - { - return false; // Syntax error - } - } - - converter_.ReadParameters(dataset); - - OrthancStone::GeometryToolbox::GetPixelSpacing(pixelSpacingX_, pixelSpacingY_, dataset); - - std::string position, orientation; - if (dataset.LookupStringValue(position, Orthanc::DICOM_TAG_IMAGE_POSITION_PATIENT, false) && - dataset.LookupStringValue(orientation, Orthanc::DICOM_TAG_IMAGE_ORIENTATION_PATIENT, false)) - { - geometry_ = OrthancStone::CoordinateSystem3D(position, orientation); - - bool ok = true; - - switch (OrthancStone::StringToSopClassUid(sopClassUid_)) - { - case OrthancStone::SopClassUid_RTDose: - type_ = Type_OrthancRawFrame; - ok = ComputeRTDoseGeometry(dataset, frame); - break; - - default: - break; - } - - if (!ok) - { - LOG(ERROR) << "Cannot deduce the 3D location of frame " << frame - << " in instance " << instanceId << ", whose SOP class UID is: " << sopClassUid_; - return false; - } - } - - return true; - } - - - const std::string Slice::GetOrthancInstanceId() const - { - if (type_ == Type_OrthancDecodableFrame || - type_ == Type_OrthancRawFrame) - { - return orthancInstanceId_; - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - } - - - unsigned int Slice::GetFrame() const - { - if (type_ == Type_Invalid) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - return frame_; - } - - - const OrthancStone::CoordinateSystem3D& Slice::GetGeometry() const - { - if (type_ == Type_Invalid) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - return geometry_; - } - - - double Slice::GetThickness() const - { - if (type_ == Type_Invalid) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - return thickness_; - } - - - double Slice::GetPixelSpacingX() const - { - if (type_ == Type_Invalid) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - return pixelSpacingX_; - } - - - double Slice::GetPixelSpacingY() const - { - if (type_ == Type_Invalid) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - return pixelSpacingY_; - } - - - unsigned int Slice::GetWidth() const - { - if (type_ == Type_Invalid) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - return width_; - } - - - unsigned int Slice::GetHeight() const - { - if (type_ == Type_Invalid) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - return height_; - } - - - const DicomFrameConverter& Slice::GetConverter() const - { - if (type_ == Type_Invalid) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - return converter_; - } - - - bool Slice::ContainsPlane(const OrthancStone::CoordinateSystem3D& plane) const - { - if (type_ == Type_Invalid) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - bool opposite; - return (OrthancStone::GeometryToolbox::IsParallelOrOpposite(opposite, - GetGeometry().GetNormal(), - plane.GetNormal()) && - OrthancStone::LinearAlgebra::IsNear(GetGeometry().ProjectAlongNormal(GetGeometry().GetOrigin()), - GetGeometry().ProjectAlongNormal(plane.GetOrigin()), - thickness_ / 2.0)); - } - - - void Slice::GetExtent(std::vector<OrthancStone::Vector>& points) const - { - double sx = GetPixelSpacingX(); - double sy = GetPixelSpacingY(); - double w = static_cast<double>(GetWidth()); - double h = static_cast<double>(GetHeight()); - - points.clear(); - points.push_back(GetGeometry().MapSliceToWorldCoordinates(-0.5 * sx, -0.5 * sy)); - points.push_back(GetGeometry().MapSliceToWorldCoordinates((w - 0.5) * sx, -0.5 * sy)); - points.push_back(GetGeometry().MapSliceToWorldCoordinates(-0.5 * sx, (h - 0.5) * sy)); - points.push_back(GetGeometry().MapSliceToWorldCoordinates((w - 0.5) * sx, (h - 0.5) * sy)); - } - - - const Orthanc::DicomImageInformation& Slice::GetImageInformation() const - { - if (imageInformation_.get() == NULL) - { - // Only available if constructing the "Slice" object with a DICOM map - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - else - { - return *imageInformation_; - } - } -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/Slice.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,155 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../Toolbox/CoordinateSystem3D.h" -#include "DicomFrameConverter.h" - -#include <DicomFormat/DicomImageInformation.h> -#include <IDynamicObject.h> - -namespace Deprecated -{ - // TODO - Remove this class - class Slice : - public Orthanc::IDynamicObject /* to be used as a payload of SlicesSorter */ - { - private: - enum Type - { - Type_Invalid, - Type_Standalone, - Type_OrthancDecodableFrame, - Type_OrthancRawFrame - // TODO A slice could come from some DICOM file (URL) - }; - - bool ComputeRTDoseGeometry(const Orthanc::DicomMap& dataset, - unsigned int frame); - - Type type_; - std::string orthancInstanceId_; - std::string sopClassUid_; - unsigned int frame_; - unsigned int frameCount_; // TODO : Redundant with "imageInformation_" - OrthancStone::CoordinateSystem3D geometry_; - double pixelSpacingX_; - double pixelSpacingY_; - double thickness_; - unsigned int width_; // TODO : Redundant with "imageInformation_" - unsigned int height_; // TODO : Redundant with "imageInformation_" - DicomFrameConverter converter_; // TODO : Partially redundant with "imageInformation_" - - std::unique_ptr<Orthanc::DicomImageInformation> imageInformation_; - - public: - Slice() : - type_(Type_Invalid) - { - } - - - // this constructor is used to reference, i.e, a slice that is being loaded - Slice(const std::string& orthancInstanceId, - unsigned int frame) : - type_(Type_Invalid), - orthancInstanceId_(orthancInstanceId), - frame_(frame) - { - } - - // TODO Is this constructor the best way to go to tackle missing - // layers within SliceViewerWidget? - Slice(const OrthancStone::CoordinateSystem3D& plane, - double thickness) : - type_(Type_Standalone), - frame_(0), - frameCount_(0), - geometry_(plane), - pixelSpacingX_(1), - pixelSpacingY_(1), - thickness_(thickness), - width_(0), - height_(0) - { - } - - Slice(const OrthancStone::CoordinateSystem3D& plane, - double pixelSpacingX, - double pixelSpacingY, - double thickness, - unsigned int width, - unsigned int height, - const DicomFrameConverter& converter) : - type_(Type_Standalone), - frameCount_(1), - geometry_(plane), - pixelSpacingX_(pixelSpacingX), - pixelSpacingY_(pixelSpacingY), - thickness_(thickness), - width_(width), - height_(height), - converter_(converter) - { - } - - bool IsValid() const - { - return type_ != Type_Invalid; - } - - bool ParseOrthancFrame(const Orthanc::DicomMap& dataset, - const std::string& instanceId, - unsigned int frame); - - bool HasOrthancDecoding() const - { - return type_ == Type_OrthancDecodableFrame; - } - - const std::string GetOrthancInstanceId() const; - - unsigned int GetFrame() const; - - const OrthancStone::CoordinateSystem3D& GetGeometry() const; - - double GetThickness() const; - - double GetPixelSpacingX() const; - - double GetPixelSpacingY() const; - - unsigned int GetWidth() const; - - unsigned int GetHeight() const; - - const DicomFrameConverter& GetConverter() const; - - bool ContainsPlane(const OrthancStone::CoordinateSystem3D& plane) const; - - void GetExtent(std::vector<OrthancStone::Vector>& points) const; - - const Orthanc::DicomImageInformation& GetImageInformation() const; - - Slice* Clone() const; - }; -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/ViewportGeometry.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,217 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "ViewportGeometry.h" - -#include <Logging.h> -#include <OrthancException.h> - -#include <boost/math/special_functions/round.hpp> - -namespace Deprecated -{ - void ViewportGeometry::ComputeTransform() - { - // The following lines must be read in reverse order! - cairo_matrix_t tmp; - - // Bring the center of the scene to the center of the view - cairo_matrix_init_translate(&transform_, - panX_ + static_cast<double>(width_) / 2.0, - panY_ + static_cast<double>(height_) / 2.0); - - // Apply the zoom around (0,0) - cairo_matrix_init_scale(&tmp, zoom_, zoom_); - cairo_matrix_multiply(&transform_, &tmp, &transform_); - - // Bring the center of the scene to (0,0) - cairo_matrix_init_translate(&tmp, - -(sceneExtent_.GetX1() + sceneExtent_.GetX2()) / 2.0, - -(sceneExtent_.GetY1() + sceneExtent_.GetY2()) / 2.0); - cairo_matrix_multiply(&transform_, &tmp, &transform_); - } - - - ViewportGeometry::ViewportGeometry() - { - width_ = 0; - height_ = 0; - - zoom_ = 1; - panX_ = 0; - panY_ = 0; - - ComputeTransform(); - } - - - void ViewportGeometry::SetDisplaySize(unsigned int width, - unsigned int height) - { - if (width_ != width || - height_ != height) - { - LOG(INFO) << "New display size: " << width << "x" << height; - - width_ = width; - height_ = height; - - ComputeTransform(); - } - } - - - void ViewportGeometry::SetSceneExtent(const OrthancStone::Extent2D& extent) - { -// LOG(INFO) << "New scene extent: (" -// << extent.GetX1() << "," << extent.GetY1() << ") => (" -// << extent.GetX2() << "," << extent.GetY2() << ")"; - - sceneExtent_ = extent; - ComputeTransform(); - } - - - void ViewportGeometry::MapDisplayToScene(double& sceneX /* out */, - double& sceneY /* out */, - double x, - double y) const - { - cairo_matrix_t transform = transform_; - - if (cairo_matrix_invert(&transform) != CAIRO_STATUS_SUCCESS) - { - LOG(ERROR) << "Cannot invert singular matrix"; - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - - sceneX = x; - sceneY = y; - cairo_matrix_transform_point(&transform, &sceneX, &sceneY); - } - - - void ViewportGeometry::MapSceneToDisplay(int& displayX /* out */, - int& displayY /* out */, - double x, - double y) const - { - cairo_matrix_transform_point(&transform_, &x, &y); - - displayX = static_cast<int>(boost::math::iround(x)); - displayY = static_cast<int>(boost::math::iround(y)); - } - - - void ViewportGeometry::MapPixelCenterToScene(std::vector<Touch>& sceneTouches /* out */, - const std::vector<Touch>& displayTouches) const - { - double sceneX, sceneY; - sceneTouches.clear(); - for (size_t t = 0; t < displayTouches.size(); t++) - { - MapPixelCenterToScene( - sceneX, - sceneY, - static_cast<int>(displayTouches[t].x), - static_cast<int>(displayTouches[t].y)); - - sceneTouches.push_back(Touch((float)sceneX, (float)sceneY)); - } - } - - void ViewportGeometry::MapPixelCenterToScene(double& sceneX, - double& sceneY, - int x, - int y) const - { - // Take the center of the pixel - MapDisplayToScene(sceneX, sceneY, - static_cast<double>(x) + 0.5, - static_cast<double>(y) + 0.5); - } - - - void ViewportGeometry::FitContent() - { - if (width_ > 0 && - height_ > 0 && - !sceneExtent_.IsEmpty()) - { - double zoomX = static_cast<double>(width_) / (sceneExtent_.GetX2() - sceneExtent_.GetX1()); - double zoomY = static_cast<double>(height_) / (sceneExtent_.GetY2() - sceneExtent_.GetY1()); - zoom_ = zoomX < zoomY ? zoomX : zoomY; - - panX_ = 0; - panY_ = 0; - - ComputeTransform(); - } - } - - - void ViewportGeometry::ApplyTransform(OrthancStone::CairoContext& context) const - { - cairo_set_matrix(context.GetObject(), &transform_); - } - - - void ViewportGeometry::GetPan(double& x, - double& y) const - { - x = panX_; - y = panY_; - } - - - void ViewportGeometry::SetPan(double x, - double y) - { - panX_ = x; - panY_ = y; - ComputeTransform(); - } - - - void ViewportGeometry::SetZoom(double zoom) - { - zoom_ = zoom; - ComputeTransform(); - } - - - OrthancStone::Matrix ViewportGeometry::GetMatrix() const - { - OrthancStone::Matrix m(3, 3); - - m(0, 0) = transform_.xx; - m(0, 1) = transform_.xy; - m(0, 2) = transform_.x0; - m(1, 0) = transform_.yx; - m(1, 1) = transform_.yy; - m(1, 2) = transform_.y0; - m(2, 0) = 0; - m(2, 1) = 0; - m(2, 2) = 1; - - return m; - } -}
--- a/OrthancStone/Sources/Deprecated/Toolbox/ViewportGeometry.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../Wrappers/CairoContext.h" -#include "../../Toolbox/Extent2D.h" -#include "../../Toolbox/LinearAlgebra.h" -#include "../Viewport/IMouseTracker.h" // to include "Touch" definition - -namespace Deprecated -{ - class ViewportGeometry - { - private: - // Extent of the scene (in world units) - OrthancStone::Extent2D sceneExtent_; - - // Size of the display (in pixels) - unsigned int width_; - unsigned int height_; - - // Zoom/pan - double zoom_; - double panX_; // In pixels (display units) - double panY_; - - cairo_matrix_t transform_; // Scene-to-display transformation - - void ComputeTransform(); - - public: - ViewportGeometry(); - - void SetDisplaySize(unsigned int width, - unsigned int height); - - void SetSceneExtent(const OrthancStone::Extent2D& extent); - - const OrthancStone::Extent2D& GetSceneExtent() const - { - return sceneExtent_; - } - - void MapDisplayToScene(double& sceneX /* out */, - double& sceneY /* out */, - double x, - double y) const; - - void MapPixelCenterToScene(double& sceneX /* out */, - double& sceneY /* out */, - int x, - int y) const; - - void MapPixelCenterToScene(std::vector<Touch>& sceneTouches /* out */, - const std::vector<Touch>& displayTouches) const; - - void MapSceneToDisplay(int& displayX /* out */, - int& displayY /* out */, - double x, - double y) const; - - unsigned int GetDisplayWidth() const - { - return width_; - } - - unsigned int GetDisplayHeight() const - { - return height_; - } - - double GetZoom() const - { - return zoom_; - } - - void FitContent(); - - void ApplyTransform(OrthancStone::CairoContext& context) const; - - void GetPan(double& x, - double& y) const; - - void SetPan(double x, - double y); - - void SetZoom(double zoom); - - OrthancStone::Matrix GetMatrix() const; - }; -}
--- a/OrthancStone/Sources/Deprecated/Viewport/CairoFont.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "CairoFont.h" - -#include <Logging.h> -#include <OrthancException.h> - -namespace Deprecated -{ - CairoFont::CairoFont(const char* family, - cairo_font_slant_t slant, - cairo_font_weight_t weight) - { - font_ = cairo_toy_font_face_create(family, slant, weight); - if (font_ == NULL) - { - LOG(ERROR) << "Unknown font: " << family; - throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource); - } - } - - - CairoFont::~CairoFont() - { - if (font_ != NULL) - { - cairo_font_face_destroy(font_); - } - } - - - void CairoFont::Draw(OrthancStone::CairoContext& context, - const std::string& text, - double size) - { - if (size <= 0) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - cairo_t* cr = context.GetObject(); - cairo_set_font_face(cr, font_); - cairo_set_font_size(cr, size); - cairo_show_text(cr, text.c_str()); - } -}
--- a/OrthancStone/Sources/Deprecated/Viewport/CairoFont.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#if !defined(ORTHANC_SANDBOXED) -# error The macro ORTHANC_SANDBOXED must be defined -#endif - -#if ORTHANC_SANDBOXED == 1 -# error The class CairoFont cannot be used in sandboxed environments -#endif - -#include "../../Wrappers/CairoContext.h" - -namespace Deprecated -{ - class CairoFont : public boost::noncopyable - { - private: - cairo_font_face_t* font_; - - public: - CairoFont(const char* family, - cairo_font_slant_t slant, - cairo_font_weight_t weight); - - ~CairoFont(); - - void Draw(OrthancStone::CairoContext& context, - const std::string& text, - double size); - }; -}
--- a/OrthancStone/Sources/Deprecated/Viewport/IMouseTracker.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../Wrappers/CairoSurface.h" -#include <vector> - -namespace Deprecated -{ - struct Touch - { - float x; - float y; - - Touch(float x, float y) - : x(x), - y(y) - { - } - Touch() - : x(0.0f), - y(0.0f) - { - } - }; - - - // this is tracking a mouse in screen coordinates/pixels unlike - // the IWorldSceneMouseTracker that is tracking a mouse - // in scene coordinates/mm. - class IMouseTracker : public boost::noncopyable - { - public: - virtual ~IMouseTracker() - { - } - - virtual void Render(Orthanc::ImageAccessor& surface) = 0; - - virtual void MouseUp() = 0; - - // Returns "true" iff. the background scene must be repainted - virtual void MouseMove(int x, - int y, - const std::vector<Touch>& displayTouches) = 0; - }; -}
--- a/OrthancStone/Sources/Deprecated/Viewport/IStatusBar.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include <string> -#include <boost/noncopyable.hpp> - -namespace Deprecated -{ - class IStatusBar : public boost::noncopyable - { - public: - virtual ~IStatusBar() - { - } - - virtual void ClearMessage() = 0; - - virtual void SetMessage(const std::string& message) = 0; - }; -}
--- a/OrthancStone/Sources/Deprecated/Viewport/IViewport.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "IStatusBar.h" -#include "../../StoneEnumerations.h" -#include "../../Messages/IObservable.h" -#include "../Viewport/IMouseTracker.h" // only to get the "Touch" definition - -#include <Images/ImageAccessor.h> - - -namespace Deprecated -{ - class IWidget; // Forward declaration - - class IViewport : public OrthancStone::IObservable - { - public: - ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, ViewportChangedMessage, IViewport); - - virtual void FitContent() = 0; - - virtual void SetStatusBar(IStatusBar& statusBar) = 0; - - virtual void SetSize(unsigned int width, - unsigned int height) = 0; - - // The function returns "true" iff. a new frame was rendered - virtual bool Render(Orthanc::ImageAccessor& surface) = 0; - - virtual void MouseDown(OrthancStone::MouseButton button, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers, - const std::vector<Touch>& touches) = 0; - - virtual void MouseUp() = 0; - - virtual void MouseMove(int x, - int y, - const std::vector<Touch>& displayTouches) = 0; - - virtual void MouseEnter() = 0; - - virtual void MouseLeave() = 0; - - virtual void MouseWheel(OrthancStone::MouseWheelDirection direction, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers) = 0; - - virtual void KeyPressed(OrthancStone::KeyboardKeys key, - char keyChar, - OrthancStone::KeyboardModifiers modifiers) = 0; - - virtual bool HasAnimation() = 0; - - virtual void DoAnimation() = 0; - - // Should only be called from IWidget - // TODO Why should this be virtual? - virtual void NotifyContentChanged() - { - BroadcastMessage(ViewportChangedMessage(*this)); - } - }; -}
--- a/OrthancStone/Sources/Deprecated/Viewport/WidgetViewport.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,286 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "WidgetViewport.h" - -#include <Images/ImageProcessing.h> -#include <OrthancException.h> - -namespace Deprecated -{ - WidgetViewport::WidgetViewport() : - statusBar_(NULL), - isMouseOver_(false), - lastMouseX_(0), - lastMouseY_(0), - backgroundChanged_(false) - { - } - - - void WidgetViewport::FitContent() - { - if (centralWidget_.get() != NULL) - { - centralWidget_->FitContent(); - } - } - - - void WidgetViewport::SetStatusBar(IStatusBar& statusBar) - { - statusBar_ = &statusBar; - - if (centralWidget_.get() != NULL) - { - centralWidget_->SetStatusBar(statusBar); - } - } - - - void WidgetViewport::SetCentralWidget(boost::shared_ptr<IWidget> widget) - { - if (widget == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - mouseTracker_.reset(NULL); - - centralWidget_ = widget; - centralWidget_->SetViewport(*this); - - if (statusBar_ != NULL) - { - centralWidget_->SetStatusBar(*statusBar_); - } - - NotifyBackgroundChanged(); - } - - - void WidgetViewport::NotifyBackgroundChanged() - { - backgroundChanged_ = true; - NotifyContentChanged(); - } - - - void WidgetViewport::SetSize(unsigned int width, - unsigned int height) - { - background_.SetSize(width, height, false /* no alpha */); - - if (centralWidget_.get() != NULL) - { - centralWidget_->SetSize(width, height); - } - - NotifyBackgroundChanged(); - } - - - bool WidgetViewport::Render(Orthanc::ImageAccessor& surface) - { - if (centralWidget_.get() == NULL) - { - return false; - } - - Orthanc::ImageAccessor background; - background_.GetWriteableAccessor(background); - - if (backgroundChanged_ && - !centralWidget_->Render(background)) - { - return false; - } - - if (background.GetWidth() != surface.GetWidth() || - background.GetHeight() != surface.GetHeight()) - { - return false; - } - - Orthanc::ImageProcessing::Convert(surface, background); - - if (mouseTracker_.get() != NULL) - { - mouseTracker_->Render(surface); - } - else if (isMouseOver_) - { - centralWidget_->RenderMouseOver(surface, lastMouseX_, lastMouseY_); - } - - return true; - } - - void WidgetViewport::TouchStart(const std::vector<Touch>& displayTouches) - { - MouseDown(OrthancStone::MouseButton_Left, (int)displayTouches[0].x, (int)displayTouches[0].y, OrthancStone::KeyboardModifiers_None, displayTouches); // one touch is equivalent to a mouse tracker without left button -> set the mouse coordinates to the first touch coordinates - } - - void WidgetViewport::TouchMove(const std::vector<Touch>& displayTouches) - { - MouseMove((int)displayTouches[0].x, (int)displayTouches[0].y, displayTouches); // one touch is equivalent to a mouse tracker without left button -> set the mouse coordinates to the first touch coordinates - } - - void WidgetViewport::TouchEnd(const std::vector<Touch>& displayTouches) - { - // note: TouchEnd is not triggered when a single touch gesture ends (it is only triggered when - // going from 2 touches to 1 touch, ...) - MouseUp(); - } - - void WidgetViewport::MouseDown(OrthancStone::MouseButton button, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers, - const std::vector<Touch>& displayTouches - ) - { - lastMouseX_ = x; - lastMouseY_ = y; - - if (centralWidget_.get() != NULL) - { - mouseTracker_.reset(centralWidget_->CreateMouseTracker(button, x, y, modifiers, displayTouches)); - } - else - { - mouseTracker_.reset(NULL); - } - - NotifyContentChanged(); - } - - - void WidgetViewport::MouseUp() - { - if (mouseTracker_.get() != NULL) - { - mouseTracker_->MouseUp(); - mouseTracker_.reset(NULL); - NotifyContentChanged(); - } - } - - - void WidgetViewport::MouseMove(int x, - int y, - const std::vector<Touch>& displayTouches) - { - if (centralWidget_.get() == NULL) - { - return; - } - - lastMouseX_ = x; - lastMouseY_ = y; - - bool repaint = false; - - if (mouseTracker_.get() != NULL) - { - mouseTracker_->MouseMove(x, y, displayTouches); - repaint = true; - } - else - { - repaint = centralWidget_->HasRenderMouseOver(); - } - - if (repaint) - { - // The scene must be repainted, notify the observers - NotifyContentChanged(); - } - } - - - void WidgetViewport::MouseEnter() - { - isMouseOver_ = true; - NotifyContentChanged(); - } - - - void WidgetViewport::MouseLeave() - { - isMouseOver_ = false; - - if (mouseTracker_.get() != NULL) - { - mouseTracker_->MouseUp(); - mouseTracker_.reset(NULL); - } - - NotifyContentChanged(); - } - - - void WidgetViewport::MouseWheel(OrthancStone::MouseWheelDirection direction, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers) - { - if (centralWidget_.get() != NULL && - mouseTracker_.get() == NULL) - { - centralWidget_->MouseWheel(direction, x, y, modifiers); - } - } - - - void WidgetViewport::KeyPressed(OrthancStone::KeyboardKeys key, - char keyChar, - OrthancStone::KeyboardModifiers modifiers) - { - if (centralWidget_.get() != NULL && - mouseTracker_.get() == NULL) - { - centralWidget_->KeyPressed(key, keyChar, modifiers); - } - } - - - bool WidgetViewport::HasAnimation() - { - if (centralWidget_.get() != NULL) - { - return centralWidget_->HasAnimation(); - } - else - { - return false; - } - } - - - void WidgetViewport::DoAnimation() - { - if (centralWidget_.get() != NULL) - { - centralWidget_->DoAnimation(); - } - } -}
--- a/OrthancStone/Sources/Deprecated/Viewport/WidgetViewport.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "IViewport.h" -#include "../Widgets/IWidget.h" - -#include <Compatibility.h> - -#include <memory> - -namespace Deprecated -{ - class WidgetViewport : public IViewport - { - private: - boost::shared_ptr<IWidget> centralWidget_; - IStatusBar* statusBar_; - std::unique_ptr<IMouseTracker> mouseTracker_; - bool isMouseOver_; - int lastMouseX_; - int lastMouseY_; - OrthancStone::CairoSurface background_; - bool backgroundChanged_; - - public: - WidgetViewport(); - - virtual void FitContent(); - - virtual void SetStatusBar(IStatusBar& statusBar); - - void SetCentralWidget(boost::shared_ptr<IWidget> widget); - - virtual void NotifyBackgroundChanged(); - - virtual void SetSize(unsigned int width, - unsigned int height); - - virtual bool Render(Orthanc::ImageAccessor& surface); - - virtual void MouseDown(OrthancStone::MouseButton button, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers, - const std::vector<Touch>& displayTouches); - - virtual void MouseUp(); - - virtual void MouseMove(int x, - int y, - const std::vector<Touch>& displayTouches); - - virtual void MouseEnter(); - - virtual void MouseLeave(); - - virtual void TouchStart(const std::vector<Touch>& touches); - - virtual void TouchMove(const std::vector<Touch>& touches); - - virtual void TouchEnd(const std::vector<Touch>& touches); - - virtual void MouseWheel(OrthancStone::MouseWheelDirection direction, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers); - - virtual void KeyPressed(OrthancStone::KeyboardKeys key, - char keyChar, - OrthancStone::KeyboardModifiers modifiers); - - virtual bool HasAnimation(); - - virtual void DoAnimation(); - }; -}
--- a/OrthancStone/Sources/Deprecated/Volumes/ISlicedVolume.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../Messages/IObservable.h" -#include "../Toolbox/Slice.h" - -namespace Deprecated -{ - class ISlicedVolume : public OrthancStone::IObservable - { - public: - ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, ContentChangedMessage, ISlicedVolume); - ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, GeometryErrorMessage, ISlicedVolume); - ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, GeometryReadyMessage, ISlicedVolume); - ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, VolumeReadyMessage, ISlicedVolume); - - - class SliceContentChangedMessage : public OrthancStone::OriginMessage<ISlicedVolume> - { - ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); - - private: - size_t sliceIndex_; - const Slice& slice_; - - public: - SliceContentChangedMessage(ISlicedVolume& origin, - size_t sliceIndex, - const Slice& slice) : - OriginMessage(origin), - sliceIndex_(sliceIndex), - slice_(slice) - { - } - - size_t GetSliceIndex() const - { - return sliceIndex_; - } - - const Slice& GetSlice() const - { - return slice_; - } - }; - - - virtual size_t GetSliceCount() const = 0; - - virtual const Slice& GetSlice(size_t slice) const = 0; - }; -}
--- a/OrthancStone/Sources/Deprecated/Volumes/IVolumeLoader.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../Messages/IObservable.h" - -namespace Deprecated -{ - class IVolumeLoader : public OrthancStone::IObservable - { - public: - ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, GeometryReadyMessage, IVolumeLoader); - ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, GeometryErrorMessage, IVolumeLoader); - ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, ContentChangedMessage, IVolumeLoader); - }; -}
--- a/OrthancStone/Sources/Deprecated/Volumes/StructureSetLoader.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,156 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "StructureSetLoader.h" - -#include "../Toolbox/MessagingToolbox.h" - -#include <OrthancException.h> - -namespace Deprecated -{ - StructureSetLoader::StructureSetLoader(OrthancApiClient& orthanc) : - orthanc_(orthanc) - { - } - - - void StructureSetLoader::OnReferencedSliceLoaded(const OrthancApiClient::JsonResponseReadyMessage& message) - { - OrthancPlugins::FullOrthancDataset dataset(message.GetJson()); - - Orthanc::DicomMap slice; - MessagingToolbox::ConvertDataset(slice, dataset); - structureSet_->AddReferencedSlice(slice); - - BroadcastMessage(ContentChangedMessage(*this)); - } - - - void StructureSetLoader::OnStructureSetLoaded(const OrthancApiClient::JsonResponseReadyMessage& message) - { - OrthancPlugins::FullOrthancDataset dataset(message.GetJson()); - structureSet_.reset(new OrthancStone::DicomStructureSet(dataset)); - - std::set<std::string> instances; - structureSet_->GetReferencedInstances(instances); - - for (std::set<std::string>::const_iterator it = instances.begin(); - it != instances.end(); ++it) - { - orthanc_.PostBinaryAsyncExpectJson("/tools/lookup", *it, - new DeprecatedCallable<StructureSetLoader, OrthancApiClient::JsonResponseReadyMessage>(GetSharedObserver(), &StructureSetLoader::OnLookupCompleted)); - } - - BroadcastMessage(GeometryReadyMessage(*this)); - } - - - void StructureSetLoader::OnLookupCompleted(const OrthancApiClient::JsonResponseReadyMessage& message) - { - const Json::Value& lookup = message.GetJson(); - - if (lookup.type() != Json::arrayValue || - lookup.size() != 1 || - !lookup[0].isMember("Type") || - !lookup[0].isMember("Path") || - lookup[0]["Type"].type() != Json::stringValue || - lookup[0]["ID"].type() != Json::stringValue || - lookup[0]["Type"].asString() != "Instance") - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol); - } - - const std::string& instance = lookup[0]["ID"].asString(); - orthanc_.GetJsonAsync("/instances/" + instance + "/tags", - new DeprecatedCallable<StructureSetLoader, OrthancApiClient::JsonResponseReadyMessage>(GetSharedObserver(), &StructureSetLoader::OnReferencedSliceLoaded)); - } - - - void StructureSetLoader::ScheduleLoadInstance(const std::string& instance) - { - if (structureSet_.get() != NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - else - { - orthanc_.GetJsonAsync("/instances/" + instance + "/tags?ignore-length=3006-0050", - new DeprecatedCallable<StructureSetLoader, OrthancApiClient::JsonResponseReadyMessage>(GetSharedObserver(), &StructureSetLoader::OnStructureSetLoaded)); - } - } - - - OrthancStone::DicomStructureSet& StructureSetLoader::GetStructureSet() - { - if (structureSet_.get() == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - else - { - return *structureSet_; - } - } - - - OrthancStone::DicomStructureSet* StructureSetLoader::SynchronousLoad( - OrthancPlugins::IOrthancConnection& orthanc, - const std::string& instanceId) - { - const std::string uri = "/instances/" + instanceId + "/tags?ignore-length=3006-0050"; - OrthancPlugins::FullOrthancDataset dataset(orthanc, uri); - - std::unique_ptr<OrthancStone::DicomStructureSet> result - (new OrthancStone::DicomStructureSet(dataset)); - - std::set<std::string> instances; - result->GetReferencedInstances(instances); - - for (std::set<std::string>::const_iterator it = instances.begin(); - it != instances.end(); ++it) - { - Json::Value lookup; - MessagingToolbox::RestApiPost(lookup, orthanc, "/tools/lookup", *it); - - if (lookup.type() != Json::arrayValue || - lookup.size() != 1 || - !lookup[0].isMember("Type") || - !lookup[0].isMember("Path") || - lookup[0]["Type"].type() != Json::stringValue || - lookup[0]["ID"].type() != Json::stringValue || - lookup[0]["Type"].asString() != "Instance") - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource); - } - - OrthancPlugins::FullOrthancDataset slice - (orthanc, "/instances/" + lookup[0]["ID"].asString() + "/tags"); - Orthanc::DicomMap m; - MessagingToolbox::ConvertDataset(m, slice); - result->AddReferencedSlice(m); - } - - result->CheckReferencedSlices(); - - return result.release(); - } -}
--- a/OrthancStone/Sources/Deprecated/Volumes/StructureSetLoader.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../Messages/ObserverBase.h" -#include "../../Toolbox/DicomStructureSet.h" -#include "../Toolbox/OrthancApiClient.h" -#include "IVolumeLoader.h" - -#include <Compatibility.h> - -namespace Deprecated -{ - class StructureSetLoader : - public IVolumeLoader, - public OrthancStone::ObserverBase<StructureSetLoader> - { - private: - OrthancApiClient& orthanc_; - std::unique_ptr<OrthancStone::DicomStructureSet> structureSet_; - - void OnReferencedSliceLoaded(const OrthancApiClient::JsonResponseReadyMessage& message); - - void OnStructureSetLoaded(const OrthancApiClient::JsonResponseReadyMessage& message); - - void OnLookupCompleted(const OrthancApiClient::JsonResponseReadyMessage& message); - - public: - StructureSetLoader(OrthancApiClient& orthanc); - - void ScheduleLoadInstance(const std::string& instance); - - bool HasStructureSet() const - { - return structureSet_.get() != NULL; - } - - OrthancStone::DicomStructureSet& GetStructureSet(); - - static OrthancStone::DicomStructureSet* SynchronousLoad( - OrthancPlugins::IOrthancConnection& orthanc, - const std::string& instanceId); - }; -}
--- a/OrthancStone/Sources/Deprecated/Widgets/CairoWidget.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "CairoWidget.h" - -#include <Images/ImageProcessing.h> -#include <OrthancException.h> - -namespace Deprecated -{ - static bool IsAligned(const Orthanc::ImageAccessor& target) - { - // TODO - return true; - } - - CairoWidget::CairoWidget(const std::string& name) : - WidgetBase(name) - { - } - - void CairoWidget::SetSize(unsigned int width, - unsigned int height) - { - surface_.SetSize(width, height, false /* no alpha */); - } - - - bool CairoWidget::Render(Orthanc::ImageAccessor& target) - { - // Don't call the base class here, as - // "ClearBackgroundCairo()" is a faster alternative - - if (IsAligned(target)) - { - OrthancStone::CairoSurface surface(target, false /* no alpha */); - OrthancStone::CairoContext context(surface); - ClearBackgroundCairo(context); - return RenderCairo(context); - } - else - { - OrthancStone::CairoContext context(surface_); - ClearBackgroundCairo(context); - - if (RenderCairo(context)) - { - Orthanc::ImageAccessor surface; - surface_.GetReadOnlyAccessor(surface); - Orthanc::ImageProcessing::Copy(target, surface); - return true; - } - else - { - return false; - } - } - } - - - void CairoWidget::RenderMouseOver(Orthanc::ImageAccessor& target, - int x, - int y) - { - if (IsAligned(target)) - { - OrthancStone::CairoSurface surface(target, false /* no alpha */); - OrthancStone::CairoContext context(surface); - RenderMouseOverCairo(context, x, y); - } - else - { - Orthanc::ImageAccessor accessor; - surface_.GetWriteableAccessor(accessor); - Orthanc::ImageProcessing::Copy(accessor, target); - - OrthancStone::CairoContext context(surface_); - RenderMouseOverCairo(context, x, y); - - Orthanc::ImageProcessing::Copy(target, accessor); - } - } -}
--- a/OrthancStone/Sources/Deprecated/Widgets/CairoWidget.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "WidgetBase.h" - -namespace Deprecated -{ - class CairoWidget : public WidgetBase - { - private: - OrthancStone::CairoSurface surface_; - - protected: - virtual bool RenderCairo(OrthancStone::CairoContext& context) = 0; - - virtual void RenderMouseOverCairo(OrthancStone::CairoContext& context, - int x, - int y) = 0; - - public: - CairoWidget(const std::string& name); - - virtual void SetSize(unsigned int width, - unsigned int height); - - virtual bool Render(Orthanc::ImageAccessor& target); - - virtual void RenderMouseOver(Orthanc::ImageAccessor& target, - int x, - int y); - }; -}
--- a/OrthancStone/Sources/Deprecated/Widgets/EmptyWidget.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "EmptyWidget.h" - -#include <Images/ImageProcessing.h> -#include <OrthancException.h> - -namespace Deprecated -{ - bool EmptyWidget::Render(Orthanc::ImageAccessor& surface) - { - // Note: This call is slow - Orthanc::ImageProcessing::Set(surface, red_, green_, blue_, 255); - return true; - } - - - void EmptyWidget::DoAnimation() - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } -}
--- a/OrthancStone/Sources/Deprecated/Widgets/EmptyWidget.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "IWidget.h" - -namespace Deprecated -{ - /** - * This is a test widget that simply fills its surface with an - * uniform color. - **/ - class EmptyWidget : public IWidget - { - private: - uint8_t red_; - uint8_t green_; - uint8_t blue_; - - public: - EmptyWidget(uint8_t red, - uint8_t green, - uint8_t blue) : - red_(red), - green_(green), - blue_(blue) - { - } - - virtual void FitContent() - { - } - - virtual void SetParent(IWidget& widget) - { - } - - virtual void SetViewport(WidgetViewport& viewport) - { - } - - virtual void NotifyContentChanged() - { - } - - virtual void SetStatusBar(IStatusBar& statusBar) - { - } - - virtual void SetSize(unsigned int width, - unsigned int height) - { - } - - virtual bool Render(Orthanc::ImageAccessor& surface); - - virtual IMouseTracker* CreateMouseTracker(OrthancStone::MouseButton button, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers, - const std::vector<Touch>& touches) - { - return NULL; - } - - virtual void RenderMouseOver(Orthanc::ImageAccessor& target, - int x, - int y) - { - } - - virtual void MouseWheel(OrthancStone::MouseWheelDirection direction, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers) - { - } - - virtual void KeyPressed(OrthancStone::KeyboardKeys key, - char keyChar, - OrthancStone::KeyboardModifiers modifiers) - { - } - - virtual bool HasAnimation() const - { - return false; - } - - virtual void DoAnimation(); - - virtual bool HasRenderMouseOver() - { - return false; - } - }; -}
--- a/OrthancStone/Sources/Deprecated/Widgets/IWidget.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../StoneEnumerations.h" -#include "../Viewport/IMouseTracker.h" -#include "../Viewport/IStatusBar.h" - -namespace Deprecated -{ - class WidgetViewport; // Forward declaration - - class IWidget : public boost::noncopyable - { - public: - virtual ~IWidget() - { - } - - virtual void FitContent() = 0; - - virtual void SetParent(IWidget& parent) = 0; - - virtual void SetViewport(WidgetViewport& viewport) = 0; - - virtual void SetStatusBar(IStatusBar& statusBar) = 0; - - virtual void SetSize(unsigned int width, - unsigned int height) = 0; - - virtual bool Render(Orthanc::ImageAccessor& surface) = 0; - - virtual IMouseTracker* CreateMouseTracker(OrthancStone::MouseButton button, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers, - const std::vector<Touch>& touches) = 0; - - virtual void RenderMouseOver(Orthanc::ImageAccessor& target, - int x, - int y) = 0; - - virtual bool HasRenderMouseOver() = 0; - - virtual void MouseWheel(OrthancStone::MouseWheelDirection direction, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers) = 0; - - virtual void KeyPressed(OrthancStone::KeyboardKeys key, - char keyChar, - OrthancStone::KeyboardModifiers modifiers) = 0; - - virtual bool HasAnimation() const = 0; - - virtual void DoAnimation() = 0; - - // Subclasses can call this method to signal the display of the - // widget must be refreshed - virtual void NotifyContentChanged() = 0; - }; -}
--- a/OrthancStone/Sources/Deprecated/Widgets/IWorldSceneInteractor.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "IWorldSceneMouseTracker.h" - -#include "../Toolbox/ViewportGeometry.h" -#include "../../StoneEnumerations.h" -#include "../Viewport/IStatusBar.h" - -namespace Deprecated -{ - class WorldSceneWidget; - - class IWorldSceneInteractor : public boost::noncopyable - { - public: - virtual ~IWorldSceneInteractor() - { - } - - virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, - const ViewportGeometry& view, - OrthancStone::MouseButton button, - OrthancStone::KeyboardModifiers modifiers, - int viewportX, - int viewportY, - double x, - double y, - IStatusBar* statusBar, - const std::vector<Touch>& touches) = 0; - - virtual void MouseOver(OrthancStone::CairoContext& context, - WorldSceneWidget& widget, - const ViewportGeometry& view, - double x, - double y, - IStatusBar* statusBar) = 0; - - virtual void MouseWheel(WorldSceneWidget& widget, - OrthancStone::MouseWheelDirection direction, - OrthancStone::KeyboardModifiers modifiers, - IStatusBar* statusBar) = 0; - - virtual void KeyPressed(WorldSceneWidget& widget, - OrthancStone::KeyboardKeys key, - char keyChar, - OrthancStone::KeyboardModifiers modifiers, - IStatusBar* statusBar) = 0; - }; -}
--- a/OrthancStone/Sources/Deprecated/Widgets/IWorldSceneMouseTracker.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "../../Wrappers/CairoContext.h" -#include "../Viewport/IMouseTracker.h" // only to get the "Touch" definition - -namespace Deprecated -{ - - // this is tracking a mouse in scene coordinates/mm unlike - // the IMouseTracker that is tracking a mouse - // in screen coordinates/pixels. - class IWorldSceneMouseTracker : public boost::noncopyable - { - public: - virtual ~IWorldSceneMouseTracker() - { - } - - virtual bool HasRender() const = 0; - - virtual void Render(OrthancStone::CairoContext& context, - double zoom) = 0; - - virtual void MouseUp() = 0; - - virtual void MouseMove(int displayX, - int displayY, - double sceneX, - double sceneY, - const std::vector<Touch>& displayTouches, - const std::vector<Touch>& sceneTouches) = 0; - }; -}
--- a/OrthancStone/Sources/Deprecated/Widgets/LayoutWidget.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,501 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "LayoutWidget.h" - -#include <Logging.h> -#include <OrthancException.h> - -#include <boost/math/special_functions/round.hpp> - -namespace Deprecated -{ - class LayoutWidget::LayoutMouseTracker : public IMouseTracker - { - private: - std::unique_ptr<IMouseTracker> tracker_; - int left_; - int top_; - unsigned int width_; - unsigned int height_; - - public: - LayoutMouseTracker(IMouseTracker* tracker, - int left, - int top, - unsigned int width, - unsigned int height) : - tracker_(tracker), - left_(left), - top_(top), - width_(width), - height_(height) - { - if (tracker == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - } - - virtual void Render(Orthanc::ImageAccessor& surface) - { - Orthanc::ImageAccessor accessor; - surface.GetRegion(accessor, left_, top_, width_, height_); - tracker_->Render(accessor); - } - - virtual void MouseUp() - { - tracker_->MouseUp(); - } - - virtual void MouseMove(int x, - int y, - const std::vector<Touch>& displayTouches) - { - std::vector<Touch> relativeTouches; - for (size_t t = 0; t < displayTouches.size(); t++) - { - relativeTouches.push_back(Touch(displayTouches[t].x - left_, displayTouches[t].y - top_)); - } - - tracker_->MouseMove(x - left_, y - top_, relativeTouches); - } - }; - - - class LayoutWidget::ChildWidget : public boost::noncopyable - { - private: - boost::shared_ptr<IWidget> widget_; - int left_; - int top_; - unsigned int width_; - unsigned int height_; - - public: - ChildWidget(boost::shared_ptr<IWidget> widget) : - widget_(widget) - { - assert(widget != NULL); - SetEmpty(); - } - - void DoAnimation() - { - if (widget_->HasAnimation()) - { - widget_->DoAnimation(); - } - } - - IWidget& GetWidget() const - { - return *widget_; - } - - void SetRectangle(unsigned int left, - unsigned int top, - unsigned int width, - unsigned int height) - { - left_ = left; - top_ = top; - width_ = width; - height_ = height; - - widget_->SetSize(width, height); - } - - void SetEmpty() - { - SetRectangle(0, 0, 0, 0); - } - - bool Contains(int x, - int y) const - { - return (x >= left_ && - y >= top_ && - x < left_ + static_cast<int>(width_) && - y < top_ + static_cast<int>(height_)); - } - - bool Render(Orthanc::ImageAccessor& target) - { - if (width_ == 0 || - height_ == 0) - { - return true; - } - else - { - Orthanc::ImageAccessor accessor; - target.GetRegion(accessor, left_, top_, width_, height_); - return widget_->Render(accessor); - } - } - - IMouseTracker* CreateMouseTracker(OrthancStone::MouseButton button, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers, - const std::vector<Touch>& touches) - { - if (Contains(x, y)) - { - IMouseTracker* tracker = widget_->CreateMouseTracker(button, - x - left_, - y - top_, - modifiers, - touches); - if (tracker) - { - return new LayoutMouseTracker(tracker, left_, top_, width_, height_); - } - } - - return NULL; - } - - void RenderMouseOver(Orthanc::ImageAccessor& target, - int x, - int y) - { - if (Contains(x, y)) - { - Orthanc::ImageAccessor accessor; - target.GetRegion(accessor, left_, top_, width_, height_); - - widget_->RenderMouseOver(accessor, x - left_, y - top_); - } - } - - void MouseWheel(OrthancStone::MouseWheelDirection direction, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers) - { - if (Contains(x, y)) - { - widget_->MouseWheel(direction, x - left_, y - top_, modifiers); - } - } - - bool HasRenderMouseOver() - { - return widget_->HasRenderMouseOver(); - } - }; - - - void LayoutWidget::ComputeChildrenExtents() - { - if (children_.size() == 0) - { - return; - } - - float internal = static_cast<float>(paddingInternal_); - - if (width_ <= paddingLeft_ + paddingRight_ || - height_ <= paddingTop_ + paddingBottom_) - { - for (size_t i = 0; i < children_.size(); i++) - { - children_[i]->SetEmpty(); - } - } - else if (isHorizontal_) - { - unsigned int padding = paddingLeft_ + paddingRight_ + (static_cast<unsigned int>(children_.size()) - 1) * paddingInternal_; - float childWidth = ((static_cast<float>(width_) - static_cast<float>(padding)) / - static_cast<float>(children_.size())); - - for (size_t i = 0; i < children_.size(); i++) - { - float left = static_cast<float>(paddingLeft_) + static_cast<float>(i) * (childWidth + internal); - float right = left + childWidth; - - if (left >= right) - { - children_[i]->SetEmpty(); - } - else - { - children_[i]->SetRectangle(static_cast<unsigned int>(left), - paddingTop_, - boost::math::iround(right - left), - height_ - paddingTop_ - paddingBottom_); - } - } - } - else - { - unsigned int padding = paddingTop_ + paddingBottom_ + (static_cast<unsigned int>(children_.size()) - 1) * paddingInternal_; - float childHeight = ((static_cast<float>(height_) - static_cast<float>(padding)) / - static_cast<float>(children_.size())); - - for (size_t i = 0; i < children_.size(); i++) - { - float top = static_cast<float>(paddingTop_) + static_cast<float>(i) * (childHeight + internal); - float bottom = top + childHeight; - - if (top >= bottom) - { - children_[i]->SetEmpty(); - } - else - { - children_[i]->SetRectangle(paddingTop_, - static_cast<unsigned int>(top), - width_ - paddingLeft_ - paddingRight_, - boost::math::iround(bottom - top)); - } - } - } - - NotifyContentChanged(*this); - } - - - LayoutWidget::LayoutWidget(const std::string& name) : - WidgetBase(name), - isHorizontal_(true), - width_(0), - height_(0), - paddingLeft_(0), - paddingTop_(0), - paddingRight_(0), - paddingBottom_(0), - paddingInternal_(0) - { - } - - - LayoutWidget::~LayoutWidget() - { - for (size_t i = 0; i < children_.size(); i++) - { - delete children_[i]; - } - } - - - void LayoutWidget::FitContent() - { - for (size_t i = 0; i < children_.size(); i++) - { - children_[i]->GetWidget().FitContent(); - } - } - - - void LayoutWidget::NotifyContentChanged(const IWidget& widget) - { - // One of the children has changed - WidgetBase::NotifyContentChanged(); - } - - - void LayoutWidget::SetHorizontal() - { - isHorizontal_ = true; - ComputeChildrenExtents(); - } - - - void LayoutWidget::SetVertical() - { - isHorizontal_ = false; - ComputeChildrenExtents(); - } - - - void LayoutWidget::SetPadding(unsigned int left, - unsigned int top, - unsigned int right, - unsigned int bottom, - unsigned int spacing) - { - paddingLeft_ = left; - paddingTop_ = top; - paddingRight_ = right; - paddingBottom_ = bottom; - paddingInternal_ = spacing; - } - - - void LayoutWidget::SetPadding(unsigned int padding) - { - paddingLeft_ = padding; - paddingTop_ = padding; - paddingRight_ = padding; - paddingBottom_ = padding; - paddingInternal_ = padding; - } - - - void LayoutWidget::AddWidget(boost::shared_ptr<IWidget> widget) // Takes ownership - { - if (widget == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - if (GetStatusBar() != NULL) - { - widget->SetStatusBar(*GetStatusBar()); - } - - children_.push_back(new ChildWidget(widget)); - widget->SetParent(*this); - - ComputeChildrenExtents(); - - if (widget->HasAnimation()) - { - hasAnimation_ = true; - } - } - - - void LayoutWidget::SetStatusBar(IStatusBar& statusBar) - { - WidgetBase::SetStatusBar(statusBar); - - for (size_t i = 0; i < children_.size(); i++) - { - children_[i]->GetWidget().SetStatusBar(statusBar); - } - } - - - void LayoutWidget::SetSize(unsigned int width, - unsigned int height) - { - width_ = width; - height_ = height; - ComputeChildrenExtents(); - } - - - bool LayoutWidget::Render(Orthanc::ImageAccessor& surface) - { - if (!WidgetBase::Render(surface)) - { - return false; - } - - for (size_t i = 0; i < children_.size(); i++) - { - if (!children_[i]->Render(surface)) - { - return false; - } - } - - return true; - } - - - IMouseTracker* LayoutWidget::CreateMouseTracker(OrthancStone::MouseButton button, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers, - const std::vector<Touch>& touches) - { - for (size_t i = 0; i < children_.size(); i++) - { - IMouseTracker* tracker = children_[i]->CreateMouseTracker(button, x, y, modifiers, touches); - if (tracker != NULL) - { - return tracker; - } - } - - return NULL; - } - - - void LayoutWidget::RenderMouseOver(Orthanc::ImageAccessor& target, - int x, - int y) - { - for (size_t i = 0; i < children_.size(); i++) - { - children_[i]->RenderMouseOver(target, x, y); - } - } - - - void LayoutWidget::MouseWheel(OrthancStone::MouseWheelDirection direction, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers) - { - for (size_t i = 0; i < children_.size(); i++) - { - children_[i]->MouseWheel(direction, x, y, modifiers); - } - } - - - void LayoutWidget::KeyPressed(OrthancStone::KeyboardKeys key, - char keyChar, - OrthancStone::KeyboardModifiers modifiers) - { - for (size_t i = 0; i < children_.size(); i++) - { - children_[i]->GetWidget().KeyPressed(key, keyChar, modifiers); - } - } - - - void LayoutWidget::DoAnimation() - { - if (hasAnimation_) - { - for (size_t i = 0; i < children_.size(); i++) - { - children_[i]->DoAnimation(); - } - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - } - - - bool LayoutWidget::HasRenderMouseOver() - { - for (size_t i = 0; i < children_.size(); i++) - { - if (children_[i]->HasRenderMouseOver()) - { - return true; - } - } - - return false; - } -}
--- a/OrthancStone/Sources/Deprecated/Widgets/LayoutWidget.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "WidgetBase.h" - -#include <vector> -#include <memory> - -namespace Deprecated -{ - class LayoutWidget : public WidgetBase - { - private: - class LayoutMouseTracker; - class ChildWidget; - - std::vector<ChildWidget*> children_; - bool isHorizontal_; - unsigned int width_; - unsigned int height_; - std::unique_ptr<IMouseTracker> mouseTracker_; - unsigned int paddingLeft_; - unsigned int paddingTop_; - unsigned int paddingRight_; - unsigned int paddingBottom_; - unsigned int paddingInternal_; - bool hasAnimation_; - - void ComputeChildrenExtents(); - - public: - LayoutWidget(const std::string& name); - - virtual ~LayoutWidget(); - - virtual void FitContent(); - - virtual void NotifyContentChanged(const IWidget& widget); - - void SetHorizontal(); - - void SetVertical(); - - void SetPadding(unsigned int left, - unsigned int top, - unsigned int right, - unsigned int bottom, - unsigned int spacing); - - void SetPadding(unsigned int padding); - - unsigned int GetPaddingLeft() const - { - return paddingLeft_; - } - - unsigned int GetPaddingTop() const - { - return paddingTop_; - } - - unsigned int GetPaddingRight() const - { - return paddingRight_; - } - - unsigned int GetPaddingBottom() const - { - return paddingBottom_; - } - - unsigned int GetPaddingInternal() const - { - return paddingInternal_; - } - - void AddWidget(boost::shared_ptr<IWidget> widget); - - virtual void SetStatusBar(IStatusBar& statusBar); - - virtual void SetSize(unsigned int width, - unsigned int height); - - virtual bool Render(Orthanc::ImageAccessor& surface); - - virtual IMouseTracker* CreateMouseTracker(OrthancStone::MouseButton button, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers, - const std::vector<Touch>& touches); - - virtual void RenderMouseOver(Orthanc::ImageAccessor& target, - int x, - int y); - - virtual void MouseWheel(OrthancStone::MouseWheelDirection direction, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers); - - virtual void KeyPressed(OrthancStone::KeyboardKeys key, - char keyChar, - OrthancStone::KeyboardModifiers modifiers); - - virtual bool HasAnimation() const - { - return hasAnimation_; - } - - virtual void DoAnimation(); - - virtual bool HasRenderMouseOver(); - }; -}
--- a/OrthancStone/Sources/Deprecated/Widgets/PanMouseTracker.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "PanMouseTracker.h" - -#include <Logging.h> -#include <OrthancException.h> - -namespace Deprecated -{ - PanMouseTracker::PanMouseTracker(WorldSceneWidget& that, - int x, - int y) : - that_(that) - { - that.GetView().GetPan(originalPanX_, originalPanY_); - that.GetView().MapPixelCenterToScene(downX_, downY_, x, y); - } - - - void PanMouseTracker::Render(OrthancStone::CairoContext& context, - double zoom) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - - - void PanMouseTracker::MouseMove(int displayX, - int displayY, - double x, - double y, - const std::vector<Touch>& displayTouches, - const std::vector<Touch>& sceneTouches) - { - ViewportGeometry view = that_.GetView(); - view.SetPan(originalPanX_ + (x - downX_) * view.GetZoom(), - originalPanY_ + (y - downY_) * view.GetZoom()); - that_.SetView(view); - } -}
--- a/OrthancStone/Sources/Deprecated/Widgets/PanMouseTracker.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "WorldSceneWidget.h" - -namespace Deprecated -{ - class PanMouseTracker : public IWorldSceneMouseTracker - { - private: - WorldSceneWidget& that_; - double originalPanX_; - double originalPanY_; - double downX_; - double downY_; - - public: - PanMouseTracker(WorldSceneWidget& that, - int x, - int y); - - virtual bool HasRender() const - { - return false; - } - - virtual void MouseUp() - { - } - - virtual void Render(OrthancStone::CairoContext& context, - double zoom); - - virtual void MouseMove(int displayX, - int displayY, - double x, - double y, - const std::vector<Touch>& displayTouches, - const std::vector<Touch>& sceneTouches); - }; -}
--- a/OrthancStone/Sources/Deprecated/Widgets/PanZoomMouseTracker.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,137 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "PanZoomMouseTracker.h" - -#include <Logging.h> -#include <OrthancException.h> -#include <math.h> - -namespace Deprecated -{ - Touch GetCenter(const std::vector<Touch>& touches) - { - return Touch((touches[0].x + touches[1].x) / 2.0f, (touches[0].y + touches[1].y) / 2.0f); - } - - double GetDistance(const std::vector<Touch>& touches) - { - float dx = touches[0].x - touches[1].x; - float dy = touches[0].y - touches[1].y; - return sqrt((double)(dx * dx) + (double)(dy * dy)); - } - - - PanZoomMouseTracker::PanZoomMouseTracker(WorldSceneWidget& that, - const std::vector<Touch>& startTouches) - : that_(that), - originalZoom_(that.GetView().GetZoom()) - { - that.GetView().GetPan(originalPanX_, originalPanY_); - that.GetView().MapPixelCenterToScene(originalSceneTouches_, startTouches); - - originalDisplayCenter_ = GetCenter(startTouches); - originalSceneCenter_ = GetCenter(originalSceneTouches_); - originalDisplayDistanceBetweenTouches_ = GetDistance(startTouches); - -// printf("original Pan %f %f\n", originalPanX_, originalPanY_); -// printf("original Zoom %f \n", originalZoom_); -// printf("original distance %f \n", (float)originalDisplayDistanceBetweenTouches_); -// printf("original display touches 0 %f %f\n", startTouches[0].x, startTouches[0].y); -// printf("original display touches 1 %f %f\n", startTouches[1].x, startTouches[1].y); -// printf("original Scene center %f %f\n", originalSceneCenter_.x, originalSceneCenter_.y); - - unsigned int height = that.GetView().GetDisplayHeight(); - - if (height <= 3) - { - idle_ = true; - LOG(WARNING) << "image is too small to zoom (current height = " << height << ")"; - } - else - { - idle_ = false; - normalization_ = 1.0 / static_cast<double>(height - 1); - } - - } - - - void PanZoomMouseTracker::Render(OrthancStone::CairoContext& context, - double zoom) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - - - void PanZoomMouseTracker::MouseMove(int displayX, - int displayY, - double x, - double y, - const std::vector<Touch>& displayTouches, - const std::vector<Touch>& sceneTouches) - { - ViewportGeometry view = that_.GetView(); - -// printf("Display touches 0 %f %f\n", displayTouches[0].x, displayTouches[0].y); -// printf("Display touches 1 %f %f\n", displayTouches[1].x, displayTouches[1].y); -// printf("Scene touches 0 %f %f\n", sceneTouches[0].x, sceneTouches[0].y); -// printf("Scene touches 1 %f %f\n", sceneTouches[1].x, sceneTouches[1].y); - -// printf("zoom = %f\n", view.GetZoom()); - Touch currentSceneCenter = GetCenter(sceneTouches); - double panX = originalPanX_ + (currentSceneCenter.x - originalSceneCenter_.x) * view.GetZoom(); - double panY = originalPanY_ + (currentSceneCenter.y - originalSceneCenter_.y) * view.GetZoom(); - - view.SetPan(panX, panY); - - static const double MIN_ZOOM = -4; - static const double MAX_ZOOM = 4; - - if (!idle_) - { - double currentDistanceBetweenTouches = GetDistance(displayTouches); - - double dy = static_cast<double>(currentDistanceBetweenTouches - originalDisplayDistanceBetweenTouches_) * normalization_; // In the range [-1,1] - double z; - - // Linear interpolation from [-1, 1] to [MIN_ZOOM, MAX_ZOOM] - if (dy < -1.0) - { - z = MIN_ZOOM; - } - else if (dy > 1.0) - { - z = MAX_ZOOM; - } - else - { - z = MIN_ZOOM + (MAX_ZOOM - MIN_ZOOM) * (dy + 1.0) / 2.0; - } - - z = pow(2.0, z); - - view.SetZoom(z * originalZoom_); - } - - that_.SetView(view); - } -}
--- a/OrthancStone/Sources/Deprecated/Widgets/PanZoomMouseTracker.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "WorldSceneWidget.h" - -namespace Deprecated -{ - class PanZoomMouseTracker : public IWorldSceneMouseTracker - { - private: - WorldSceneWidget& that_; - std::vector<Touch> originalSceneTouches_; - Touch originalSceneCenter_; - Touch originalDisplayCenter_; - double originalPanX_; - double originalPanY_; - double originalZoom_; - double originalDisplayDistanceBetweenTouches_; - bool idle_; - double normalization_; - - public: - PanZoomMouseTracker(WorldSceneWidget& that, - const std::vector<Touch>& startTouches); - - virtual bool HasRender() const - { - return false; - } - - virtual void MouseUp() - { - } - - virtual void Render(OrthancStone::CairoContext& context, - double zoom); - - virtual void MouseMove(int displayX, - int displayY, - double x, - double y, - const std::vector<Touch>& displayTouches, - const std::vector<Touch>& sceneTouches); - }; -}
--- a/OrthancStone/Sources/Deprecated/Widgets/SliceViewerWidget.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,616 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "SliceViewerWidget.h" - -#include "../Layers/SliceOutlineRenderer.h" -#include "../../Toolbox/GeometryToolbox.h" -#include "../Layers/FrameRenderer.h" - -#include <Logging.h> -#include <OrthancException.h> - -#include <boost/math/constants/constants.hpp> - - -static const double THIN_SLICE_THICKNESS = 100.0 * std::numeric_limits<double>::epsilon(); - -namespace Deprecated -{ - void SliceViewerWidget::Scene::DeleteLayer(size_t index) - { - if (index >= renderers_.size()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - assert(countMissing_ <= renderers_.size()); - - if (renderers_[index] != NULL) - { - assert(countMissing_ < renderers_.size()); - delete renderers_[index]; - renderers_[index] = NULL; - countMissing_++; - } - } - - - SliceViewerWidget::Scene::Scene(const OrthancStone::CoordinateSystem3D& plane, - double thickness, - size_t countLayers) : - plane_(plane), - thickness_(thickness), - countMissing_(countLayers), - renderers_(countLayers, NULL) - { - if (thickness <= 0) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - } - - - SliceViewerWidget::Scene::~Scene() - { - for (size_t i = 0; i < renderers_.size(); i++) - { - DeleteLayer(i); - } - } - - void SliceViewerWidget::Scene::SetLayer(size_t index, - ILayerRenderer* renderer) // Takes ownership - { - if (renderer == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); - } - - DeleteLayer(index); - - renderers_[index] = renderer; - countMissing_--; - } - - - bool SliceViewerWidget::Scene::RenderScene(OrthancStone::CairoContext& context, - const ViewportGeometry& view, - const OrthancStone::CoordinateSystem3D& viewportPlane) - { - bool fullQuality = true; - cairo_t *cr = context.GetObject(); - - for (size_t i = 0; i < renderers_.size(); i++) - { - if (renderers_[i] != NULL) - { - const OrthancStone::CoordinateSystem3D& framePlane = renderers_[i]->GetLayerPlane(); - - double x0, y0, x1, y1, x2, y2; - viewportPlane.ProjectPoint(x0, y0, framePlane.GetOrigin()); - viewportPlane.ProjectPoint(x1, y1, framePlane.GetOrigin() + framePlane.GetAxisX()); - viewportPlane.ProjectPoint(x2, y2, framePlane.GetOrigin() + framePlane.GetAxisY()); - - /** - * Now we solve the system of linear equations Ax + b = x', given: - * A [0 ; 0] + b = [x0 ; y0] - * A [1 ; 0] + b = [x1 ; y1] - * A [0 ; 1] + b = [x2 ; y2] - * <=> - * b = [x0 ; y0] - * A [1 ; 0] = [x1 ; y1] - b = [x1 - x0 ; y1 - y0] - * A [0 ; 1] = [x2 ; y2] - b = [x2 - x0 ; y2 - y0] - * <=> - * b = [x0 ; y0] - * [a11 ; a21] = [x1 - x0 ; y1 - y0] - * [a12 ; a22] = [x2 - x0 ; y2 - y0] - **/ - - cairo_matrix_t transform; - cairo_matrix_init(&transform, x1 - x0, y1 - y0, x2 - x0, y2 - y0, x0, y0); - - cairo_save(cr); - cairo_transform(cr, &transform); - - if (!renderers_[i]->RenderLayer(context, view)) - { - cairo_restore(cr); - return false; - } - - cairo_restore(cr); - } - - if (renderers_[i] != NULL && - !renderers_[i]->IsFullQuality()) - { - fullQuality = false; - } - } - - if (!fullQuality) - { - double x, y; - view.MapDisplayToScene(x, y, static_cast<double>(view.GetDisplayWidth()) / 2.0, 10); - - cairo_translate(cr, x, y); - -#if 1 - double s = 5.0 / view.GetZoom(); - cairo_rectangle(cr, -s, -s, 2.0 * s, 2.0 * s); -#else - // TODO Drawing filled circles makes WebAssembly crash! - cairo_arc(cr, 0, 0, 5.0 / view.GetZoom(), 0, 2.0 * boost::math::constants::pi<double>()); -#endif - - cairo_set_line_width(cr, 2.0 / view.GetZoom()); - cairo_set_source_rgb(cr, 1, 1, 1); - cairo_stroke_preserve(cr); - cairo_set_source_rgb(cr, 1, 0, 0); - cairo_fill(cr); - } - - return true; - } - - void SliceViewerWidget::Scene::SetLayerStyle(size_t index, - const RenderStyle& style) - { - if (renderers_[index] != NULL) - { - renderers_[index]->SetLayerStyle(style); - } - } - - bool SliceViewerWidget::Scene::ContainsPlane(const OrthancStone::CoordinateSystem3D& plane) const - { - bool isOpposite; - if (!OrthancStone::GeometryToolbox::IsParallelOrOpposite(isOpposite, - plane.GetNormal(), - plane_.GetNormal())) - { - return false; - } - else - { - double z = (plane_.ProjectAlongNormal(plane.GetOrigin()) - - plane_.ProjectAlongNormal(plane_.GetOrigin())); - - if (z < 0) - { - z = -z; - } - - return z <= thickness_; - } - } - - - bool SliceViewerWidget::LookupLayer(size_t& index /* out */, - const IVolumeSlicer& layer) const - { - LayersIndex::const_iterator found = layersIndex_.find(&layer); - - if (found == layersIndex_.end()) - { - return false; - } - else - { - index = found->second; - assert(index < layers_.size() && - layers_[index].get() == &layer); - return true; - } - } - - - void SliceViewerWidget::GetLayerExtent(OrthancStone::Extent2D& extent, - IVolumeSlicer& source) const - { - extent.Reset(); - - std::vector<OrthancStone::Vector> points; - if (source.GetExtent(points, plane_)) - { - for (size_t i = 0; i < points.size(); i++) - { - double x, y; - plane_.ProjectPoint(x, y, points[i]); - extent.AddPoint(x, y); - } - } - } - - - OrthancStone::Extent2D SliceViewerWidget::GetSceneExtent() - { - OrthancStone::Extent2D sceneExtent; - - for (size_t i = 0; i < layers_.size(); i++) - { - assert(layers_[i] != NULL); - OrthancStone::Extent2D layerExtent; - GetLayerExtent(layerExtent, *layers_[i]); - - sceneExtent.Union(layerExtent); - } - - return sceneExtent; - } - - - bool SliceViewerWidget::RenderScene(OrthancStone::CairoContext& context, - const ViewportGeometry& view) - { - if (currentScene_.get() != NULL) - { - return currentScene_->RenderScene(context, view, plane_); - } - else - { - return true; - } - } - - - void SliceViewerWidget::ResetPendingScene() - { - double thickness; - if (pendingScene_.get() == NULL) - { - thickness = 1.0; - } - else - { - thickness = pendingScene_->GetThickness(); - } - - pendingScene_.reset(new Scene(plane_, thickness, layers_.size())); - } - - - void SliceViewerWidget::UpdateLayer(size_t index, - ILayerRenderer* renderer, - const OrthancStone::CoordinateSystem3D& plane) - { - LOG(INFO) << "Updating layer " << index; - - std::unique_ptr<ILayerRenderer> tmp(renderer); - - if (renderer == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); - } - - if (index >= layers_.size()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - assert(layers_.size() == styles_.size()); - renderer->SetLayerStyle(styles_[index]); - - if (currentScene_.get() != NULL && - currentScene_->ContainsPlane(plane)) - { - currentScene_->SetLayer(index, tmp.release()); - NotifyContentChanged(); - } - else if (pendingScene_.get() != NULL && - pendingScene_->ContainsPlane(plane)) - { - pendingScene_->SetLayer(index, tmp.release()); - - if (currentScene_.get() == NULL || - !currentScene_->IsComplete() || - pendingScene_->IsComplete()) - { -#if __cplusplus < 201103L - currentScene_.reset(pendingScene_.release()); -#else - currentScene_ = std::move(pendingScene_); -#endif - - NotifyContentChanged(); - } - } - } - - - SliceViewerWidget::SliceViewerWidget(const std::string& name) : - WorldSceneWidget(name), - started_(false) - { - SetBackgroundCleared(true); - } - - - void SliceViewerWidget::ObserveLayer(IVolumeSlicer& layer) - { - // currently ignoring errors of type IVolumeSlicer::GeometryErrorMessage - - Register<IVolumeSlicer::GeometryReadyMessage>(layer, &SliceViewerWidget::OnGeometryReady); - Register<IVolumeSlicer::SliceContentChangedMessage>(layer, &SliceViewerWidget::OnSliceChanged); - Register<IVolumeSlicer::ContentChangedMessage>(layer, &SliceViewerWidget::OnContentChanged); - Register<IVolumeSlicer::LayerReadyMessage>(layer, &SliceViewerWidget::OnLayerReady); - Register<IVolumeSlicer::LayerErrorMessage>(layer, &SliceViewerWidget::OnLayerError); - } - - - size_t SliceViewerWidget::AddLayer(boost::shared_ptr<IVolumeSlicer> layer) - { - if (layer == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); - } - - size_t index = layers_.size(); - layers_.push_back(layer); - styles_.push_back(RenderStyle()); - layersIndex_[layer.get()] = index; - - ResetPendingScene(); - - ObserveLayer(*layer); - - ResetChangedLayers(); - - return index; - } - - - void SliceViewerWidget::ReplaceLayer(size_t index, - boost::shared_ptr<IVolumeSlicer> layer) - { - if (layer == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); - } - - if (index >= layers_.size()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - layers_[index] = layer; - layersIndex_[layer.get()] = index; - - ResetPendingScene(); - - ObserveLayer(*layer); - - InvalidateLayer(index); - } - - - void SliceViewerWidget::RemoveLayer(size_t index) - { - if (index >= layers_.size()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - IVolumeSlicer* previousLayer = layers_[index].get(); - layersIndex_.erase(layersIndex_.find(previousLayer)); - layers_.erase(layers_.begin() + index); - changedLayers_.erase(changedLayers_.begin() + index); - styles_.erase(styles_.begin() + index); - - layers_[index].reset(); - - currentScene_->DeleteLayer(index); - ResetPendingScene(); - - NotifyContentChanged(); - } - - - const RenderStyle& SliceViewerWidget::GetLayerStyle(size_t layer) const - { - if (layer >= layers_.size()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - assert(layers_.size() == styles_.size()); - return styles_[layer]; - } - - - void SliceViewerWidget::SetLayerStyle(size_t layer, - const RenderStyle& style) - { - if (layer >= layers_.size()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - assert(layers_.size() == styles_.size()); - styles_[layer] = style; - - if (currentScene_.get() != NULL) - { - currentScene_->SetLayerStyle(layer, style); - } - - if (pendingScene_.get() != NULL) - { - pendingScene_->SetLayerStyle(layer, style); - } - - NotifyContentChanged(); - } - - - void SliceViewerWidget::SetSlice(const OrthancStone::CoordinateSystem3D& plane) - { - LOG(INFO) << "Setting slice origin: (" << plane.GetOrigin()[0] - << "," << plane.GetOrigin()[1] - << "," << plane.GetOrigin()[2] << ")"; - - Deprecated::Slice displayedSlice(plane_, THIN_SLICE_THICKNESS); - - //if (!displayedSlice.ContainsPlane(slice)) - { - if (currentScene_.get() == NULL || - (pendingScene_.get() != NULL && - pendingScene_->IsComplete())) - { -#if __cplusplus < 201103L - currentScene_.reset(pendingScene_.release()); -#else - currentScene_ = std::move(pendingScene_); -#endif - } - - plane_ = plane; - ResetPendingScene(); - - InvalidateAllLayers(); // TODO Removing this line avoid loading twice the image in WASM - } - - BroadcastMessage(DisplayedSliceMessage(*this, displayedSlice)); - } - - - void SliceViewerWidget::OnGeometryReady(const IVolumeSlicer::GeometryReadyMessage& message) - { - size_t i; - if (LookupLayer(i, message.GetOrigin())) - { - LOG(INFO) << ": Geometry ready for layer " << i << " in " << GetName(); - - changedLayers_[i] = true; - //layers_[i]->ScheduleLayerCreation(plane_); - } - BroadcastMessage(GeometryChangedMessage(*this)); - } - - - void SliceViewerWidget::InvalidateAllLayers() - { - for (size_t i = 0; i < layers_.size(); i++) - { - assert(layers_[i] != NULL); - changedLayers_[i] = true; - - //layers_[i]->ScheduleLayerCreation(plane_); - } - } - - - void SliceViewerWidget::InvalidateLayer(size_t layer) - { - if (layer >= layers_.size()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - assert(layers_[layer] != NULL); - changedLayers_[layer] = true; - - //layers_[layer]->ScheduleLayerCreation(plane_); - } - - - void SliceViewerWidget::OnContentChanged(const IVolumeSlicer::ContentChangedMessage& message) - { - size_t index; - if (LookupLayer(index, message.GetOrigin())) - { - InvalidateLayer(index); - } - - BroadcastMessage(SliceViewerWidget::ContentChangedMessage(*this)); - } - - - void SliceViewerWidget::OnSliceChanged(const IVolumeSlicer::SliceContentChangedMessage& message) - { - if (message.GetSlice().ContainsPlane(plane_)) - { - size_t index; - if (LookupLayer(index, message.GetOrigin())) - { - InvalidateLayer(index); - } - } - - BroadcastMessage(SliceViewerWidget::ContentChangedMessage(*this)); - } - - - void SliceViewerWidget::OnLayerReady(const IVolumeSlicer::LayerReadyMessage& message) - { - size_t index; - if (LookupLayer(index, message.GetOrigin())) - { - LOG(INFO) << "Renderer ready for layer " << index; - UpdateLayer(index, message.CreateRenderer(), message.GetSlice()); - } - - BroadcastMessage(SliceViewerWidget::ContentChangedMessage(*this)); - } - - - void SliceViewerWidget::OnLayerError(const IVolumeSlicer::LayerErrorMessage& message) - { - size_t index; - if (LookupLayer(index, message.GetOrigin())) - { - LOG(ERROR) << "Using error renderer on layer " << index; - - // TODO - //UpdateLayer(index, new SliceOutlineRenderer(slice), slice); - - BroadcastMessage(SliceViewerWidget::ContentChangedMessage(*this)); - } - } - - - void SliceViewerWidget::ResetChangedLayers() - { - changedLayers_.resize(layers_.size()); - - for (size_t i = 0; i < changedLayers_.size(); i++) - { - changedLayers_[i] = false; - } - } - - - void SliceViewerWidget::DoAnimation() - { - assert(changedLayers_.size() <= layers_.size()); - - for (size_t i = 0; i < changedLayers_.size(); i++) - { - if (changedLayers_[i]) - { - layers_[i]->ScheduleLayerCreation(plane_); - } - } - - ResetChangedLayers(); - } -}
--- a/OrthancStone/Sources/Deprecated/Widgets/SliceViewerWidget.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,210 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "WorldSceneWidget.h" -#include "../Layers/IVolumeSlicer.h" -#include "../../Toolbox/Extent2D.h" -#include "../../Messages/ObserverBase.h" - -#include <map> - -namespace Deprecated -{ - class SliceViewerWidget : - public WorldSceneWidget, - public OrthancStone::ObserverBase<SliceViewerWidget>, - public OrthancStone::IObservable - { - public: - ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, GeometryChangedMessage, SliceViewerWidget); - ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, ContentChangedMessage, SliceViewerWidget); - - - // TODO - Use this message in ReferenceLineSource - class DisplayedSliceMessage : public OrthancStone::OriginMessage<SliceViewerWidget> - { - ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); - - private: - const Deprecated::Slice& slice_; - - public: - DisplayedSliceMessage(SliceViewerWidget& origin, - const Deprecated::Slice& slice) : - OriginMessage(origin), - slice_(slice) - { - } - - const Deprecated::Slice& GetSlice() const - { - return slice_; - } - }; - - private: - SliceViewerWidget(const SliceViewerWidget&); - SliceViewerWidget& operator=(const SliceViewerWidget&); - - class Scene : public boost::noncopyable - { - private: - OrthancStone::CoordinateSystem3D plane_; - double thickness_; - size_t countMissing_; - std::vector<ILayerRenderer*> renderers_; - - public: - void DeleteLayer(size_t index); - - Scene(const OrthancStone::CoordinateSystem3D& plane, - double thickness, - size_t countLayers); - - ~Scene(); - - void SetLayer(size_t index, - ILayerRenderer* renderer); // Takes ownership - - const OrthancStone::CoordinateSystem3D& GetPlane() const - { - return plane_; - } - - bool HasRenderer(size_t index) - { - return renderers_[index] != NULL; - } - - bool IsComplete() const - { - return countMissing_ == 0; - } - - unsigned int GetCountMissing() const - { - return static_cast<unsigned int>(countMissing_); - } - - bool RenderScene(OrthancStone::CairoContext& context, - const ViewportGeometry& view, - const OrthancStone::CoordinateSystem3D& viewportPlane); - - void SetLayerStyle(size_t index, - const RenderStyle& style); - - bool ContainsPlane(const OrthancStone::CoordinateSystem3D& plane) const; - - double GetThickness() const - { - return thickness_; - } - }; - - - typedef std::map<const IVolumeSlicer*, size_t> LayersIndex; - - bool started_; - LayersIndex layersIndex_; - std::vector<boost::shared_ptr<IVolumeSlicer> > layers_; - std::vector<RenderStyle> styles_; - OrthancStone::CoordinateSystem3D plane_; - std::unique_ptr<Scene> currentScene_; - std::unique_ptr<Scene> pendingScene_; - std::vector<bool> changedLayers_; - - bool LookupLayer(size_t& index /* out */, - const IVolumeSlicer& layer) const; - - void GetLayerExtent(OrthancStone::Extent2D& extent, - IVolumeSlicer& source) const; - - void OnGeometryReady(const IVolumeSlicer::GeometryReadyMessage& message); - - virtual void OnContentChanged(const IVolumeSlicer::ContentChangedMessage& message); - - virtual void OnSliceChanged(const IVolumeSlicer::SliceContentChangedMessage& message); - - virtual void OnLayerReady(const IVolumeSlicer::LayerReadyMessage& message); - - virtual void OnLayerError(const IVolumeSlicer::LayerErrorMessage& message); - - void ObserveLayer(IVolumeSlicer& source); - - void ResetChangedLayers(); - - public: - SliceViewerWidget(const std::string& name); - - virtual OrthancStone::Extent2D GetSceneExtent(); - - protected: - virtual bool RenderScene(OrthancStone::CairoContext& context, - const ViewportGeometry& view); - - void ResetPendingScene(); - - void UpdateLayer(size_t index, - ILayerRenderer* renderer, - const OrthancStone::CoordinateSystem3D& plane); - - void InvalidateAllLayers(); - - void InvalidateLayer(size_t layer); - - public: - virtual ~SliceViewerWidget() - { - } - - size_t AddLayer(boost::shared_ptr<IVolumeSlicer> layer); - - void ReplaceLayer(size_t layerIndex, boost::shared_ptr<IVolumeSlicer> layer); // Takes ownership - - void RemoveLayer(size_t layerIndex); - - size_t GetLayerCount() const - { - return layers_.size(); - } - - const RenderStyle& GetLayerStyle(size_t layer) const; - - void SetLayerStyle(size_t layer, - const RenderStyle& style); - - void SetSlice(const OrthancStone::CoordinateSystem3D& plane); - - const OrthancStone::CoordinateSystem3D& GetSlice() const - { - return plane_; - } - - virtual bool HasAnimation() const - { - return true; - } - - virtual void DoAnimation(); - }; -}
--- a/OrthancStone/Sources/Deprecated/Widgets/TestCairoWidget.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,126 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "TestCairoWidget.h" - -#include <stdio.h> - - -namespace Deprecated -{ - namespace Samples - { - void TestCairoWidget::DoAnimation() - { - value_ -= 0.01f; - if (value_ < 0) - { - value_ = 1; - } - - NotifyContentChanged(); - } - - - bool TestCairoWidget::RenderCairo(OrthancStone::CairoContext& context) - { - cairo_t* cr = context.GetObject(); - - cairo_set_source_rgb (cr, .3, 0, 0); - cairo_paint(cr); - - cairo_set_source_rgb(cr, 0, 1, 0); - cairo_rectangle(cr, width_ / 4, height_ / 4, width_ / 2, height_ / 2); - cairo_set_line_width(cr, 1.0); - cairo_fill(cr); - - cairo_set_source_rgb(cr, 0, 1, value_); - cairo_rectangle(cr, width_ / 2 - 50, height_ / 2 - 50, 100, 100); - cairo_fill(cr); - - return true; - } - - - void TestCairoWidget::RenderMouseOverCairo(OrthancStone::CairoContext& context, - int x, - int y) - { - cairo_t* cr = context.GetObject(); - - cairo_set_source_rgb (cr, 1, 0, 0); - cairo_rectangle(cr, x - 5, y - 5, 10, 10); - cairo_set_line_width(cr, 1.0); - cairo_stroke(cr); - - char buf[64]; - sprintf(buf, "(%d,%d)", x, y); - UpdateStatusBar(buf); - } - - - TestCairoWidget::TestCairoWidget(const std::string& name, bool animate) : - CairoWidget(name), - width_(0), - height_(0), - value_(1), - animate_(animate) - { - } - - - void TestCairoWidget::SetSize(unsigned int width, - unsigned int height) - { - CairoWidget::SetSize(width, height); - width_ = width; - height_ = height; - } - - - IMouseTracker* TestCairoWidget::CreateMouseTracker(OrthancStone::MouseButton button, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers, - const std::vector<Touch>& touches) - { - UpdateStatusBar("Click"); - return NULL; - } - - - void TestCairoWidget::MouseWheel(OrthancStone::MouseWheelDirection direction, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers) - { - UpdateStatusBar(direction == OrthancStone::MouseWheelDirection_Down ? "Wheel down" : "Wheel up"); - } - - - void TestCairoWidget::KeyPressed(OrthancStone::KeyboardKeys key, - char keyChar, - OrthancStone::KeyboardModifiers modifiers) - { - UpdateStatusBar("Key pressed: \"" + std::string(1, keyChar) + "\""); - } - } -}
--- a/OrthancStone/Sources/Deprecated/Widgets/TestCairoWidget.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "CairoWidget.h" - -namespace Deprecated -{ - namespace Samples - { - class TestCairoWidget : public CairoWidget - { - private: - unsigned int width_; - unsigned int height_; - float value_; - bool animate_; - - protected: - virtual bool RenderCairo(OrthancStone::CairoContext& context); - - virtual void RenderMouseOverCairo(OrthancStone::CairoContext& context, - int x, - int y); - - public: - TestCairoWidget(const std::string& name, bool animate); - - virtual void SetSize(unsigned int width, - unsigned int height); - - virtual IMouseTracker* CreateMouseTracker(OrthancStone::MouseButton button, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers, - const std::vector<Touch>& touches); - - virtual void MouseWheel(OrthancStone::MouseWheelDirection direction, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers); - - virtual void KeyPressed(OrthancStone::KeyboardKeys key, - char keyChar, - OrthancStone::KeyboardModifiers modifiers); - - virtual bool HasAnimation() const - { - return animate_; - } - - virtual void DoAnimation(); - - virtual bool HasRenderMouseOver() - { - return true; - } - }; - } -}
--- a/OrthancStone/Sources/Deprecated/Widgets/TestWorldSceneWidget.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,149 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "TestWorldSceneWidget.h" - -#include <OrthancException.h> - -#include <math.h> -#include <stdio.h> - -namespace Deprecated -{ - namespace Samples - { - class TestWorldSceneWidget::Interactor : public IWorldSceneInteractor - { - public: - virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, - const ViewportGeometry& view, - OrthancStone::MouseButton button, - OrthancStone::KeyboardModifiers modifiers, - int viewportX, - int viewportY, - double x, - double y, - IStatusBar* statusBar, - const std::vector<Touch>& touches) - { - if (statusBar) - { - char buf[64]; - sprintf(buf, "X = %0.2f, Y = %0.2f", x, y); - statusBar->SetMessage(buf); - } - - return NULL; - } - - virtual void MouseOver(OrthancStone::CairoContext& context, - WorldSceneWidget& widget, - const ViewportGeometry& view, - double x, - double y, - IStatusBar* statusBar) - { - double S = 0.5; - - if (fabs(x) <= S && - fabs(y) <= S) - { - cairo_t* cr = context.GetObject(); - cairo_set_source_rgb(cr, 1, 0, 0); - cairo_rectangle(cr, -S, -S , 2.0 * S, 2.0 * S); - cairo_set_line_width(cr, 1.0 / view.GetZoom()); - cairo_stroke(cr); - } - } - - virtual void MouseWheel(WorldSceneWidget& widget, - OrthancStone::MouseWheelDirection direction, - OrthancStone::KeyboardModifiers modifiers, - IStatusBar* statusBar) - { - if (statusBar) - { - statusBar->SetMessage(direction == OrthancStone::MouseWheelDirection_Down ? "Wheel down" : "Wheel up"); - } - } - - virtual void KeyPressed(WorldSceneWidget& widget, - OrthancStone::KeyboardKeys key, - char keyChar, - OrthancStone::KeyboardModifiers modifiers, - IStatusBar* statusBar) - { - if (statusBar) - { - statusBar->SetMessage("Key pressed: \"" + std::string(1, keyChar) + "\""); - } - } - }; - - - bool TestWorldSceneWidget::RenderScene(OrthancStone::CairoContext& context, - const ViewportGeometry& view) - { - cairo_t* cr = context.GetObject(); - - // Clear background - cairo_set_source_rgb(cr, 0, 0, 0); - cairo_paint(cr); - - float color = static_cast<float>(count_ % 16) / 15.0f; - cairo_set_source_rgb(cr, 0, 1.0f - color, color); - cairo_rectangle(cr, -10, -.5, 20, 1); - cairo_fill(cr); - - return true; - } - - - TestWorldSceneWidget::TestWorldSceneWidget(const std::string& name, bool animate) : - WorldSceneWidget(name), - interactor_(new Interactor), - animate_(animate), - count_(0) - { - SetInteractor(*interactor_); - } - - - OrthancStone::Extent2D TestWorldSceneWidget::GetSceneExtent() - { - return OrthancStone::Extent2D(-10, -.5, 10, .5); - } - - - void TestWorldSceneWidget::DoAnimation() - { - if (animate_) - { - count_++; - NotifyContentChanged(); - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - } - } -}
--- a/OrthancStone/Sources/Deprecated/Widgets/TestWorldSceneWidget.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "WorldSceneWidget.h" - -#include <memory> - -namespace Deprecated -{ - namespace Samples - { - class TestWorldSceneWidget : public WorldSceneWidget - { - private: - class Interactor; - - std::unique_ptr<Interactor> interactor_; - bool animate_; - unsigned int count_; - - protected: - virtual bool RenderScene(OrthancStone::CairoContext& context, - const ViewportGeometry& view); - - public: - TestWorldSceneWidget(const std::string& name, bool animate); - - virtual OrthancStone::Extent2D GetSceneExtent(); - - virtual bool HasAnimation() const - { - return animate_; - } - - virtual void DoAnimation(); - - virtual bool HasRenderMouseOver() - { - return true; - } - }; - } -}
--- a/OrthancStone/Sources/Deprecated/Widgets/WidgetBase.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,166 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "WidgetBase.h" - -#include <OrthancException.h> -#include <Images/ImageProcessing.h> -#include <Logging.h> - -namespace Deprecated -{ - void WidgetBase::NotifyContentChanged() - { - if (parent_ != NULL) - { - parent_->NotifyContentChanged(); - } - - if (viewport_ != NULL) - { - viewport_->NotifyBackgroundChanged(); - } - } - - - void WidgetBase::SetParent(IWidget& parent) - { - if (parent_ != NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - else - { - parent_ = &parent; - } - } - - - void WidgetBase::ClearBackgroundOrthanc(Orthanc::ImageAccessor& target) const - { - // Clear the background using Orthanc - - if (backgroundCleared_) - { - Orthanc::ImageProcessing::Set(target, - backgroundColor_[0], - backgroundColor_[1], - backgroundColor_[2], - 255 /* alpha */); - } - } - - - void WidgetBase::ClearBackgroundCairo(OrthancStone::CairoContext& context) const - { - // Clear the background using Cairo - - if (IsBackgroundCleared()) - { - uint8_t red, green, blue; - GetBackgroundColor(red, green, blue); - - context.SetSourceColor(red, green, blue); - cairo_paint(context.GetObject()); - } - } - - - void WidgetBase::ClearBackgroundCairo(Orthanc::ImageAccessor& target) const - { - OrthancStone::CairoSurface surface(target, false /* no alpha */); - OrthancStone::CairoContext context(surface); - ClearBackgroundCairo(context); - } - - - void WidgetBase::UpdateStatusBar(const std::string& message) - { - if (statusBar_ != NULL) - { - statusBar_->SetMessage(message); - } - } - - - WidgetBase::WidgetBase(const std::string& name) : - parent_(NULL), - viewport_(NULL), - statusBar_(NULL), - backgroundCleared_(false), - transmitMouseOver_(false), - name_(name) - { - backgroundColor_[0] = 0; - backgroundColor_[1] = 0; - backgroundColor_[2] = 0; - } - - - void WidgetBase::SetViewport(WidgetViewport& viewport) - { - if (viewport_ != NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - else - { - viewport_ = &viewport; - } - } - - - void WidgetBase::SetBackgroundColor(uint8_t red, - uint8_t green, - uint8_t blue) - { - backgroundColor_[0] = red; - backgroundColor_[1] = green; - backgroundColor_[2] = blue; - } - - void WidgetBase::GetBackgroundColor(uint8_t& red, - uint8_t& green, - uint8_t& blue) const - { - red = backgroundColor_[0]; - green = backgroundColor_[1]; - blue = backgroundColor_[2]; - } - - - bool WidgetBase::Render(Orthanc::ImageAccessor& surface) - { -#if 0 - ClearBackgroundOrthanc(surface); -#else - ClearBackgroundCairo(surface); // Faster than Orthanc -#endif - - return true; - } - - - void WidgetBase::DoAnimation() - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } -}
--- a/OrthancStone/Sources/Deprecated/Widgets/WidgetBase.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "IWidget.h" - -#include "../../Wrappers/CairoContext.h" -#include "../Viewport/WidgetViewport.h" - -namespace Deprecated -{ - class WidgetBase : public IWidget - { - private: - IWidget* parent_; - WidgetViewport* viewport_; - IStatusBar* statusBar_; - bool backgroundCleared_; - uint8_t backgroundColor_[3]; - bool transmitMouseOver_; - std::string name_; - - protected: - void ClearBackgroundOrthanc(Orthanc::ImageAccessor& target) const; - - void ClearBackgroundCairo(OrthancStone::CairoContext& context) const; - - void ClearBackgroundCairo(Orthanc::ImageAccessor& target) const; - - void UpdateStatusBar(const std::string& message); - - IStatusBar* GetStatusBar() const - { - return statusBar_; - } - - public: - WidgetBase(const std::string& name); - - virtual void FitContent() - { - } - - virtual void SetParent(IWidget& parent); - - virtual void SetViewport(WidgetViewport& viewport); - - void SetBackgroundCleared(bool clear) - { - backgroundCleared_ = clear; - } - - bool IsBackgroundCleared() const - { - return backgroundCleared_; - } - - void SetTransmitMouseOver(bool transmit) - { - transmitMouseOver_ = transmit; - } - - void SetBackgroundColor(uint8_t red, - uint8_t green, - uint8_t blue); - - void GetBackgroundColor(uint8_t& red, - uint8_t& green, - uint8_t& blue) const; - - virtual void SetStatusBar(IStatusBar& statusBar) - { - statusBar_ = &statusBar; - } - - virtual bool Render(Orthanc::ImageAccessor& surface); - - virtual bool HasAnimation() const - { - return false; - } - - virtual void DoAnimation(); - - virtual bool HasRenderMouseOver() - { - return transmitMouseOver_; - } - - virtual void NotifyContentChanged(); - - const std::string& GetName() const - { - return name_; - } - - }; -}
--- a/OrthancStone/Sources/Deprecated/Widgets/WorldSceneWidget.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,229 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "WorldSceneWidget.h" - -#include "PanMouseTracker.h" -#include "ZoomMouseTracker.h" -#include "PanZoomMouseTracker.h" - -#include <Logging.h> -#include <OrthancException.h> - -#include <math.h> -#include <memory> -#include <cassert> - -namespace Deprecated -{ - // this is an adapter between a IWorldSceneMouseTracker - // that is tracking a mouse in scene coordinates/mm and - // an IMouseTracker that is tracking a mouse - // in screen coordinates/pixels. - class WorldSceneWidget::SceneMouseTracker : public IMouseTracker - { - private: - ViewportGeometry view_; - std::unique_ptr<IWorldSceneMouseTracker> tracker_; - - public: - SceneMouseTracker(const ViewportGeometry& view, - IWorldSceneMouseTracker* tracker) : - view_(view), - tracker_(tracker) - { - if (tracker == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); - } - } - - virtual void Render(Orthanc::ImageAccessor& target) - { - if (tracker_->HasRender()) - { - OrthancStone::CairoSurface surface(target, false /* no alpha */); - OrthancStone::CairoContext context(surface); - view_.ApplyTransform(context); - tracker_->Render(context, view_.GetZoom()); - } - } - - virtual void MouseUp() - { - tracker_->MouseUp(); - } - - virtual void MouseMove(int x, - int y, - const std::vector<Touch>& displayTouches) - { - double sceneX, sceneY; - view_.MapPixelCenterToScene(sceneX, sceneY, x, y); - - std::vector<Touch> sceneTouches; - for (size_t t = 0; t < displayTouches.size(); t++) - { - double sx, sy; - - view_.MapPixelCenterToScene( - sx, sy, (int)displayTouches[t].x, (int)displayTouches[t].y); - - sceneTouches.push_back( - Touch(static_cast<float>(sx), static_cast<float>(sy))); - } - tracker_->MouseMove(x, y, sceneX, sceneY, displayTouches, sceneTouches); - } - }; - - - bool WorldSceneWidget::RenderCairo(OrthancStone::CairoContext& context) - { - view_.ApplyTransform(context); - return RenderScene(context, view_); - } - - - void WorldSceneWidget::RenderMouseOverCairo(OrthancStone::CairoContext& context, - int x, - int y) - { - ViewportGeometry view = GetView(); - view.ApplyTransform(context); - - double sceneX, sceneY; - view.MapPixelCenterToScene(sceneX, sceneY, x, y); - - if (interactor_) - { - interactor_->MouseOver(context, *this, view, sceneX, sceneY, GetStatusBar()); - } - } - - - void WorldSceneWidget::SetSceneExtent(ViewportGeometry& view) - { - view.SetSceneExtent(GetSceneExtent()); - } - - - void WorldSceneWidget::SetSize(unsigned int width, - unsigned int height) - { - CairoWidget::SetSize(width, height); - view_.SetDisplaySize(width, height); - } - - - void WorldSceneWidget::SetInteractor(IWorldSceneInteractor& interactor) - { - interactor_ = &interactor; - } - - - void WorldSceneWidget::FitContent() - { - SetSceneExtent(view_); - view_.FitContent(); - - NotifyContentChanged(); - } - - - void WorldSceneWidget::SetView(const ViewportGeometry& view) - { - view_ = view; - - NotifyContentChanged(); - } - - - IMouseTracker* WorldSceneWidget::CreateMouseTracker(OrthancStone::MouseButton button, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers, - const std::vector<Touch>& touches) - { - double sceneX, sceneY; - view_.MapPixelCenterToScene(sceneX, sceneY, x, y); - - // asks the Widget Interactor to provide a mouse tracker - std::unique_ptr<IWorldSceneMouseTracker> tracker; - - if (interactor_) - { - tracker.reset(interactor_->CreateMouseTracker(*this, view_, button, modifiers, x, y, sceneX, sceneY, GetStatusBar(), touches)); - } - - if (tracker.get() != NULL) - { - return new SceneMouseTracker(view_, tracker.release()); - } - else if (hasDefaultMouseEvents_) - { - if (touches.size() == 2) - { - return new SceneMouseTracker(view_, new PanZoomMouseTracker(*this, touches)); - } - else - { - switch (button) - { - case OrthancStone::MouseButton_Middle: - return new SceneMouseTracker(view_, new PanMouseTracker(*this, x, y)); - - case OrthancStone::MouseButton_Right: - return new SceneMouseTracker(view_, new ZoomMouseTracker(*this, x, y)); - - default: - return NULL; - } - } - } - else - { - return NULL; - } - } - - - void WorldSceneWidget::MouseWheel(OrthancStone::MouseWheelDirection direction, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers) - { - if (interactor_) - { - interactor_->MouseWheel(*this, direction, modifiers, GetStatusBar()); - } - } - - - void WorldSceneWidget::KeyPressed(OrthancStone::KeyboardKeys key, - char keyChar, - OrthancStone::KeyboardModifiers modifiers) - { - if (interactor_) - { - interactor_->KeyPressed(*this, key, keyChar, modifiers, GetStatusBar()); - } - } -}
--- a/OrthancStone/Sources/Deprecated/Widgets/WorldSceneWidget.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "CairoWidget.h" -#include "IWorldSceneInteractor.h" - -#include "../Toolbox/ViewportGeometry.h" - -namespace Deprecated -{ - class WorldSceneWidget : public CairoWidget - { - private: - class SceneMouseTracker; - - ViewportGeometry view_; - IWorldSceneInteractor* interactor_; - bool hasDefaultMouseEvents_; - - protected: - virtual OrthancStone::Extent2D GetSceneExtent() = 0; - - virtual bool RenderScene(OrthancStone::CairoContext& context, - const ViewportGeometry& view) = 0; - - // From CairoWidget - virtual bool RenderCairo(OrthancStone::CairoContext& context); - - // From CairoWidget - virtual void RenderMouseOverCairo(OrthancStone::CairoContext& context, - int x, - int y); - - void SetSceneExtent(ViewportGeometry& geometry); - - public: - WorldSceneWidget(const std::string& name) : - CairoWidget(name), - interactor_(NULL), - hasDefaultMouseEvents_(true) - { - } - - void SetDefaultMouseEvents(bool value) - { - hasDefaultMouseEvents_ = value; - } - - bool HasDefaultMouseEvents() const - { - return hasDefaultMouseEvents_; - } - - void SetInteractor(IWorldSceneInteractor& interactor); - - void SetView(const ViewportGeometry& view); - - const ViewportGeometry& GetView() const - { - return view_; - } - - virtual void SetSize(unsigned int width, - unsigned int height); - - virtual void FitContent(); - - virtual IMouseTracker* CreateMouseTracker(OrthancStone::MouseButton button, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers, - const std::vector<Touch>& touches); - - virtual void MouseWheel(OrthancStone::MouseWheelDirection direction, - int x, - int y, - OrthancStone::KeyboardModifiers modifiers); - - virtual void KeyPressed(OrthancStone::KeyboardKeys key, - char keyChar, - OrthancStone::KeyboardModifiers modifiers); - }; -}
--- a/OrthancStone/Sources/Deprecated/Widgets/ZoomMouseTracker.cpp Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "ZoomMouseTracker.h" - -#include <Logging.h> -#include <OrthancException.h> - -namespace Deprecated -{ - ZoomMouseTracker::ZoomMouseTracker(WorldSceneWidget& that, - int x, - int y) : - that_(that), - originalZoom_(that.GetView().GetZoom()), - downX_(x), - downY_(y) - { - that.GetView().MapPixelCenterToScene(centerX_, centerY_, x, y); - - unsigned int height = that.GetView().GetDisplayHeight(); - - if (height <= 3) - { - idle_ = true; - LOG(WARNING) << "image is too small to zoom (current height = " << height << ")"; - } - else - { - idle_ = false; - normalization_ = 1.0 / static_cast<double>(height - 1); - } - } - - - void ZoomMouseTracker::Render(OrthancStone::CairoContext& context, - double zoom) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - - - void ZoomMouseTracker::MouseMove(int displayX, - int displayY, - double x, - double y, - const std::vector<Touch>& displayTouches, - const std::vector<Touch>& sceneTouches) - { - static const double MIN_ZOOM = -4; - static const double MAX_ZOOM = 4; - - - if (!idle_) - { - double dy = static_cast<double>(displayY - downY_) * normalization_; // In the range [-1,1] - double z; - - // Linear interpolation from [-1, 1] to [MIN_ZOOM, MAX_ZOOM] - if (dy < -1.0) - { - z = MIN_ZOOM; - } - else if (dy > 1.0) - { - z = MAX_ZOOM; - } - else - { - z = MIN_ZOOM + (MAX_ZOOM - MIN_ZOOM) * (dy + 1.0) / 2.0; - } - - z = pow(2.0, z); - - ViewportGeometry view = that_.GetView(); - - view.SetZoom(z * originalZoom_); - - // Correct the pan so that the original click point is kept at - // the same location on the display - double panX, panY; - view.GetPan(panX, panY); - - int tx, ty; - view.MapSceneToDisplay(tx, ty, centerX_, centerY_); - view.SetPan(panX + static_cast<double>(downX_ - tx), - panY + static_cast<double>(downY_ - ty)); - - that_.SetView(view); - } - } -}
--- a/OrthancStone/Sources/Deprecated/Widgets/ZoomMouseTracker.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "WorldSceneWidget.h" - -namespace Deprecated -{ - class ZoomMouseTracker : public IWorldSceneMouseTracker - { - private: - WorldSceneWidget& that_; - double originalZoom_; - int downX_; - int downY_; - double centerX_; - double centerY_; - bool idle_; - double normalization_; - - public: - ZoomMouseTracker(WorldSceneWidget& that, - int x, - int y); - - virtual bool HasRender() const - { - return false; - } - - virtual void MouseUp() - { - } - - virtual void Render(OrthancStone::CairoContext& context, - double zoom); - - virtual void MouseMove(int displayX, - int displayY, - double x, - double y, - const std::vector<Touch>& displayTouches, - const std::vector<Touch>& sceneTouches); - }; -}
--- a/OrthancStone/Sources/Deprecated/dev.h Thu Sep 17 15:39:33 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,958 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include "Layers/FrameRenderer.h" -#include "Layers/LineLayerRenderer.h" -#include "Layers/SliceOutlineRenderer.h" -#include "Toolbox/DownloadStack.h" -#include "Toolbox/GeometryToolbox.h" -#include "Toolbox/OrthancSlicesLoader.h" -#include "Volumes/ISlicedVolume.h" -#include "Volumes/ImageBuffer3D.h" -#include "Widgets/SliceViewerWidget.h" - -#include <Logging.h> -#include <Images/ImageProcessing.h> -#include <OrthancException.h> - -#include <boost/math/special_functions/round.hpp> - - -namespace Deprecated -{ - // TODO: Handle errors while loading - class OrthancVolumeImage : - public ISlicedVolume, - public OrthancStone::IObserver - { - private: - OrthancSlicesLoader loader_; - std::unique_ptr<OrthancStone::ImageBuffer3D> image_; - std::unique_ptr<DownloadStack> downloadStack_; - bool computeRange_; - size_t pendingSlices_; - - void ScheduleSliceDownload() - { - assert(downloadStack_.get() != NULL); - - unsigned int slice; - if (downloadStack_->Pop(slice)) - { - loader_.ScheduleLoadSliceImage(slice, OrthancStone::SliceImageQuality_Jpeg90); - } - } - - - static bool IsCompatible(const Slice& a, - const Slice& b) - { - if (!OrthancStone::GeometryToolbox::IsParallel(a.GetGeometry().GetNormal(), - b.GetGeometry().GetNormal())) - { - LOG(ERROR) << "A slice in the volume image is not parallel to the others."; - return false; - } - - if (a.GetConverter().GetExpectedPixelFormat() != b.GetConverter().GetExpectedPixelFormat()) - { - LOG(ERROR) << "The pixel format changes across the slices of the volume image."; - return false; - } - - if (a.GetWidth() != b.GetWidth() || - a.GetHeight() != b.GetHeight()) - { - LOG(ERROR) << "The slices dimensions (width/height) are varying throughout the volume image"; - return false; - } - - if (!OrthancStone::LinearAlgebra::IsNear(a.GetPixelSpacingX(), b.GetPixelSpacingX()) || - !OrthancStone::LinearAlgebra::IsNear(a.GetPixelSpacingY(), b.GetPixelSpacingY())) - { - LOG(ERROR) << "The pixel spacing of the slices change across the volume image"; - return false; - } - - return true; - } - - - static double GetDistance(const Slice& a, - const Slice& b) - { - return fabs(a.GetGeometry().ProjectAlongNormal(a.GetGeometry().GetOrigin()) - - a.GetGeometry().ProjectAlongNormal(b.GetGeometry().GetOrigin())); - } - - - void OnSliceGeometryReady(const OrthancSlicesLoader::SliceGeometryReadyMessage& message) - { - assert(&message.GetOrigin() == &loader_); - - if (loader_.GetSlicesCount() == 0) - { - LOG(ERROR) << "Empty volume image"; - BroadcastMessage(ISlicedVolume::GeometryErrorMessage(*this)); - return; - } - - for (size_t i = 1; i < loader_.GetSlicesCount(); i++) - { - if (!IsCompatible(loader_.GetSlice(0), loader_.GetSlice(i))) - { - BroadcastMessage(ISlicedVolume::GeometryErrorMessage(*this)); - return; - } - } - - double spacingZ; - - if (loader_.GetSlicesCount() > 1) - { - spacingZ = GetDistance(loader_.GetSlice(0), loader_.GetSlice(1)); - } - else - { - // This is a volume with one single slice: Choose a dummy - // z-dimension for voxels - spacingZ = 1; - } - - for (size_t i = 1; i < loader_.GetSlicesCount(); i++) - { - if (!OrthancStone::LinearAlgebra::IsNear(spacingZ, GetDistance(loader_.GetSlice(i - 1), loader_.GetSlice(i)), - 0.001 /* this is expressed in mm */)) - { - LOG(ERROR) << "The distance between successive slices is not constant in a volume image"; - BroadcastMessage(ISlicedVolume::GeometryErrorMessage(*this)); - return; - } - } - - unsigned int width = loader_.GetSlice(0).GetWidth(); - unsigned int height = loader_.GetSlice(0).GetHeight(); - Orthanc::PixelFormat format = loader_.GetSlice(0).GetConverter().GetExpectedPixelFormat(); - LOG(INFO) << "Creating a volume image of size " << width << "x" << height - << "x" << loader_.GetSlicesCount() << " in " << Orthanc::EnumerationToString(format); - - image_.reset(new OrthancStone::ImageBuffer3D(format, width, height, static_cast<unsigned int>(loader_.GetSlicesCount()), computeRange_)); - image_->GetGeometry().SetAxialGeometry(loader_.GetSlice(0).GetGeometry()); - image_->GetGeometry().SetVoxelDimensions(loader_.GetSlice(0).GetPixelSpacingX(), - loader_.GetSlice(0).GetPixelSpacingY(), spacingZ); - image_->Clear(); - - downloadStack_.reset(new DownloadStack(static_cast<unsigned int>(loader_.GetSlicesCount()))); - pendingSlices_ = loader_.GetSlicesCount(); - - for (unsigned int i = 0; i < 4; i++) // Limit to 4 simultaneous downloads - { - ScheduleSliceDownload(); - } - - // TODO Check the DicomFrameConverter are constant - - BroadcastMessage(ISlicedVolume::GeometryReadyMessage(*this)); - } - - - void OnSliceGeometryError(const OrthancSlicesLoader::SliceGeometryErrorMessage& message) - { - assert(&message.GetOrigin() == &loader_); - - LOG(ERROR) << "Unable to download a volume image"; - BroadcastMessage(ISlicedVolume::GeometryErrorMessage(*this)); - } - - - void OnSliceImageReady(const OrthancSlicesLoader::SliceImageReadyMessage& message) - { - assert(&message.GetOrigin() == &loader_); - - { - OrthancStone::ImageBuffer3D::SliceWriter writer(*image_, OrthancStone::VolumeProjection_Axial, message.GetSliceIndex()); - Orthanc::ImageProcessing::Copy(writer.GetAccessor(), message.GetImage()); - } - - BroadcastMessage(ISlicedVolume::SliceContentChangedMessage - (*this, message.GetSliceIndex(), message.GetSlice())); - - if (pendingSlices_ == 1) - { - BroadcastMessage(ISlicedVolume::VolumeReadyMessage(*this)); - pendingSlices_ = 0; - } - else if (pendingSlices_ > 1) - { - pendingSlices_ -= 1; - } - - ScheduleSliceDownload(); - } - - - void OnSliceImageError(const OrthancSlicesLoader::SliceImageErrorMessage& message) - { - assert(&message.GetOrigin() == &loader_); - - LOG(ERROR) << "Cannot download slice " << message.GetSliceIndex() << " in a volume image"; - ScheduleSliceDownload(); - } - - - public: - OrthancVolumeImage(OrthancStone::MessageBroker& broker, - OrthancApiClient& orthanc, - bool computeRange) : - ISlicedVolume(broker), - IObserver(broker), - loader_(broker, orthanc), - computeRange_(computeRange), - pendingSlices_(0) - { - loader_.RegisterObserverCallback( - new OrthancStone::Callable<OrthancVolumeImage, OrthancSlicesLoader::SliceGeometryReadyMessage> - (*this, &OrthancVolumeImage::OnSliceGeometryReady)); - - loader_.RegisterObserverCallback( - new OrthancStone::Callable<OrthancVolumeImage, OrthancSlicesLoader::SliceGeometryErrorMessage> - (*this, &OrthancVolumeImage::OnSliceGeometryError)); - - loader_.RegisterObserverCallback( - new OrthancStone::Callable<OrthancVolumeImage, OrthancSlicesLoader::SliceImageReadyMessage> - (*this, &OrthancVolumeImage::OnSliceImageReady)); - - loader_.RegisterObserverCallback( - new OrthancStone::Callable<OrthancVolumeImage, OrthancSlicesLoader::SliceImageErrorMessage> - (*this, &OrthancVolumeImage::OnSliceImageError)); - } - - void ScheduleLoadSeries(const std::string& seriesId) - { - loader_.ScheduleLoadSeries(seriesId); - } - - void ScheduleLoadInstance(const std::string& instanceId) - { - loader_.ScheduleLoadInstance(instanceId); - } - - void ScheduleLoadFrame(const std::string& instanceId, - unsigned int frame) - { - loader_.ScheduleLoadFrame(instanceId, frame); - } - - virtual size_t GetSlicesCount() const - { - return loader_.GetSlicesCount(); - } - - virtual const Slice& GetSlice(size_t index) const - { - return loader_.GetSlice(index); - } - - OrthancStone::ImageBuffer3D& GetImage() const - { - if (image_.get() == NULL) - { - // The geometry is not ready yet - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - else - { - return *image_; - } - } - - bool FitWindowingToRange(RenderStyle& style, - const DicomFrameConverter& converter) const - { - if (image_.get() == NULL) - { - return false; - } - else - { - return image_->FitWindowingToRange(style, converter); - } - } - }; - - - class VolumeImageGeometry - { - private: - unsigned int width_; - unsigned int height_; - size_t depth_; - double pixelSpacingX_; - double pixelSpacingY_; - double sliceThickness_; - OrthancStone::CoordinateSystem3D reference_; - DicomFrameConverter converter_; - - double ComputeAxialThickness(const OrthancVolumeImage& volume) const - { - double thickness; - - size_t n = volume.GetSlicesCount(); - if (n > 1) - { - const Slice& a = volume.GetSlice(0); - const Slice& b = volume.GetSlice(n - 1); - thickness = ((reference_.ProjectAlongNormal(b.GetGeometry().GetOrigin()) - - reference_.ProjectAlongNormal(a.GetGeometry().GetOrigin())) / - (static_cast<double>(n) - 1.0)); - } - else - { - thickness = volume.GetSlice(0).GetThickness(); - } - - if (thickness <= 0) - { - // The slices should have been sorted with increasing Z - // (along the normal) by the OrthancSlicesLoader - throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); - } - else - { - return thickness; - } - } - - void SetupAxial(const OrthancVolumeImage& volume) - { - const Slice& axial = volume.GetSlice(0); - - width_ = axial.GetWidth(); - height_ = axial.GetHeight(); - depth_ = volume.GetSlicesCount(); - - pixelSpacingX_ = axial.GetPixelSpacingX(); - pixelSpacingY_ = axial.GetPixelSpacingY(); - sliceThickness_ = ComputeAxialThickness(volume); - - reference_ = axial.GetGeometry(); - } - - void SetupCoronal(const OrthancVolumeImage& volume) - { - const Slice& axial = volume.GetSlice(0); - double axialThickness = ComputeAxialThickness(volume); - - width_ = axial.GetWidth(); - height_ = static_cast<unsigned int>(volume.GetSlicesCount()); - depth_ = axial.GetHeight(); - - pixelSpacingX_ = axial.GetPixelSpacingX(); - pixelSpacingY_ = axialThickness; - sliceThickness_ = axial.GetPixelSpacingY(); - - OrthancStone::Vector origin = axial.GetGeometry().GetOrigin(); - origin += (static_cast<double>(volume.GetSlicesCount() - 1) * - axialThickness * axial.GetGeometry().GetNormal()); - - reference_ = OrthancStone::CoordinateSystem3D(origin, - axial.GetGeometry().GetAxisX(), - - axial.GetGeometry().GetNormal()); - } - - void SetupSagittal(const OrthancVolumeImage& volume) - { - const Slice& axial = volume.GetSlice(0); - double axialThickness = ComputeAxialThickness(volume); - - width_ = axial.GetHeight(); - height_ = static_cast<unsigned int>(volume.GetSlicesCount()); - depth_ = axial.GetWidth(); - - pixelSpacingX_ = axial.GetPixelSpacingY(); - pixelSpacingY_ = axialThickness; - sliceThickness_ = axial.GetPixelSpacingX(); - - OrthancStone::Vector origin = axial.GetGeometry().GetOrigin(); - origin += (static_cast<double>(volume.GetSlicesCount() - 1) * - axialThickness * axial.GetGeometry().GetNormal()); - - reference_ = OrthancStone::CoordinateSystem3D(origin, - axial.GetGeometry().GetAxisY(), - axial.GetGeometry().GetNormal()); - } - - public: - VolumeImageGeometry(const OrthancVolumeImage& volume, - OrthancStone::VolumeProjection projection) - { - if (volume.GetSlicesCount() == 0) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - converter_ = volume.GetSlice(0).GetConverter(); - - switch (projection) - { - case OrthancStone::VolumeProjection_Axial: - SetupAxial(volume); - break; - - case OrthancStone::VolumeProjection_Coronal: - SetupCoronal(volume); - break; - - case OrthancStone::VolumeProjection_Sagittal: - SetupSagittal(volume); - break; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - } - - size_t GetSlicesCount() const - { - return depth_; - } - - const OrthancStone::Vector& GetNormal() const - { - return reference_.GetNormal(); - } - - bool LookupSlice(size_t& index, - const OrthancStone::CoordinateSystem3D& slice) const - { - bool opposite; - if (!OrthancStone::GeometryToolbox::IsParallelOrOpposite(opposite, - reference_.GetNormal(), - slice.GetNormal())) - { - return false; - } - - double z = (reference_.ProjectAlongNormal(slice.GetOrigin()) - - reference_.ProjectAlongNormal(reference_.GetOrigin())) / sliceThickness_; - - int s = static_cast<int>(boost::math::iround(z)); - - if (s < 0 || - s >= static_cast<int>(depth_)) - { - return false; - } - else - { - index = static_cast<size_t>(s); - return true; - } - } - - Slice* GetSlice(size_t slice) const - { - if (slice >= depth_) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - else - { - OrthancStone::CoordinateSystem3D origin(reference_.GetOrigin() + - static_cast<double>(slice) * sliceThickness_ * reference_.GetNormal(), - reference_.GetAxisX(), - reference_.GetAxisY()); - - return new Slice(origin, pixelSpacingX_, pixelSpacingY_, sliceThickness_, - width_, height_, converter_); - } - } - }; - - - - class VolumeImageMPRSlicer : - public IVolumeSlicer, - public OrthancStone::IObserver - { - private: - class RendererFactory : public LayerReadyMessage::IRendererFactory - { - private: - const Orthanc::ImageAccessor& frame_; - const Slice& slice_; - bool isFullQuality_; - - public: - RendererFactory(const Orthanc::ImageAccessor& frame, - const Slice& slice, - bool isFullQuality) : - frame_(frame), - slice_(slice), - isFullQuality_(isFullQuality) - { - } - - virtual ILayerRenderer* CreateRenderer() const - { - return FrameRenderer::CreateRenderer(frame_, slice_, isFullQuality_); - } - }; - - - OrthancVolumeImage& volume_; - std::unique_ptr<VolumeImageGeometry> axialGeometry_; - std::unique_ptr<VolumeImageGeometry> coronalGeometry_; - std::unique_ptr<VolumeImageGeometry> sagittalGeometry_; - - - bool IsGeometryReady() const - { - return axialGeometry_.get() != NULL; - } - - void OnGeometryReady(const ISlicedVolume::GeometryReadyMessage& message) - { - assert(&message.GetOrigin() == &volume_); - - // These 3 values are only used to speed up the IVolumeSlicer - axialGeometry_.reset(new VolumeImageGeometry(volume_, OrthancStone::VolumeProjection_Axial)); - coronalGeometry_.reset(new VolumeImageGeometry(volume_, OrthancStone::VolumeProjection_Coronal)); - sagittalGeometry_.reset(new VolumeImageGeometry(volume_, OrthancStone::VolumeProjection_Sagittal)); - - BroadcastMessage(IVolumeSlicer::GeometryReadyMessage(*this)); - } - - void OnGeometryError(const ISlicedVolume::GeometryErrorMessage& message) - { - assert(&message.GetOrigin() == &volume_); - - BroadcastMessage(IVolumeSlicer::GeometryErrorMessage(*this)); - } - - void OnContentChanged(const ISlicedVolume::ContentChangedMessage& message) - { - assert(&message.GetOrigin() == &volume_); - - BroadcastMessage(IVolumeSlicer::ContentChangedMessage(*this)); - } - - void OnSliceContentChanged(const ISlicedVolume::SliceContentChangedMessage& message) - { - assert(&message.GetOrigin() == &volume_); - - //IVolumeSlicer::OnSliceContentChange(slice); - - // TODO Improve this? - BroadcastMessage(IVolumeSlicer::ContentChangedMessage(*this)); - } - - const VolumeImageGeometry& GetProjectionGeometry(OrthancStone::VolumeProjection projection) - { - if (!IsGeometryReady()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - switch (projection) - { - case OrthancStone::VolumeProjection_Axial: - return *axialGeometry_; - - case OrthancStone::VolumeProjection_Sagittal: - return *sagittalGeometry_; - - case OrthancStone::VolumeProjection_Coronal: - return *coronalGeometry_; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - } - - - bool DetectProjection(OrthancStone::VolumeProjection& projection, - const OrthancStone::CoordinateSystem3D& viewportSlice) - { - bool isOpposite; // Ignored - - if (OrthancStone::GeometryToolbox::IsParallelOrOpposite(isOpposite, - viewportSlice.GetNormal(), - axialGeometry_->GetNormal())) - { - projection = OrthancStone::VolumeProjection_Axial; - return true; - } - else if (OrthancStone::GeometryToolbox::IsParallelOrOpposite(isOpposite, - viewportSlice.GetNormal(), - sagittalGeometry_->GetNormal())) - { - projection = OrthancStone::VolumeProjection_Sagittal; - return true; - } - else if (OrthancStone::GeometryToolbox::IsParallelOrOpposite(isOpposite, - viewportSlice.GetNormal(), - coronalGeometry_->GetNormal())) - { - projection = OrthancStone::VolumeProjection_Coronal; - return true; - } - else - { - return false; - } - } - - - public: - VolumeImageMPRSlicer(OrthancStone::MessageBroker& broker, - OrthancVolumeImage& volume) : - IVolumeSlicer(broker), - IObserver(broker), - volume_(volume) - { - volume_.RegisterObserverCallback( - new OrthancStone::Callable<VolumeImageMPRSlicer, ISlicedVolume::GeometryReadyMessage> - (*this, &VolumeImageMPRSlicer::OnGeometryReady)); - - volume_.RegisterObserverCallback( - new OrthancStone::Callable<VolumeImageMPRSlicer, ISlicedVolume::GeometryErrorMessage> - (*this, &VolumeImageMPRSlicer::OnGeometryError)); - - volume_.RegisterObserverCallback( - new OrthancStone::Callable<VolumeImageMPRSlicer, ISlicedVolume::ContentChangedMessage> - (*this, &VolumeImageMPRSlicer::OnContentChanged)); - - volume_.RegisterObserverCallback( - new OrthancStone::Callable<VolumeImageMPRSlicer, ISlicedVolume::SliceContentChangedMessage> - (*this, &VolumeImageMPRSlicer::OnSliceContentChanged)); - } - - virtual bool GetExtent(std::vector<OrthancStone::Vector>& points, - const OrthancStone::CoordinateSystem3D& viewportSlice) ORTHANC_OVERRIDE - { - OrthancStone::VolumeProjection projection; - - if (!IsGeometryReady() || - !DetectProjection(projection, viewportSlice)) - { - return false; - } - else - { - // As the slices of the volumic image are arranged in a box, - // we only consider one single reference slice (the one with index 0). - std::unique_ptr<Slice> slice(GetProjectionGeometry(projection).GetSlice(0)); - slice->GetExtent(points); - - return true; - } - } - - virtual void ScheduleLayerCreation(const OrthancStone::CoordinateSystem3D& viewportSlice) ORTHANC_OVERRIDE - { - OrthancStone::VolumeProjection projection; - - if (IsGeometryReady() && - DetectProjection(projection, viewportSlice)) - { - const VolumeImageGeometry& geometry = GetProjectionGeometry(projection); - - size_t closest; - - if (geometry.LookupSlice(closest, viewportSlice)) - { - bool isFullQuality = true; // TODO - - std::unique_ptr<Orthanc::Image> frame; - - { - OrthancStone::ImageBuffer3D::SliceReader reader(volume_.GetImage(), projection, static_cast<unsigned int>(closest)); - - // TODO Transfer ownership if non-axial, to avoid memcpy - frame.reset(Orthanc::Image::Clone(reader.GetAccessor())); - } - - std::unique_ptr<Slice> slice(geometry.GetSlice(closest)); - - RendererFactory factory(*frame, *slice, isFullQuality); - - BroadcastMessage(IVolumeSlicer::LayerReadyMessage(*this, factory, slice->GetGeometry())); - return; - } - } - - // Error - OrthancStone::CoordinateSystem3D slice; - BroadcastMessage(IVolumeSlicer::LayerErrorMessage(*this, slice)); - } - }; - - - class VolumeImageInteractor : - public IWorldSceneInteractor, - public OrthancStone::IObserver - { - private: - SliceViewerWidget& widget_; - OrthancStone::VolumeProjection projection_; - std::unique_ptr<VolumeImageGeometry> slices_; - size_t slice_; - - protected: - void OnGeometryReady(const ISlicedVolume::GeometryReadyMessage& message) - { - if (slices_.get() == NULL) - { - const OrthancVolumeImage& image = - dynamic_cast<const OrthancVolumeImage&>(message.GetOrigin()); - - slices_.reset(new VolumeImageGeometry(image, projection_)); - SetSlice(slices_->GetSlicesCount() / 2); - - widget_.FitContent(); - } - } - - virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, - const ViewportGeometry& view, - OrthancStone::MouseButton button, - OrthancStone::KeyboardModifiers modifiers, - int viewportX, - int viewportY, - double x, - double y, - IStatusBar* statusBar, - const std::vector<Touch>& touches) ORTHANC_OVERRIDE - { - return NULL; - } - - virtual void MouseOver(OrthancStone::CairoContext& context, - WorldSceneWidget& widget, - const ViewportGeometry& view, - double x, - double y, - IStatusBar* statusBar) ORTHANC_OVERRIDE - { - } - - virtual void MouseWheel(WorldSceneWidget& widget, - OrthancStone::MouseWheelDirection direction, - OrthancStone::KeyboardModifiers modifiers, - IStatusBar* statusBar) ORTHANC_OVERRIDE - { - int scale = (modifiers & OrthancStone::KeyboardModifiers_Control ? 10 : 1); - - switch (direction) - { - case OrthancStone::MouseWheelDirection_Up: - OffsetSlice(-scale); - break; - - case OrthancStone::MouseWheelDirection_Down: - OffsetSlice(scale); - break; - - default: - break; - } - } - - virtual void KeyPressed(WorldSceneWidget& widget, - OrthancStone::KeyboardKeys key, - char keyChar, - OrthancStone::KeyboardModifiers modifiers, - IStatusBar* statusBar) ORTHANC_OVERRIDE - { - switch (keyChar) - { - case 's': - widget.FitContent(); - break; - - default: - break; - } - } - - public: - VolumeImageInteractor(OrthancStone::MessageBroker& broker, - OrthancVolumeImage& volume, - SliceViewerWidget& widget, - OrthancStone::VolumeProjection projection) : - IObserver(broker), - widget_(widget), - projection_(projection) - { - widget.SetInteractor(*this); - - volume.RegisterObserverCallback( - new OrthancStone::Callable<VolumeImageInteractor, ISlicedVolume::GeometryReadyMessage> - (*this, &VolumeImageInteractor::OnGeometryReady)); - } - - bool IsGeometryReady() const - { - return slices_.get() != NULL; - } - - size_t GetSlicesCount() const - { - if (slices_.get() == NULL) - { - return 0; - } - else - { - return slices_->GetSlicesCount(); - } - } - - void OffsetSlice(int offset) - { - if (slices_.get() != NULL) - { - int slice = static_cast<int>(slice_) + offset; - - if (slice < 0) - { - slice = 0; - } - - if (slice >= static_cast<int>(slices_->GetSlicesCount())) - { - slice = static_cast<unsigned int>(slices_->GetSlicesCount()) - 1; - } - - if (slice != static_cast<int>(slice_)) - { - SetSlice(slice); - } - } - } - - void SetSlice(size_t slice) - { - if (slices_.get() != NULL) - { - slice_ = slice; - - std::unique_ptr<Slice> tmp(slices_->GetSlice(slice_)); - widget_.SetSlice(tmp->GetGeometry()); - } - } - }; - - - - class ReferenceLineSource : public IVolumeSlicer - { - private: - class RendererFactory : public LayerReadyMessage::IRendererFactory - { - private: - double x1_; - double y1_; - double x2_; - double y2_; - const OrthancStone::CoordinateSystem3D& slice_; - - public: - RendererFactory(double x1, - double y1, - double x2, - double y2, - const OrthancStone::CoordinateSystem3D& slice) : - x1_(x1), - y1_(y1), - x2_(x2), - y2_(y2), - slice_(slice) - { - } - - virtual ILayerRenderer* CreateRenderer() const - { - return new LineLayerRenderer(x1_, y1_, x2_, y2_, slice_); - } - }; - - SliceViewerWidget& otherPlane_; - - public: - ReferenceLineSource(OrthancStone::MessageBroker& broker, - SliceViewerWidget& otherPlane) : - IVolumeSlicer(broker), - otherPlane_(otherPlane) - { - BroadcastMessage(IVolumeSlicer::GeometryReadyMessage(*this)); - } - - virtual bool GetExtent(std::vector<OrthancStone::Vector>& points, - const OrthancStone::CoordinateSystem3D& viewportSlice) - { - return false; - } - - virtual void ScheduleLayerCreation(const OrthancStone::CoordinateSystem3D& viewportSlice) - { - Slice reference(viewportSlice, 0.001); - - OrthancStone::Vector p, d; - - const OrthancStone::CoordinateSystem3D& slice = otherPlane_.GetSlice(); - - // Compute the line of intersection between the two slices - if (!OrthancStone::GeometryToolbox::IntersectTwoPlanes(p, d, - slice.GetOrigin(), slice.GetNormal(), - viewportSlice.GetOrigin(), viewportSlice.GetNormal())) - { - // The two slice are parallel, don't try and display the intersection - BroadcastMessage(IVolumeSlicer::LayerErrorMessage(*this, reference.GetGeometry())); - } - else - { - double x1, y1, x2, y2; - viewportSlice.ProjectPoint(x1, y1, p); - viewportSlice.ProjectPoint(x2, y2, p + 1000.0 * d); - - const OrthancStone::Extent2D extent = otherPlane_.GetSceneExtent(); - - if (OrthancStone::GeometryToolbox::ClipLineToRectangle(x1, y1, x2, y2, - x1, y1, x2, y2, - extent.GetX1(), extent.GetY1(), - extent.GetX2(), extent.GetY2())) - { - RendererFactory factory(x1, y1, x2, y2, slice); - BroadcastMessage(IVolumeSlicer::LayerReadyMessage(*this, factory, reference.GetGeometry())); - } - else - { - // Error: Parallel slices - BroadcastMessage(IVolumeSlicer::LayerErrorMessage(*this, reference.GetGeometry())); - } - } - } - }; -}