comparison OrthancStone/Sources/Scene2D/Internals/CompositorHelper.cpp @ 1512:244ad1e4e76a

reorganization of folders
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 07 Jul 2020 16:21:02 +0200
parents Framework/Scene2D/Internals/CompositorHelper.cpp@30deba7bc8e2
children 4fb8fdf03314
comparison
equal deleted inserted replaced
1511:9dfeee74c1e6 1512:244ad1e4e76a
1 /**
2 * Stone of Orthanc
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2020 Osimis S.A., Belgium
6 *
7 * This program is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU Affero General Public License
9 * as published by the Free Software Foundation, either version 3 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 **/
20
21
22 #include "CompositorHelper.h"
23
24 #include <OrthancException.h>
25
26 namespace OrthancStone
27 {
28 namespace Internals
29 {
30 class CompositorHelper::Item : public boost::noncopyable
31 {
32 private:
33 std::unique_ptr<ILayerRenderer> renderer_;
34 const ISceneLayer& layer_;
35 uint64_t layerIdentifier_;
36 uint64_t lastRevision_;
37
38 public:
39 Item(ILayerRenderer* renderer, // Takes ownership
40 const ISceneLayer& layer,
41 uint64_t layerIdentifier) :
42 renderer_(renderer),
43 layer_(layer),
44 layerIdentifier_(layerIdentifier),
45 lastRevision_(layer.GetRevision())
46 {
47 if (renderer == NULL)
48 {
49 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
50 }
51 }
52
53 ILayerRenderer& GetRenderer() const
54 {
55 assert(renderer_.get() != NULL);
56 return *renderer_;
57 }
58
59 const ISceneLayer& GetLayer() const
60 {
61 return layer_;
62 }
63
64 uint64_t GetLayerIdentifier() const
65 {
66 return layerIdentifier_;
67 }
68
69 uint64_t GetLastRevision() const
70 {
71 return lastRevision_;
72 }
73
74 void UpdateRenderer()
75 {
76 assert(renderer_.get() != NULL);
77 renderer_->Update(layer_);
78 lastRevision_ = layer_.GetRevision();
79 }
80 };
81
82
83 void CompositorHelper::Visit(const Scene2D& scene,
84 const ISceneLayer& layer,
85 uint64_t layerIdentifier,
86 int depth)
87 {
88 // "Visit()" is only applied to layers existing in the scene
89 assert(scene.HasLayer(depth));
90
91 Content::iterator found = content_.find(depth);
92
93 assert(found == content_.end() ||
94 found->second != NULL);
95
96 if (found == content_.end() ||
97 found->second->GetLayerIdentifier() != layerIdentifier)
98 {
99 // This is the first time this layer is rendered, or the layer
100 // is not the same as before
101 if (found != content_.end())
102 {
103 delete found->second;
104 content_.erase(found);
105 }
106
107 // the returned renderer can be NULL in case of an unknown layer
108 // or a NullLayer
109 std::unique_ptr<ILayerRenderer> renderer(factory_.Create(layer));
110
111 if (renderer.get() != NULL)
112 {
113 renderer->Render(sceneTransform_, canvasWidth_, canvasHeight_);
114 content_[depth] = new Item(renderer.release(), layer, layerIdentifier);
115 }
116 }
117 else
118 {
119 // This layer has already been rendered
120 assert(found->second->GetLastRevision() <= layer.GetRevision());
121
122 if (found->second->GetLastRevision() < layer.GetRevision())
123 {
124 found->second->UpdateRenderer();
125 }
126
127 found->second->GetRenderer().Render(sceneTransform_, canvasWidth_, canvasHeight_);
128 }
129
130 // Check invariants
131 assert(content_.find(depth) == content_.end() ||
132 (content_[depth]->GetLayerIdentifier() == layerIdentifier &&
133 content_[depth]->GetLastRevision() == layer.GetRevision()));
134 }
135
136
137 CompositorHelper::~CompositorHelper()
138 {
139 for (Content::iterator it = content_.begin(); it != content_.end(); ++it)
140 {
141 assert(it->second != NULL);
142 delete it->second;
143 }
144 }
145
146
147 void CompositorHelper::Refresh(const Scene2D& scene,
148 unsigned int canvasWidth,
149 unsigned int canvasHeight)
150 {
151 /**
152 * Safeguard mechanism to enforce the fact that the same scene
153 * is always used with the compositor. Note that the safeguard
154 * is not 100% bullet-proof, as a new scene might reuse the same
155 * address as a previous scene.
156 **/
157 if (lastScene_ != NULL &&
158 lastScene_ != &scene)
159 {
160 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls,
161 "ICompositor::ResetScene() should have been called");
162 }
163
164 lastScene_ = &scene;
165
166 // Bring coordinate (0,0) to the center of the canvas
167 AffineTransform2D offset = AffineTransform2D::CreateOffset(
168 static_cast<double>(canvasWidth) / 2.0,
169 static_cast<double>(canvasHeight) / 2.0);
170
171 sceneTransform_ = AffineTransform2D::Combine(offset, scene.GetSceneToCanvasTransform());
172 canvasWidth_ = canvasWidth;
173 canvasHeight_ = canvasHeight;
174 scene.Apply(*this);
175 }
176 }
177 }