Fix export of graphics images when compiling latex file.

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@7649 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Angus Leeming 2003-09-03 17:23:38 +00:00
parent d80565c905
commit a4fc784124
8 changed files with 245 additions and 120 deletions

View File

@ -1,3 +1,9 @@
2003-09-03 Angus Leeming <leeming@lyx.org>
* insetexternal.C (updateExternal):
* insetgraphics.C (prepareFile): Fix the conversion when exporting to
latex.
2003-09-03 Angus Leeming <leeming@lyx.org> 2003-09-03 Angus Leeming <leeming@lyx.org>
* insetexternal.C: don't bring namespace lyx::support into the global * insetexternal.C: don't bring namespace lyx::support into the global

View File

@ -518,28 +518,33 @@ void InsetExternal::updateExternal(string const & format,
if (external_in_tmpdir && !from_file.empty()) { if (external_in_tmpdir && !from_file.empty()) {
// We are running stuff through LaTeX // We are running stuff through LaTeX
from_file = support::copyFileToDir(buf.tmppath, from_file); string const temp_file =
if (from_file.empty()) support::MakeAbsPath(params_.filename.mangledFilename(),
buf.tmppath);
unsigned long const from_checksum = support::sum(from_file);
unsigned long const temp_checksum = support::sum(temp_file);
// Nothing to do...
if (from_checksum == temp_checksum)
return; return;
// Cannot proceed...
if (!support::copy(from_file, temp_file))
return;
from_file = temp_file;
} }
string const to_file = doSubstitution(params_, buf, string const to_file = doSubstitution(params_, buf,
outputFormat.updateResult); outputFormat.updateResult);
string const abs_to_file = support::MakeAbsPath(to_file, buf.filePath());
support::FileInfo fi(from_file); // Do we need to perform the conversion?
string abs_to_file = to_file; // Yes if to_file does not exist or if from_file is newer than to_file
if (!support::AbsolutePath(to_file)) if (support::compare_timestamps(from_file, abs_to_file) < 0)
abs_to_file = support::MakeAbsPath(to_file, return;
support::OnlyPath(from_file));
support::FileInfo fi2(abs_to_file); string const to_filebase = support::ChangeExtension(to_file, string());
if (fi2.exist() && fi.exist() && converters.convert(&buf, from_file, to_filebase, from_format, to_format);
difftime(fi2.getModificationTime(),
fi.getModificationTime()) >= 0) {
} else {
string const to_filebase = support::ChangeExtension(to_file, string());
converters.convert(&buf, from_file, to_filebase,
from_format, to_format);
}
} }

View File

