]> git.lyx.org Git - lyx.git/blob - src/insets/render_graphic.C
This commit is a big rework of the FontLoader/FontMetrics interaction. Only Qt4 for...
[lyx.git] / src / insets / render_graphic.C
1 /**
2  * \file render_graphic.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Angus Leeming
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "render_graphic.h"
14
15 #include "insets/inset.h"
16
17 #include "gettext.h"
18 #include "LColor.h"
19 #include "lyx_main.h"
20 #include "lyxrc.h"
21 #include "metricsinfo.h"
22
23 #include "frontends/Application.h"
24 #include "frontends/FontLoader.h"
25 #include "frontends/FontMetrics.h"
26 #include "frontends/Painter.h"
27
28 #include "graphics/GraphicsImage.h"
29
30 #include "support/filetools.h"
31
32 #include <boost/bind.hpp>
33
34 namespace graphics = lyx::graphics;
35
36 using lyx::docstring;
37 using lyx::support::absolutePath;
38 using lyx::support::onlyFilename;
39
40 using std::string;
41 using std::auto_ptr;
42
43
44 RenderGraphic::RenderGraphic(InsetBase const * inset)
45 {
46         loader_.connect(boost::bind(&LyX::updateInset,
47                                     boost::cref(LyX::cref()), inset));
48 }
49
50
51 RenderGraphic::RenderGraphic(RenderGraphic const & other,
52                              InsetBase const * inset)
53         : RenderBase(other),
54           loader_(other.loader_),
55           params_(other.params_)
56 {
57         loader_.connect(boost::bind(&LyX::updateInset,
58                                     boost::cref(LyX::cref()), inset));
59 }
60
61
62 auto_ptr<RenderBase> RenderGraphic::clone(InsetBase const * inset) const
63 {
64         return auto_ptr<RenderBase>(new RenderGraphic(*this, inset));
65 }
66
67
68 void RenderGraphic::update(graphics::Params const & params)
69 {
70         params_ = params;
71
72         if (!params_.filename.empty()) {
73                 BOOST_ASSERT(absolutePath(params_.filename));
74                 loader_.reset(params_.filename, params_);
75         }
76 }
77
78
79 namespace {
80
81 bool displayGraphic(graphics::Params const & params)
82 {
83         return params.display != graphics::NoDisplay &&
84                 lyxrc.display_graphics != graphics::NoDisplay;
85 }
86
87
88 string const statusMessage(graphics::Params const & params,
89                            graphics::ImageStatus status)
90 {
91         docstring ret;
92
93         if (!displayGraphic(params))
94                 ret = _("Not shown.");
95         else {
96                 switch (status) {
97                 case graphics::WaitingToLoad:
98                         ret = _("Not shown.");
99                         break;
100                 case graphics::Loading:
101                         ret = _("Loading...");
102                         break;
103                 case graphics::Converting:
104                         ret = _("Converting to loadable format...");
105                         break;
106                 case graphics::Loaded:
107                         ret = _("Loaded into memory. Generating pixmap...");
108                         break;
109                 case graphics::ScalingEtc:
110                         ret = _("Scaling etc...");
111                         break;
112                 case graphics::Ready:
113                         ret = _("Ready to display");
114                         break;
115                 case graphics::ErrorNoFile:
116                         ret = _("No file found!");
117                         break;
118                 case graphics::ErrorConverting:
119                         ret = _("Error converting to loadable format");
120                         break;
121                 case graphics::ErrorLoading:
122                         ret = _("Error loading file into memory");
123                         break;
124                 case graphics::ErrorGeneratingPixmap:
125                         ret = _("Error generating the pixmap");
126                         break;
127                 case graphics::ErrorUnknown:
128                         ret = _("No image");
129                         break;
130                 }
131         }
132
133         // FIXME UNICODE
134         return lyx::to_utf8(ret);
135 }
136
137
138 bool readyToDisplay(graphics::Loader const & loader)
139 {
140         if (!loader.image() || loader.status() != graphics::Ready)
141                 return false;
142         return loader.image()->isDrawable();
143 }
144
145 } // namespace anon
146
147
148 void RenderGraphic::metrics(MetricsInfo & mi, Dimension & dim) const
149 {
150         bool image_ready = displayGraphic(params_) && readyToDisplay(loader_);
151
152         dim.asc = image_ready ? loader_.image()->getHeight() : 50;
153         dim.des = 0;
154
155         if (image_ready) {
156                 dim.wid = loader_.image()->getWidth() +
157                         2 * InsetOld::TEXT_TO_INSET_OFFSET;
158         } else {
159                 int font_width = 0;
160
161                 LyXFont msgFont(mi.base.font);
162                 msgFont.setFamily(LyXFont::SANS_FAMILY);
163
164                 string const justname = onlyFilename(params_.filename);
165                 docstring djust(justname.begin(), justname.end());
166                 if (!justname.empty()) {
167                         msgFont.setSize(LyXFont::SIZE_FOOTNOTE);
168                         font_width = theApp->fontLoader().metrics(msgFont)
169                                 .width(djust);
170                 }
171
172                 string const msg = statusMessage(params_, loader_.status());
173                 if (!msg.empty()) {
174                         docstring dmsg(msg.begin(), msg.end());
175                         msgFont.setSize(LyXFont::SIZE_TINY);
176                         font_width = std::max(font_width, theApp->fontLoader()
177                                 .metrics(msgFont).width(dmsg));
178                 }
179
180                 dim.wid = std::max(50, font_width + 15);
181         }
182
183         dim_ = dim;
184 }
185
186
187 void RenderGraphic::draw(PainterInfo & pi, int x, int y) const
188 {
189         if (displayGraphic(params_)) {
190                 if (loader_.status() == graphics::WaitingToLoad)
191                         loader_.startLoading();
192                 if (!loader_.monitoring())
193                         loader_.startMonitoring();
194         }
195
196         // This will draw the graphics. If the graphics has not been
197         // loaded yet, we draw just a rectangle.
198
199         if (displayGraphic(params_) && readyToDisplay(loader_)) {
200                 pi.pain.image(x + InsetOld::TEXT_TO_INSET_OFFSET,
201                               y - dim_.asc,
202                               dim_.wid - 2 * InsetOld::TEXT_TO_INSET_OFFSET,
203                               dim_.asc + dim_.des,
204                               *loader_.image());
205
206         } else {
207                 pi.pain.rectangle(x + InsetOld::TEXT_TO_INSET_OFFSET,
208                                   y - dim_.asc,
209                                   dim_.wid - 2 * InsetOld::TEXT_TO_INSET_OFFSET,
210                                   dim_.asc + dim_.des,
211                                   LColor::foreground);
212
213                 // Print the file name.
214                 LyXFont msgFont = pi.base.font;
215                 msgFont.setFamily(LyXFont::SANS_FAMILY);
216                 string const justname = onlyFilename(params_.filename);
217
218                 if (!justname.empty()) {
219                         docstring djust(justname.begin(), justname.end());
220                         msgFont.setSize(LyXFont::SIZE_FOOTNOTE);
221                         pi.pain.text(x + InsetOld::TEXT_TO_INSET_OFFSET + 6,
222                                    y - theApp->fontLoader().metrics(msgFont).maxAscent() - 4,
223                                    djust, msgFont);
224                 }
225
226                 // Print the message.
227                 string const msg = statusMessage(params_, loader_.status());
228                 if (!msg.empty()) {
229                         docstring dmsg(msg.begin(), msg.end());
230                         msgFont.setSize(LyXFont::SIZE_TINY);
231                         pi.pain.text(x + InsetOld::TEXT_TO_INSET_OFFSET + 6,
232                                      y - 4, dmsg, msgFont);
233                 }
234         }
235 }