+2001-02-20 Baruch Even <baruch@ev-en.org>
+
+ * GraphicsCache.C: Changed to use shared_ptr<GraphicsCacheItem>
+ instead of a pure pointer.
+
+ * GraphicsCacheItem.[Ch]:
+ * GraphicsCacheItem_pimpl.[Ch]: Collapsed them into GraphicsCacheItem,
+ removed the reference counting that was inside. Also fixed a bug where
+ a temporary file wouldn't get erased.
+
+ * ImageLoader.[Ch]: Changed the semantics of the image_ pointers usage.
+ Ownership is now dropped when the caller requests the image_ pointer.
+
2001-02-20 Baruch Even <baruch@ev-en.org>
* GraphicsCache.C: Cleared up the confusion on when and how it is
#endif
#include "GraphicsCache.h"
+#include "GraphicsCacheItem.h"
#include "support/LAssert.h"
}
-GraphicsCacheItem *
+GraphicsCache::shared_ptr_item
GraphicsCache::addFile(string const & filename)
{
CacheType::iterator it = cache.find(filename);
if (it != cache.end()) {
- return new GraphicsCacheItem( *((*it).second) );
+ return (*it).second;
}
- GraphicsCacheItem * cacheItem = new GraphicsCacheItem();
- if (cacheItem == 0)
- return 0;
-
- cacheItem->setFilename(filename);
+ shared_ptr_item cacheItem(new GraphicsCacheItem(filename));
+ if (cacheItem.get() == 0)
+ return cacheItem;
cache[filename] = cacheItem;
-
- // We do not want to return the main cache object, otherwise when the
- // will destroy their copy they will destroy the main copy.
- return new GraphicsCacheItem( *cacheItem );
+
+ // GraphicsCacheItem_ptr is a shared_ptr and thus reference counted,
+ // it is safe to return it directly.
+ return cacheItem;
}
#include "LString.h"
#include "GraphicsCacheItem.h"
#include <boost/utility.hpp>
+#include <boost/smart_ptr.hpp>
+
+class GraphicsCacheItem;
/** GraphicsCache is the manager of the image cache.
It is responsible of create the GraphicsCacheItem's and maintain them.
/// Get the instance of the class.
static GraphicsCache * getInstance();
+ typedef boost::shared_ptr<GraphicsCacheItem> shared_ptr_item;
+
/// Add a file to the cache.
- GraphicsCacheItem * addFile(string const & filename);
+ shared_ptr_item addFile(string const & filename);
private:
/// Remove a cache item if it's count has gone to zero.
/// Holder of the single instance of the class.
static GraphicsCache * singleton;
///
- typedef std::map<string, GraphicsCacheItem *> CacheType;
+ typedef std::map<string, shared_ptr_item> CacheType;
///
CacheType cache;
#include "graphics/GraphicsCache.h"
#include "graphics/GraphicsCacheItem.h"
-#include "graphics/GraphicsCacheItem_pimpl.h"
#include "frontends/support/LyXImage.h"
+#include "graphics/ImageLoaderXPM.h"
+#include "support/filetools.h"
+#include "support/lyxlib.h"
+#include "support/syscall.h"
+#include "debug.h"
-GraphicsCacheItem::GraphicsCacheItem()
- : pimpl(new GraphicsCacheItem_pimpl)
+using std::endl;
+
+GraphicsCacheItem::GraphicsCacheItem(string const & filename)
+ : imageStatus_(GraphicsCacheItem::Loading)
{
- pimpl->refCount = 1;
+ filename_ = filename;
+
+ renderXPM(filename);
+ // For now we do it synchronously
+ imageConverted(0);
}
GraphicsCacheItem::~GraphicsCacheItem()
-{
- destroy();
-}
+{}
-bool
-GraphicsCacheItem::setFilename(string const & filename)
-{
- filename_ = filename;
- return pimpl->setFilename(filename);
-}
-
+GraphicsCacheItem::ImageStatus
+GraphicsCacheItem::getImageStatus() const { return imageStatus_; }
-GraphicsCacheItem::GraphicsCacheItem(GraphicsCacheItem const & gci)
- : pimpl(0)
-{
- // copy will set the actual value of the pimpl.
- copy(gci);
-}
-GraphicsCacheItem &
-GraphicsCacheItem::operator=(GraphicsCacheItem const & gci)
-{
- // Are we trying to copy the object onto itself.
- if (this == &gci)
- return *this;
+LyXImage *
+GraphicsCacheItem::getImage() const { return image_.get(); }
- // Destroy old copy
- destroy();
- // And then copy new object.
- copy(gci);
+void
+GraphicsCacheItem::imageConverted(int retval)
+{
+ lyxerr << "imageConverted, retval=" << retval << endl;
- return *this;
-}
+ if (retval) {
+ lyxerr << "(GraphicsCacheItem::imageConverter) "
+ "Error converting image." << endl;
+ imageStatus_ = GraphicsCacheItem::ErrorConverting;
+ return;
+ }
-GraphicsCacheItem *
-GraphicsCacheItem::Clone() const
-{
- return new GraphicsCacheItem(*this);
+ // Do the actual image loading from XPM to memory.
+ loadXPMImage();
}
-void
-GraphicsCacheItem::copy(GraphicsCacheItem const & gci)
+
+bool
+GraphicsCacheItem::renderXPM(string const & filename)
{
- pimpl = gci.pimpl;
- ++(pimpl->refCount);
+ // Create the command to do the conversion, this depends on ImageMagicks
+ // convert program.
+ string command = "convert ";
+ command += filename;
+ command += " XPM:";
+
+ // Take only the filename part of the file, without path or extension.
+ string temp = OnlyFilename(filename);
+ temp = ChangeExtension(filename, string());
+
+ // Add some stuff to have it a unique temp file.
+ // This tempfile is deleted in loadXPMImage after it is loaded to memory.
+ tempfile = lyx::tempName(string(), temp);
+ // Remove the temp file, we only want the name...
+ lyx::unlink(tempfile);
+ tempfile = ChangeExtension(tempfile, ".xpm");
+
+ command += tempfile;
+
+ // Run the convertor.
+ lyxerr << "Launching convert to xpm, command=" << command << endl;
+ Systemcalls syscall;
+ syscall.startscript(Systemcalls::Wait, command);
+
+ return true;
}
+// This function gets called from the callback after the image has been
+// converted successfully.
void
-GraphicsCacheItem::destroy()
+GraphicsCacheItem::loadXPMImage()
{
- if (!pimpl)
- return;
-
- --(pimpl->refCount);
- if (pimpl->refCount == 0) {
- delete pimpl;
- pimpl = 0;
-
- GraphicsCache * gc = GraphicsCache::getInstance();
- gc->removeFile(filename_);
+ lyxerr << "Loading XPM Image... ";
+
+ ImageLoaderXPM imageLoader;
+ if (imageLoader.loadImage(tempfile) == ImageLoader::OK) {
+ lyxerr << "Success." << endl;
+ image_.reset(imageLoader.getImage());
+ imageStatus_ = GraphicsCacheItem::Loaded;
+ } else {
+ lyxerr << "Fail." << endl;
+ imageStatus_ = GraphicsCacheItem::ErrorReading;
}
-}
-
-GraphicsCacheItem::ImageStatus
-GraphicsCacheItem::getImageStatus() const { return pimpl->imageStatus_; }
-
-LyXImage *
-GraphicsCacheItem::getImage() const { return pimpl->getImage(); }
+ // remove the xpm file now.
+ lyx::unlink(tempfile);
+ // and remove the reference to the filename.
+ tempfile = string();
+}
#include XPM_H_LOCATION
#include "LString.h"
+#include <boost/utility.hpp>
+#include <boost/smart_ptr.hpp>
+
#include "sigc++/signal_system.h"
#ifdef SIGC_CXX_NAMESPACES
using SigC::Signal0;
#endif
-/* (Baruch Even 2000-08-05)
- * This has a major drawback: it is only designed for X servers, no easy
- * porting to non X-server based platform is offered right now, this is done
- * in order to get a first version out of the door.
- *
- * Later versions should consider how to do this with more platform
- * independence, this will probably involve changing the Painter class too.
- */
-
-class GraphicsCacheItem_pimpl;
class LyXImage;
/// A GraphicsCache item holder.
-class GraphicsCacheItem {
+class GraphicsCacheItem : public noncopyable {
public:
+ /// c-tor
+ GraphicsCacheItem(string const & filename);
/// d-tor, frees the image structures.
~GraphicsCacheItem();
- /// copy c-tor.
- GraphicsCacheItem(GraphicsCacheItem const &);
- /// Assignment operator.
- GraphicsCacheItem & operator=(GraphicsCacheItem const &);
/// Return a pixmap that can be displayed on X server.
LyXImage * getImage() const;
*/
void imageConverted(int retval);
- /// Create another copy of the object.
- GraphicsCacheItem * Clone() const;
-
private:
- /// Private c-tor so that only GraphicsCache can create an instance.
- GraphicsCacheItem();
-
- /// internal copy mechanism.
- void copy(GraphicsCacheItem const &);
- /// internal destroy mechanism.
- void destroy();
-
- /// Set the filename this item will be pointing too.
- bool setFilename(string const & filename);
-
- ///
- friend class GraphicsCache;
-
- ///
- GraphicsCacheItem_pimpl * pimpl;
+ bool renderXPM(string const & filename);
+ void loadXPMImage();
/** The filename we refer too.
This is used when removing ourselves from the cache.
*/
string filename_;
+ /// The temporary file that we use
+ string tempfile;
+ /// The image status
+ ImageStatus imageStatus_;
+ /// The image (if it got loaded)
+ boost::scoped_ptr<LyXImage> image_;
};
#endif
+++ /dev/null
-// -*- C++ -*-
-/* This file is part of
- * =================================================
- *
- * LyX, The Document Processor
- * Copyright 1995 Matthias Ettrich.
- * Copyright 1995-2000 The LyX Team.
- *
- * This file Copyright 2000 Baruch Even
- * ================================================= */
-
-#include <config.h>
-
-#include <map>
-
-#include FORMS_H_LOCATION
-
-#ifdef __GNUG__
-#pragma implementation
-#endif
-
-#include "GraphicsCacheItem.h"
-#include "GraphicsCacheItem_pimpl.h"
-
-#include "frontends/support/LyXImage.h"
-#include "ImageLoaderXPM.h"
-#include "support/filetools.h"
-#include "debug.h"
-#include "support/LAssert.h"
-
-using std::endl;
-using std::map;
-
-
-GraphicsCacheItem_pimpl::GraphicsCacheItem_pimpl()
- : imageStatus_(GraphicsCacheItem::Loading),
- image_(0), imageLoader(0), refCount(0)
-{}
-
-
-GraphicsCacheItem_pimpl::~GraphicsCacheItem_pimpl()
-{
- delete image_; image_ = 0;
- delete imageLoader; imageLoader = 0;
-}
-
-
-bool
-GraphicsCacheItem_pimpl::setFilename(string const & filename)
-{
- imageLoader = new ImageLoaderXPM();
- imageStatus_ = GraphicsCacheItem::Loading;
-
- if (renderXPM(filename))
- return true;
-
- return false;
-}
-
-
-/*** Callback method ***/
-
-typedef map<string, GraphicsCacheItem_pimpl*> CallbackMap;
-static CallbackMap callbackMap;
-
-
-static
-void callback(string cmd, int retval)
-{
- lyxerr << "callback, cmd=" << cmd << ", retval=" << retval << endl;
-
- GraphicsCacheItem_pimpl * item = callbackMap[cmd];
- callbackMap.erase(cmd);
-
- item->imageConverted(retval);
-}
-
-
-void
-GraphicsCacheItem_pimpl::imageConverted(int retval)
-{
- lyxerr << "imageConverted, retval=" << retval << endl;
-
- if (retval) {
- lyxerr << "(GraphicsCacheItem_pimpl::imageConverter) "
- "Error converting image." << endl;
- imageStatus_ = GraphicsCacheItem::ErrorConverting;
- return;
- }
-
- // Do the actual image loading from XPM to memory.
- loadXPMImage();
-}
-
-/**********************/
-
-bool
-GraphicsCacheItem_pimpl::renderXPM(string const & filename)
-{
- // Create the command to do the conversion, this depends on ImageMagicks
- // convert program.
- string command = "convert ";
- command += filename;
- command += " XPM:";
-
- // Take only the filename part of the file, without path or extension.
- string temp = OnlyFilename(filename);
- temp = ChangeExtension(filename, string());
-
- // Add some stuff to have it a unique temp file.
- // This tempfile is deleted in loadXPMImage after it is loaded to memory.
- xpmfile = lyx::tempName(string(), temp);
- xpmfile = ChangeExtension(xpmfile, ".xpm");
-
- command += xpmfile;
-
- // Set the callback mapping to point to us.
- callbackMap[command] = this;
-
- // Run the convertor.
- // There is a problem with running it asyncronously, it doesn't return
- // to call the callback, so until the Systemcalls mechanism is fixed
- // I use the syncronous method.
- lyxerr << "Launching convert to xpm, command=" << command << endl;
-// syscall.startscript(Systemcalls::DontWait, command, &callback);
- syscall.startscript(Systemcalls::Wait, command, &callback);
-
- return true;
-}
-
-
-// This function gets called from the callback after the image has been
-// converted successfully.
-void
-GraphicsCacheItem_pimpl::loadXPMImage()
-{
- lyxerr << "Loading XPM Image... ";
-
- if (imageLoader->loadImage(xpmfile) == ImageLoader::OK) {
- lyxerr << "Success." << endl;
- image_ = imageLoader->getImage();
- imageStatus_ = GraphicsCacheItem::Loaded;
- } else {
- lyxerr << "Fail." << endl;
- imageStatus_ = GraphicsCacheItem::ErrorReading;
- }
-
- // remove the xpm file now.
- lyx::unlink(xpmfile);
- // and remove the reference to the filename.
- xpmfile = string();
-}
+++ /dev/null
-// -*- C++ -*-
-/* This file is part of
- * =================================================
- *
- * LyX, The Document Processor
- * Copyright 1995 Matthias Ettrich.
- * Copyright 1995-2000 The LyX Team.
- *
- * This file Copyright 2000 Baruch Even
- * ================================================= */
-
-#ifndef GRAPHICSCACHEITEM_PIMPL_H
-#define GRAPHICSCACHEITEM_PIMPL_H
-
-#include <config.h>
-
-#ifdef __GNUG__
-#pragma interface
-#endif
-
-#include "graphics/GraphicsCacheItem.h"
-
-#include XPM_H_LOCATION
-#include "LString.h"
-#include "graphics/ImageLoader.h"
-#include "support/syscall.h"
-
-#include "sigc++/signal_system.h"
-#ifdef SIGC_CXX_NAMESPACES
-using SigC::Signal0;
-#endif
-
-class LyXImage;
-
-/// A GraphicsCache item holder.
-class GraphicsCacheItem_pimpl {
-public:
- /// d-tor, frees the image structures.
- ~GraphicsCacheItem_pimpl();
-
- /// Return a pixmap that can be displayed on X server.
- LyXImage * getImage() const { return image_; };
-
- typedef GraphicsCacheItem::ImageStatus ImageStatus;
-
- /// Is the pixmap ready for display?
- ImageStatus getImageStatus() const;
-
- /** Get a notification when the image conversion is done.
- used by an internal callback mechanism. */
- void imageConverted(int retval);
-
-private:
- /// Private c-tor so that only GraphicsCache can create an instance.
- GraphicsCacheItem_pimpl();
-
- /// Set the filename this item will be pointing too.
- bool setFilename(string const & filename);
-
- /// Create an XPM file version of the image.
- bool renderXPM(string const & filename);
-
- /// Load the image from XPM to memory Pixmap
- void loadXPMImage();
-
- ///
- friend class GraphicsCacheItem;
-
- /// The file name of the XPM file.
- string xpmfile;
- /// Is the pixmap loaded?
- ImageStatus imageStatus_;
- /// The image pixmap
- LyXImage * image_;
- /// The rendering object.
- ImageLoader * imageLoader;
-
- /// The system caller, runs the convertor.
- Systemcalls syscall;
-
- /// The reference count
- int refCount;
-};
-
-#endif
freeImage();
}
+void
+ImageLoader::freeImage()
+{
+ delete image_;
+ image_ = 0;
+}
+
bool ImageLoader::isImageFormatOK(string const & /*filename*/) const
{
return false;
void ImageLoader::setImage(LyXImage * image)
{
- freeImage();
-
image_ = image;
}
-void ImageLoader::freeImage()
+LyXImage * ImageLoader::getImage()
{
- delete image_;
+ LyXImage * tmp = image_;
image_ = 0;
+ return tmp;
}
ImageLoader::FormatList const
/// Start loading the image file.
ImageLoader::Result loadImage(string const & filename);
- /// Get the last rendered pixmap. Returns 0 if no image is ready.
- LyXImage * getImage() const { return image_; };
+ /** Get the last rendered pixmap. Returns 0 if no image is ready.
+ *
+ * It is a one time operation, that is, after you get the image
+ * you are completely responsible to destroy it and the ImageLoader
+ * will not know about the image.
+ *
+ * This way we avoid deleting the image if you still use it and the
+ * ImageLoader is destructed, and if you don't use it we get to
+ * destruct the image to avoid memory leaks.
+ */
+ LyXImage * getImage();
/// Return the list of loadable formats.
virtual FormatList const loadableFormats() const;
/// Free the loaded image.
void freeImage();
- /// The loaded image.
+ /// The loaded image. An auto_ptr would be great here, but it's not
+ /// available everywhere (gcc 2.95.2 doesnt have it).
LyXImage * image_;
};
GraphicsCache.C \
GraphicsCacheItem.h \
GraphicsCacheItem.C \
- GraphicsCacheItem_pimpl.h \
- GraphicsCacheItem_pimpl.C \
ImageLoaderXPM.h \
ImageLoaderXPM.C \
ImageLoader.h \
+2001-02-21 Baruch Even <baruch@ev-en.org>
+
+ * insetgraphics.[Ch]: Changed to use boost::shared_ptr<GraphicsCacheItem>
+ instead of GraphicsCacheItem *.
+
2001-02-22 Jean-Marc Lasgouttes <Jean-Marc.Lasgouttes@inria.fr>
* insetcollapsable.C (getLyXText): add const qualifier to second
{
char const * msg = 0;
- if (cacheHandle) {
+ if (cacheHandle.get()) {
switch (cacheHandle->getImageStatus()) {
case GraphicsCacheItem::UnknownError:
msg = _("Unknown Error");
int InsetGraphics::ascent(BufferView *, LyXFont const &) const
{
LyXImage * pixmap = 0;
- if (cacheHandle && (pixmap = cacheHandle->getImage()))
+ if (cacheHandle.get() && (pixmap = cacheHandle->getImage()))
return pixmap->getHeight();
else
return 50;
{
LyXImage * pixmap = 0;
- if (cacheHandle && (pixmap = cacheHandle->getImage()))
+ if (cacheHandle.get() && (pixmap = cacheHandle->getImage()))
return pixmap->getWidth();
else {
char const * msg = statusMessage();
// Get the image status, default to unknown error.
GraphicsCacheItem::ImageStatus status = GraphicsCacheItem::UnknownError;
- if (cacheHandle)
+ if (cacheHandle.get())
status = cacheHandle->getImageStatus();
// Check if the image is now ready.
void InsetGraphics::updateInset() const
{
GraphicsCache * gc = GraphicsCache::getInstance();
- GraphicsCacheItem * temp = 0;
+ boost::shared_ptr<GraphicsCacheItem> temp(0);
+ // We do it this way so that in the face of some error, we will still
+ // be in a valid state.
if (!params.filename.empty()) {
temp = gc->addFile(params.filename);
}
// Mark the image as unloaded so that it gets updated.
imageLoaded = false;
- delete cacheHandle;
cacheHandle = temp;
}
{
InsetGraphics * newInset = new InsetGraphics;
- if (cacheHandle)
- newInset->cacheHandle = cacheHandle->Clone();
- else
- newInset->cacheHandle = 0;
+ newInset->cacheHandle = cacheHandle;
newInset->imageLoaded = imageLoaded;
newInset->setParams(getParams());
#include "insets/lyxinset.h"
#include "insets/insetgraphicsParams.h"
#include "graphics/GraphicsCacheItem.h"
+#include <boost/smart_ptr.hpp>
#include "LaTeXFeatures.h"
string const prepareFile(Buffer const * buf) const;
/// The graphics cache handle.
- mutable GraphicsCacheItem * cacheHandle;
+ mutable boost::shared_ptr<GraphicsCacheItem> cacheHandle;
/// is the pixmap initialized?
mutable bool imageLoaded;