]> git.lyx.org Git - lyx.git/blob - src/graphics/GraphicsLoader.C
d0c582ce06f2e5b49f407fbe8983b570416d198f
[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 Loader::~Loader()
157 {}
158
159
160 void Loader::reset(string const & file, DisplayType type)
161 {
162         pimpl_->unsetOldFile();
163
164         pimpl_->params_ = GParams();
165         pimpl_->params_.display = type;
166         pimpl_->setFile(file);
167 }
168
169
170 void Loader::reset(string const & file, GParams const & params)
171 {
172         pimpl_->unsetOldFile();
173
174         pimpl_->params_ = params;
175         pimpl_->setFile(file);
176 }
177
178
179 void Loader::reset(GParams const & params)
180 {
181         pimpl_->params_ = params;
182
183         if (pimpl_->status_ == Loaded)
184                 pimpl_->createPixmap();
185 }
186
187
188 void Loader::startLoading()
189 {
190         if (pimpl_->status_ != WaitingToLoad || !pimpl_->graphic_.get())
191                 return;
192
193         pimpl_->graphic_->statusChanged.connect(
194                 boost::bind(&Loader::Impl::statusChanged,
195                             pimpl_.get()));
196         pimpl_->graphic_->startLoading();
197 }
198
199
200 string const & Loader::filename() const
201 {
202         static string const empty;
203         return pimpl_->graphic_.get() ? pimpl_->graphic_->filename() : empty;
204 }
205
206
207 ImageStatus Loader::status() const
208 {
209         return pimpl_->status_;
210 }
211
212
213 GImage const * Loader::image() const
214 {
215         return pimpl_->image_.get();
216 }
217
218 } // namespace grfx