]> git.lyx.org Git - lyx.git/blob - src/graphics/GraphicsCacheItem.C
Herbert's latest graphics patch.
[lyx.git] / src / graphics / GraphicsCacheItem.C
1 /* This file is part of
2  * =================================================
3  * 
4  *          LyX, The Document Processor
5  *          Copyright 1995 Matthias Ettrich.
6  *          Copyright 1995-2001 The LyX Team.
7  *
8  * \author Baruch Even
9  * \author Herbert Voss <voss@lyx.org>
10  * ================================================= */
11
12 #include <config.h>
13
14 #ifdef __GNUG__
15 #pragma implementation
16 #endif
17
18 #include "graphics/GraphicsCache.h"
19 #include "graphics/GraphicsCacheItem.h"
20 #include "frontends/support/LyXImage.h"
21 #include "graphics/ImageLoaderXPM.h"
22 #include "converter.h"
23 #include "support/filetools.h"
24 #include "support/lyxlib.h"
25 #include "lyx_gui_misc.h"
26 #include "debug.h"
27 #include "support/LAssert.h"
28 #include "gettext.h"
29 #include "support/syscall.h"
30 #include "lyxfunc.h"
31
32 using std::endl;
33
34 /*
35  * The order of conversion:
36  *
37  * The c-tor calls convertImage()
38  * 
39  * convertImage() verifies that we need to do conversion, if not it will just
40  * call the loadImage()
41  * if conversion is needed, it will initiate the conversion.
42  *
43  * When the conversion is completed imageConverted() is called, which in turn
44  * calls loadImage().
45  *
46  * Since we currently do everything synchronously, convertImage() calls
47  * imageConverted() right after it does the call to the conversion process.
48 */
49
50 GraphicsCacheItem::GraphicsCacheItem(string const & filename)
51         : imageStatus_(GraphicsCacheItem::Loading)
52 {
53         filename_ = filename;
54         
55         bool success = convertImage(filename);
56         if (! success) // Conversion failed miserably (couldn't even start).
57                 setStatus(ErrorConverting);
58 }
59
60
61 GraphicsCacheItem::~GraphicsCacheItem()
62 {}
63
64
65 GraphicsCacheItem::ImageStatus 
66 GraphicsCacheItem::getImageStatus() const { return imageStatus_; }
67
68
69 void GraphicsCacheItem::setStatus(ImageStatus new_status)
70 {
71         imageStatus_ = new_status;
72 }
73
74
75 LyXImage * 
76 GraphicsCacheItem::getImage() const { return image_.get(); }
77
78
79 void GraphicsCacheItem::imageConverted(bool success)
80 {
81         // Debug output
82         string text = "succeeded";
83         if (!success)
84                 text = "failed";
85         lyxerr << "imageConverted, conversion " << text << "." << endl;
86
87         if (! success) {
88                 lyxerr << "(GraphicsCacheItem::imageConverter) "
89                         "Error converting image." << endl;
90                 setStatus(GraphicsCacheItem::ErrorConverting);
91                 return;
92         }
93
94         // Do the actual image loading from file to memory.
95         loadImage();    
96 }
97
98
99 namespace {
100
101 string const findTargetFormat(string const & from)
102 {
103         typedef ImageLoader::FormatList FormatList;
104         FormatList formats = ImageLoaderXPM().loadableFormats();
105         lyx::Assert(formats.size() > 0); // There must be a format to load from.
106
107         FormatList::const_iterator iter = formats.begin();
108         FormatList::const_iterator end  = formats.end();
109
110         for (; iter != end; ++iter) {
111                 if (converters.isReachable(from, *iter))
112                         break;
113         }
114         if (iter == end) {
115                 // We do not know how to convert the image to something loadable.
116                 lyxerr << "ERROR: Do not know how to convert image." << std::endl;
117                 return string();
118         }
119         return (*iter);
120 }
121
122 } // anon namespace
123
124         
125 bool GraphicsCacheItem::convertImage(string const & filename)
126 {
127         setStatus(GraphicsCacheItem::Converting);
128         string filename_ = string(filename);
129         lyxerr << "try to convert image file: " << filename_ << endl;
130 // maybe that other zip extensions also be useful, especially the
131 // ones that may be declared in texmf/tex/latex/config/graphics.cfg.
132 // for example:
133 /* -----------snip-------------
134           {\DeclareGraphicsRule{.pz}{eps}{.bb}{}%
135            \DeclareGraphicsRule{.eps.Z}{eps}{.eps.bb}{}%
136            \DeclareGraphicsRule{.ps.Z}{eps}{.ps.bb}{}%
137            \DeclareGraphicsRule{.ps.gz}{eps}{.ps.bb}{}%
138            \DeclareGraphicsRule{.eps.gz}{eps}{.eps.bb}{}}}%
139    -----------snip-------------*/
140
141         lyxerr << "GetExtension: " << GetExtension(filename_) << endl;
142         bool zipped = GetExtension(filename_).compare("gz") == 0;
143         if (zipped)
144             filename_ = ChangeExtension(filename_, string());   // snip the ".gz"
145         string const from = getExtFromContents(filename_);      // get the type
146         lyxerr << "GetExtFromContents: " << from << endl;
147         string const to = findTargetFormat(from);
148         lyxerr << "from: " << from << " -> " << to << endl;
149         if (to.empty()) 
150                 return false;
151         // manage zipped files. unzip them first into the tempdir
152         if (zipped) {
153             tempfile = lyx::tempName(string(), filename_);
154             // Run gunzip
155             string const command = "gunzip -c "+filename+" > "+tempfile;
156             Systemcalls one(Systemcalls::System, command); 
157             filename_ = tempfile;
158         }
159         if (from == to) {
160                 // No conversion needed!
161                 // Saves more than just time: prevents the deletion of
162                 // the "to" file after loading when it's the same as the "from"!
163                 tempfile = filename_;
164                 loadImage();    
165                 return true;
166         }
167         // Take only the filename part of the file, without path or extension.
168         string temp = OnlyFilename(filename_);
169         temp = ChangeExtension(filename_, string());
170         
171         // Add some stuff to have it a unique temp file.
172         // This tempfile is deleted in loadImage after it is loaded to memory.
173         tempfile = lyx::tempName(string(), temp);
174         // Remove the temp file, we only want the name...
175         lyx::unlink(tempfile);
176         bool result = converters.convert(0, filename_, tempfile, from, to);
177         tempfile.append(".xpm");
178         // For now we are synchronous
179         imageConverted(result);
180         // Cleanup after the conversion.
181         lyx::unlink(tempfile);
182         if (zipped)
183             lyx::unlink(filename_);
184         tempfile = string();
185         return true;
186 }
187
188
189 // This function gets called from the callback after the image has been
190 // converted successfully.
191 void
192 GraphicsCacheItem::loadImage()
193 {
194         lyxerr << "Loading XPM Image... ";
195
196         ImageLoaderXPM imageLoader;
197         if (imageLoader.loadImage(tempfile) == ImageLoader::OK) {
198                 lyxerr << "Success." << endl;
199                 image_.reset(imageLoader.getImage());
200                 setStatus(GraphicsCacheItem::Loaded);
201         } else {
202                 lyxerr << "Loading " << tempfile << "Failed" << endl;
203                 setStatus(GraphicsCacheItem::ErrorReading);
204         }
205 }