@ -74,6 +74,7 @@ TODO
#include "frontends/Alert.h" #include "frontends/Alert.h"
#include "frontends/Dialogs.h" #include "frontends/Dialogs.h"
#include "support/LAssert.h"
#include "support/filetools.h" #include "support/filetools.h"
#include "support/lyxalgo.h" // lyx::count #include "support/lyxalgo.h" // lyx::count
#include "support/lyxlib.h" // float_equal #include "support/lyxlib.h" // float_equal
@ -81,11 +82,13 @@ TODO
#include "support/systemcall.h" #include "support/systemcall.h"
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/tuple/tuple.hpp>
#include <algorithm> // For the std::max #include <algorithm> // For the std::max
// set by Exporters // set by Exporters
namespace support = lyx::support;
using namespace lyx::support; using namespace lyx::support;
using std::ostream; using std::ostream;
@ -328,14 +331,79 @@ string const InsetGraphics::createLatexOptions() const
} }
namespace {
enum CopyStatus {
SUCCESS,
FAILURE,
IDENTICAL_PATHS,
IDENTICAL_CONTENTS
};
std::pair<CopyStatus, string> const
copyToDirIfNeeded(string const & file_in, string const & dir)
{
using support::rtrim;
support::Assert(AbsolutePath(file_in));
string const only_path = support::OnlyPath(file_in);
if (rtrim(support::OnlyPath(file_in) , "/") == rtrim(dir, "/"))
return std::make_pair(IDENTICAL_PATHS, file_in);
string mangled;
if (support::zippedFile(file_in)) {
string const ext = GetExtension(file_in);
string const unzipped = support::unzippedFileName(file_in);
mangled = FileName(unzipped).mangledFilename();
mangled += "." + ext;
} else
mangled = FileName(file_in).mangledFilename();
string const file_out = support::MakeAbsPath(mangled, dir);
unsigned long const checksum_in = support::sum(file_in);
unsigned long const checksum_out = support::sum(file_out);
if (checksum_in == checksum_out)
// Nothing to do...
return std::make_pair(IDENTICAL_CONTENTS, file_out);
bool const success = support::copy(file_in, file_out);
if (!success) {
lyxerr[Debug::GRAPHICS]
<< support::bformat(_("Could not copy the file\n%1$s\n"
"into the temporary directory."),
file_in)
<< std::endl;
}
CopyStatus status = success ? SUCCESS : FAILURE;
return std::make_pair(status, file_out);
}
string const stripExtensionIfPossible(string const & file, string const & to)
{
// No conversion is needed. LaTeX can handle the graphic file as is.
// This is true even if the orig_file is compressed.
if (formats.getFormat(to)->extension() == GetExtension(file))
return RemoveExtension(file);
return file;
}
} // namespace anon
string const InsetGraphics::prepareFile(Buffer const & buf, string const InsetGraphics::prepareFile(Buffer const & buf,
LatexRunParams const & runparams) const LatexRunParams const & runparams) const
{ {
// LaTeX can cope if the graphics file doesn't exist, so just return the
// filename.
string orig_file = params().filename.absFilename(); string orig_file = params().filename.absFilename();
string const rel_file = params().filename.relFilename(buf.filePath()); string const rel_file = params().filename.relFilename(buf.filePath());
// LaTeX can cope if the graphics file doesn't exist, so just return the
// filename.
if (!IsFileReadable(orig_file)) { if (!IsFileReadable(orig_file)) {
lyxerr[Debug::GRAPHICS] lyxerr[Debug::GRAPHICS]
<< "InsetGraphics::prepareFile\n" << "InsetGraphics::prepareFile\n"
@ -343,11 +411,11 @@ string const InsetGraphics::prepareFile(Buffer const & buf,
return rel_file; return rel_file;
} }
bool const zipped = zippedFile(orig_file);
// If the file is compressed and we have specified that it // If the file is compressed and we have specified that it
// should not be uncompressed, then just return its name and // should not be uncompressed, then just return its name and
// let LaTeX do the rest! // let LaTeX do the rest!
bool const zipped = params().filename.isZipped();
if (zipped && params().noUnzip) { if (zipped && params().noUnzip) {
lyxerr[Debug::GRAPHICS] lyxerr[Debug::GRAPHICS]
<< "\tpass zipped file to LaTeX but with full path.\n"; << "\tpass zipped file to LaTeX but with full path.\n";
@ -361,95 +429,85 @@ string const InsetGraphics::prepareFile(Buffer const & buf,
string temp_file = orig_file; string temp_file = orig_file;
if (zipped) { if (zipped) {
// Uncompress the file if necessary. CopyStatus status;
// If it has been uncompressed in a previous call to boost::tie(status, temp_file) =
// prepareFile, do nothing. copyToDirIfNeeded(orig_file, buf.tmppath);
temp_file = MakeAbsPath(OnlyFilename(temp_file), buf.tmppath);
lyxerr[Debug::GRAPHICS]
<< "\ttemp_file: " << temp_file << endl;
if (graphic_->hasFileChanged() || !IsFileReadable(temp_file)) {
bool const success = copy(orig_file, temp_file);
lyxerr[Debug::GRAPHICS]
<< "\tCopying zipped file from "
<< orig_file << " to " << temp_file
<< (success ? " succeeded\n" : " failed\n");
} else
lyxerr[Debug::GRAPHICS]
<< "\tzipped file " << temp_file
<< " exists! Maybe no tempdir ...\n";
orig_file = unzipFile(temp_file);
lyxerr[Debug::GRAPHICS]
<< "\tunzipped to " << orig_file << endl;
}
if (status == FAILURE)
return orig_file;
orig_file = unzippedFileName(temp_file);
if (!IsFileReadable(orig_file)) {
unzipFile(temp_file);
lyxerr[Debug::GRAPHICS]
<< "\tunzipped to " << orig_file << endl;
}
}
string const from = getExtFromContents(orig_file); string const from = getExtFromContents(orig_file);
string const to = findTargetFormat(from, runparams); string const to = findTargetFormat(from, runparams);
lyxerr[Debug::GRAPHICS] lyxerr[Debug::GRAPHICS]
<< "\t we have: from " << from << " to " << to << '\n'; << "\t we have: from " << from << " to " << to << '\n';
if (from == to && !lyxrc.use_tempdir) { if (from == to && !lyxrc.use_tempdir)
// No conversion is needed. LaTeX can handle the return stripExtensionIfPossible(orig_file, to);
// graphic file as is.
// This is true even if the orig_file is compressed.
if (formats.getFormat(to)->extension() == GetExtension(orig_file))
return RemoveExtension(orig_file);
return orig_file;
}
// We're going to be running the exported buffer through the LaTeX // We're going to be running the exported buffer through the LaTeX
// compiler, so must ensure that LaTeX can cope with the graphics // compiler, so must ensure that LaTeX can cope with the graphics
// file format. // file format.
// Perform all these manipulations on a temporary file if possible.
// If we are not using a temp dir, then temp_file contains the
// original file.
// to allow files with the same name in different dirs
// we manipulate the original file "any.dir/file.ext"
// to "any_dir_file.ext"! changing the dots in the
// dirname is important for the use of ChangeExtension
lyxerr[Debug::GRAPHICS] lyxerr[Debug::GRAPHICS]
<< "\tthe orig file is: " << orig_file << endl; << "\tthe orig file is: " << orig_file << endl;
bool conversion_needed = true;
if (lyxrc.use_tempdir) { if (lyxrc.use_tempdir) {
temp_file = copyFileToDir(buf.tmppath, orig_file); CopyStatus status;
if (temp_file.empty()) { boost::tie(status, temp_file) =
string str = bformat(_("Could not copy the file\n%1$s\n" copyToDirIfNeeded(orig_file, buf.tmppath);
"into the temporary directory."),
orig_file);
Alert::error(_("Graphics display failed"), str);
return orig_file;
}
if (from == to) { if (status == FAILURE)
// No conversion is needed. LaTeX can handle the return orig_file;
// graphic file as is. else if (status == IDENTICAL_CONTENTS)
if (formats.getFormat(to)->extension() == GetExtension(orig_file)) conversion_needed = false;
return RemoveExtension(temp_file); }
return temp_file;
} if (from == to)
return stripExtensionIfPossible(temp_file, to);
string const to_file_base = RemoveExtension(temp_file);
string const to_file = ChangeExtension(to_file_base, to);
// Do we need to perform the conversion?
// Yes if to_file does not exist or if temp_file is newer than to_file
if (!conversion_needed ||
support::compare_timestamps(temp_file, to_file) < 0) {
lyxerr[Debug::GRAPHICS]
<< bformat(_("No conversion of %1$s is needed after all"),
rel_file)
<< std::endl;
return to_file_base;
} }
string const outfile_base = RemoveExtension(temp_file);
lyxerr[Debug::GRAPHICS] lyxerr[Debug::GRAPHICS]
<< "\tThe original file is " << orig_file << "\n" << "\tThe original file is " << orig_file << "\n"
<< "\tA copy has been made and convert is to be called with:\n" << "\tA copy has been made and convert is to be called with:\n"
<< "\tfile to convert = " << temp_file << '\n' << "\tfile to convert = " << temp_file << '\n'
<< "\toutfile_base = " << outfile_base << '\n' << "\tto_file_base = " << to_file_base << '\n'
<< "\t from " << from << " to " << to << '\n'; << "\t from " << from << " to " << to << '\n';
// if no special converter defined, than we take the default one // if no special converter defined, than we take the default one
// from ImageMagic: convert from:inname.from to:outname.to // from ImageMagic: convert from:inname.from to:outname.to
if (!converters.convert(&buf, temp_file, outfile_base, from, to)) { if (!converters.convert(&buf, temp_file, to_file_base, from, to)) {
string const command = string const command =
"sh " + LibFileSearch("scripts", "convertDefault.sh") + "sh " + LibFileSearch("scripts", "convertDefault.sh") +
' ' + from + ':' + temp_file + ' ' + ' ' + from + ':' + temp_file + ' ' +
to + ':' + outfile_base + '.' + to; to + ':' + to_file_base + '.' + to;
lyxerr[Debug::GRAPHICS] lyxerr[Debug::GRAPHICS]
<< "No converter defined! I use convertDefault.sh:\n\t" << "No converter defined! I use convertDefault.sh:\n\t"
<< command << endl; << command << endl;
Systemcall one; Systemcall one;
one.startscript(Systemcall::Wait, command); one.startscript(Systemcall::Wait, command);
if (!IsFileReadable(ChangeExtension(outfile_base, to))) { if (!IsFileReadable(ChangeExtension(to_file_base, to))) {
string str = bformat(_("No information for converting %1$s " string str = bformat(_("No information for converting %1$s "
"format files to %2$s.\n" "format files to %2$s.\n"
"Try defining a convertor in the preferences."), from, to); "Try defining a convertor in the preferences."), from, to);
@ -457,7 +515,7 @@ string const InsetGraphics::prepareFile(Buffer const & buf,
} }
} }
return RemoveExtension(temp_file); return to_file_base;
} }

View File

@ -1,3 +1,13 @@
2003-09-03 Angus Leeming <leeming@lyx.org>
* filename.[Ch] (FileName): new c-tor takes abs_filename arg.
(mangledFilename): new function, returning a mangled version of the
absolute file name, suitable for use in the temp dir when, for example,
converting an image file to another format.
* filetools.[Ch] (copyFileToDir): removed.
(compare_timestamps): new function.
2003-09-03 Angus Leeming <leeming@lyx.org> 2003-09-03 Angus Leeming <leeming@lyx.org>
* translator.h: Assert is in namespace lyx::support... * translator.h: Assert is in namespace lyx::support...
@ -22,7 +32,7 @@
2003-07-29 Lars Gullik Bjønnes <larsbj@gullik.net> 2003-07-29 Lars Gullik Bjønnes <larsbj@gullik.net>
* Makefile.am: contidionalize USE_COMPRESSION * Makefile.am: conditionalize USE_COMPRESSION.
2003-07-28 Lars Gullik Bjønnes <larsbj@gullik.net> 2003-07-28 Lars Gullik Bjønnes <larsbj@gullik.net>

View File

@ -13,6 +13,8 @@
#include "filename.h" #include "filename.h"
#include "support/filetools.h" #include "support/filetools.h"
#include "lstrings.h"
#include "LAssert.h"
namespace lyx { namespace lyx {
@ -24,6 +26,13 @@ FileName::FileName()
{} {}
FileName::FileName(string const & abs_filename, bool save_abs)
: name_(abs_filename), save_abs_path_(save_abs)
{
Assert(AbsolutePath(name_));
}
void FileName::set(string const & name, string const & buffer_path) void FileName::set(string const & name, string const & buffer_path)
{ {
save_abs_path_ = AbsolutePath(name); save_abs_path_ = AbsolutePath(name);
@ -49,6 +58,32 @@ string const FileName::outputFilename(string const & path) const
} }
string const FileName::mangledFilename() const
{
string mname = os::slashify_path(name_);
// Remove the extension.
mname = ChangeExtension(name_, string());
// Replace '/' in the file name with '_'
mname = subst(mname, "/", "_");
// Replace '.' in the file name with '_'
mname = subst(mname, ".", "_");
// Add the extension back on
return ChangeExtension(mname, GetExtension(name_));
}
bool FileName::isZipped() const
{
return zippedFile(name_);
}
string const FileName::unzippedFilename() const
{
return unzippedFileName(name_);
}
bool operator==(FileName const & lhs, FileName const & rhs) bool operator==(FileName const & lhs, FileName const & rhs)
{ {
return lhs.absFilename() == rhs.absFilename() && return lhs.absFilename() == rhs.absFilename() &&
@ -61,5 +96,5 @@ bool operator!=(FileName const & lhs, FileName const & rhs)
return !(lhs == rhs); return !(lhs == rhs);
} }
} //namespace support } // namespace support
} // namespace lyx } // namespace lyx

View File

@ -22,11 +22,15 @@ namespace support {
class FileName { class FileName {
public: public:
FileName(); FileName();
/** \param filename the file in question. Must have an absolute path.
* \param save_abs_path how is the file to be output to file?
*/
FileName(string const & abs_filename, bool save_abs_path = true);
/** \param filename the file in question. May have either a relative /** \param filename the file in question. May have either a relative
or an absolute path. * or an absolute path.
\param buffer_path if \c filename has a relative path, generate * \param buffer_path if \c filename has a relative path, generate
the absolute path using this. * the absolute path using this.
*/ */
void set(string const & filename, string const & buffer_path); void set(string const & filename, string const & buffer_path);
@ -39,6 +43,16 @@ public:
string const relFilename(string const & buffer_path = string()) const; string const relFilename(string const & buffer_path = string()) const;
/// \param buf_path if empty, uses `pwd` /// \param buf_path if empty, uses `pwd`
string const outputFilename(string const & buf_path = string()) const; string const outputFilename(string const & buf_path = string()) const;
/** \return a mangled version of the absolute file name,
* suitable for use in the temp dir when, for example, converting
* an image file to another format.
*/
string const mangledFilename() const;
/// \return true if the file is compressed.
bool isZipped() const;
/// \return the absolute file name without its .gz, .z, .Z extension
string const unzippedFilename() const;
private: private:
string name_; string name_;

View File

@ -1134,10 +1134,18 @@ bool zippedFile(string const & name)
} }
string const unzippedFileName(string const & zipped_file)
{
string const ext = GetExtension(zipped_file);
if (ext == "gz" || ext == "z" || ext == "Z")
return ChangeExtension(zipped_file, string());
return "unzipped_" + zipped_file;
}
string const unzipFile(string const & zipped_file) string const unzipFile(string const & zipped_file)
{ {
string const file = ChangeExtension(zipped_file, string()); string const tempfile = unzippedFileName(zipped_file);
string const tempfile = tempName(string(), file);
// Run gunzip // Run gunzip
string const command = "gunzip -c " + zipped_file + " > " + tempfile; string const command = "gunzip -c " + zipped_file + " > " + tempfile;
Systemcall one; Systemcall one;
@ -1333,43 +1341,29 @@ string const readBB_from_PSFile(string const & file)
} }
string const copyFileToDir(string const & path, string const & file_in) int compare_timestamps(string const & file1, string const & file2)
{ {
Assert(AbsolutePath(path)); Assert(AbsolutePath(file1) && AbsolutePath(file2));
// First, make the file path relative to path.
string file_out = MakeRelPath(path, NormalizePath(file_in));
file_out = os::slashify_path(file_out);
// Now generate a unique filename.
// Remove the extension.
file_out = ChangeExtension(file_out, string());
// Replace '/' in the file name with '_'
file_out = subst(file_out, "/", "_");
// Replace '.' in the file name with '_'
file_out = subst(file_out, ".", "_");
// Append a unique ID
// static int id;
// file_out += '_' + tostr(id++);
// Add the extension back on
file_out = ChangeExtension(file_out, GetExtension(file_in));
// Put this file in the buffer's temp dir
file_out = MakeAbsPath(file_out, path);
// If the original is newer than the copy, then copy the original // If the original is newer than the copy, then copy the original
// to the new directory. // to the new directory.
FileInfo fi(file_in); FileInfo f1(file1);
FileInfo fi2(file_out); FileInfo f2(file2);
bool success = true; int cmp = 0;
if (fi.exist()) { if (f1.exist() && f2.exist()) {
if (!fi2.exist() || double const tmp = difftime(f1.getModificationTime(),
difftime(fi.getModificationTime(), f2.getModificationTime());
fi2.getModificationTime()) >= 0) if (tmp != 0)
success = copy(file_in, file_out); cmp = tmp > 0 ? 1 : -1;
} else if (f1.exist()) {
cmp = 1;
} else if (f2.exist()) {
cmp = -1;
} }
return success ? file_out : string(); return cmp;
} }
} //namespace support } //namespace support

View File

@ -143,6 +143,9 @@ string const getExtFromContents(string const & name);
/// check for zipped file /// check for zipped file
bool zippedFile(string const & name); bool zippedFile(string const & name);
/// \return the name that LyX will give to the unzipped file.
string const unzippedFileName(string const & zipped_file);
/// unzip a file /// unzip a file
string const unzipFile(string const & zipped_file); string const unzipFile(string const & zipped_file);
@ -210,14 +213,14 @@ void removeAutosaveFile(string const & filename);
/// read the BoundingBox entry from a ps/eps/pdf-file /// read the BoundingBox entry from a ps/eps/pdf-file
string const readBB_from_PSFile(string const & file); string const readBB_from_PSFile(string const & file);
/** Copy \c file to directory \c path. The file name is manipulated /** \param file1, file2 the two files to be compared. Must have absolute paths.
so that eg some/path/to/file becomes some_path_to_file. * \returns 1 if \c file1 has a more recent timestamp than \c file2,
\param path where to put the file * 0 if their timestamps are the same,
\param file the file that is copied * -1 if \c file2 has a more recent timestamp than \c file1.
\returns this file name if the file is copied successfully, else * If one of the files does not exist, the return value indicates the file
\returns an empty string. * which does exist. Eg, if \c file1 exists but \c file2 does not, return 1.
*/ */
string const copyFileToDir(string const & path, string const & file); int compare_timestamps(string const & file1, string const & file2);
typedef std::pair<int, string> cmd_ret; typedef std::pair<int, string> cmd_ret;