]> git.lyx.org Git - lyx.git/blob - src/graphics/GraphicsLoader.C
Create a grfx::Loader class and so move large chunks of code out of
[lyx.git] / src / graphics / GraphicsLoader.C
1 /*
2  * \file GraphicsLoader.C
3  * Copyright 2002 the LyX Team
4  * Read the file COPYING
5  *
6  * \author Angus Leeming <leeming@lyx.org>
7  */
8
9 #include <config.h>
10
11 #ifdef __GNUG__
12 #pragma implementation
13 #endif
14
15 #include "GraphicsLoader.h"
16 #include "GraphicsCache.h"
17 #include "GraphicsCacheItem.h"
18 #include "GraphicsImage.h"
19 #include "GraphicsParams.h"
20
21 #include <boost/bind.hpp>
22
23 namespace grfx {
24
25 struct Loader::Impl {
26         ///
27         Impl(Loader &, GParams const &);
28         ///
29         ~Impl();
30         ///
31         void setFile(string const & file);
32         ///
33         void unsetOldFile();
34         ///
35         void createPixmap();
36         ///
37         void statusChanged();
38
39         ///
40         Loader & parent_;
41         /// The loading status of the image.
42         ImageStatus status_;
43         /** Must store a copy of the cached item to ensure that it is not
44          *  erased unexpectedly by the cache itself.
45          */
46         GraphicPtr graphic_;
47         ///
48         GParams params_;
49         /// We modify a local copy of the image once it is loaded.
50         ImagePtr image_;
51 };
52
53
54 Loader::Impl::Impl(Loader & parent, GParams const & params)
55         : parent_(parent), status_(WaitingToLoad), params_(params)
56 {}
57
58
59 Loader::Impl::~Impl()
60 {
61         unsetOldFile();
62 }
63
64
65 void Loader::Impl::setFile(string const & file)
66 {
67         if (file.empty())
68                 return;
69
70         GCache & gc = GCache::get();
71         if (!gc.inCache(file))
72                 gc.add(file);
73
74         // We /must/ make a local copy of this.
75         graphic_ = gc.graphic(file);
76         status_ = graphic_->status();
77
78         if (status_ == Loaded) {
79                 createPixmap();
80         }
81
82         // It's easiest to do this without checking
83         parent_.statusChanged();
84 }
85
86
87 void Loader::Impl::unsetOldFile()
88 {
89         if (!graphic_.get())
90                 return;
91
92         string const old_file = graphic_->filename();
93         graphic_.reset();
94         GCache::get().remove(old_file);
95
96         status_ = WaitingToLoad;
97         params_ = GParams();
98         image_.reset();
99 }
100
101
102 void Loader::Impl::statusChanged()
103 {
104         status_ = graphic_->status();
105         if (status_ == Loaded)
106                 createPixmap();
107
108         parent_.statusChanged();
109 }
110
111
112 void Loader::Impl::createPixmap()
113 {
114         if (!graphic_.get() || image_.get() ||
115             params_.display == NoDisplay || status_ != Loaded)
116                 return;
117
118         image_.reset(graphic_->image()->clone());
119
120         // These do nothing if there's nothing to do
121         image_->clip(params_);
122         image_->rotate(params_);
123         image_->scale(params_);
124
125         bool const success = image_->setPixmap(params_);
126
127         if (success) {
128                 status_ = Ready;
129         } else {
130                 image_.reset();
131                 status_ = ErrorGeneratingPixmap;
132         }
133 }
134
135
136 Loader::Loader()
137         : pimpl_(new Impl(*this, GParams()))
138 {}
139
140
141 Loader::Loader(string const & file, DisplayType type)
142         : pimpl_(new Impl(*this, GParams()))
143 {
144         pimpl_->params_.display = type;
145         pimpl_->setFile(file);
146 }
147
148
149 Loader::Loader(string const & file, GParams const & params)
150         : pimpl_(new Impl(*this, params))
151 {
152         pimpl_->setFile(file);
153 }
154
155
156 void Loader::reset(string const & file, DisplayType type)
157 {
158         pimpl_->unsetOldFile();
159
160         pimpl_->params_ = GParams();
161         pimpl_->params_.display = type;
162         pimpl_->setFile(file);
163 }
164
165
166 void Loader::reset(string const & file, GParams const & params)
167 {
168         pimpl_->unsetOldFile();
169
170         pimpl_->params_ = params;
171         pimpl_->setFile(file);
172 }
173
174
175 void Loader::reset(GParams const & params)
176 {
177         pimpl_->params_ = params;
178
179         if (pimpl_->status_ == Loaded)
180                 pimpl_->createPixmap();
181 }
182
183
184 void Loader::startLoading()
185 {
186         if (pimpl_->status_ != WaitingToLoad || !pimpl_->graphic_.get())
187                 return;
188
189         pimpl_->graphic_->statusChanged.connect(
190                 boost::bind(&Loader::Impl::statusChanged,
191                             pimpl_.get()));
192         pimpl_->graphic_->startLoading();
193 }
194
195
196 string const & Loader::filename() const
197 {
198         static string const empty;
199         return pimpl_->graphic_.get() ? pimpl_->graphic_->filename() : empty;
200 }
201
202
203 ImageStatus Loader::status() const
204 {
205         return pimpl_->status_;
206 }
207
208
209 GImage const * Loader::image() const
210 {
211         return pimpl_->image_.get();
212 }
213
214 } // namespace grfx