+2000-08-10 Juergen Vigna <jug@sad.it>
+
+ * src/insets/insetgraphics.C (draw): fixed access to 0 cacheHandle.
+ (InsetGraphics): initialized cacheHandle to 0.
+ (draw): changed call to updateInset to status=CHANGE_IN_DRAW.
+
+2000-08-10 Baruch Even <baruch.even@writeme.com>
+
+ * src/graphics/GraphicsCache.h:
+ * src/graphics/GraphicsCache.C (addFile, removeFile): Changed to work
+ correctly as a cache.
+
+ * src/graphics/GraphicsCacheItem.h:
+ * src/graphics/GraphicsCacheItem.C: Changed to the pimpl idiom to allow
+ reference counting.
+
+ * src/graphics/GraphicsCacheItem_pimpl.h:
+ * src/graphics/GraphicsCacheItem_pimpl.C: The implementation of the
+ GraphicsCacheItem.
+
+ * src/insets/insetgraphics.h:
+ * src/insets/insetgraphics.C: Changed from using a signal notification
+ to polling when image is not loaded.
+
2000-08-10 Allan Rae <rae@lyx.org>
* development/tools/makeLyXsigc.sh: Updated to allow Signal3. Note
--- /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
+ * ================================================= */
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+
+#include <config.h>
+#include "EPS_Renderer.h"
+
+#include FORMS_H_LOCATION
+#include <iostream>
+#include <fstream>
+
+#include "support/LAssert.h"
+#include "debug.h"
+
+using std::endl;
+using std::ios;
+
+EPS_Renderer::EPS_Renderer()
+ : Renderer()
+{}
+
+EPS_Renderer::~EPS_Renderer()
+{}
+
+bool EPS_Renderer::renderImage()
+{
+ return false;
+}
+
+bool EPS_Renderer::isImageFormatOK(string const & filename) const
+{
+ std::ifstream is(filename.c_str(), ios::in);
+
+ // The signature of the file without the spaces.
+ static const char str[] = "%!PS";
+ const char * ptr = str;
+
+ do {
+ char c;
+ is >> c;
+
+ if (c != *ptr)
+ return false;
+
+ ++ptr;
+ } while (*ptr != '\0');
+
+ return true;
+}
--- /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 EPS_RENDERER_H
+#define EPS_RENDERER_H
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "graphics/Renderer.h"
+
+class EPS_Renderer : public Renderer {
+public:
+ /// c-tor.
+ EPS_Renderer();
+ /// d-tor.
+ virtual ~EPS_Renderer();
+
+ /// Load the EPS image and create a pixmap out of it.
+ virtual bool renderImage();
+
+private:
+ /// Verify that filename is really an EPS file.
+ virtual bool isImageFormatOK(string const & filename) const;
+};
+
+#endif
}
-GraphicsCacheItem *
+GraphicsCacheItem *
GraphicsCache::addFile(string const & filename)
{
CacheType::const_iterator it = cache.find(filename);
if (it != cache.end()) {
- return (*it).second;
+ return new GraphicsCacheItem( *((*it).second) );
}
GraphicsCacheItem * cacheItem = new GraphicsCacheItem();
- if (cacheItem == 0) {
+ if (cacheItem == 0)
return 0;
- }
- bool result = cacheItem->setFilename(filename);
- if (!result)
- return 0;
+ cacheItem->setFilename(filename);
cache[filename] = cacheItem;
-
- return 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 );
}
void
GraphicsCache::removeFile(string const & filename)
{
- CacheType::const_iterator it = cache.find(filename);
-
- if (it != cache.end()) {
- // INCOMPLETE!
-// cache.erase(it);
- }
+ // We do not destroy the GraphicsCacheItem since we are here because
+ // the last copy of it is being erased.
+
+ if (cache.find(filename) != cache.end())
+ cache.erase(filename);
}
#pragma implementation
#endif
-#include "GraphicsCacheItem.h"
-
-#include "graphics/XPM_Renderer.h"
-#include "support/filetools.h"
-#include "debug.h"
-#include "support/LAssert.h"
-#include <unistd.h> // unlink
-
-#include <map>
-
-#include FORMS_H_LOCATION
-
-using std::endl;
-using std::map;
+#include "graphics/GraphicsCache.h"
+#include "graphics/GraphicsCacheItem.h"
+#include "graphics/GraphicsCacheItem_pimpl.h"
GraphicsCacheItem::GraphicsCacheItem()
- : height_(-1), width_(-1), imageStatus_(Loading),
- pixmap_(0), renderer(0)
-{}
+ : pimpl(new GraphicsCacheItem_pimpl)
+{
+ pimpl->refCount = 1;
+}
GraphicsCacheItem::~GraphicsCacheItem()
{
- if (imageStatus_ == Loaded) {
- XFreePixmap(fl_display, pixmap_);
- }
-
- delete renderer;
+ destroy();
}
bool
GraphicsCacheItem::setFilename(string const & filename)
{
- imageStatus_ = Loading;
-
- renderer = new XPM_Renderer();
- if (renderXPM(filename))
- return true;
-
- return false;
+ filename_ = filename;
+ return pimpl->setFilename(filename);
}
-/*** Callback method ***/
-
-typedef map<string, GraphicsCacheItem*> CallbackMap;
-static CallbackMap callbackMap;
-
-void
-callback(string cmd, int retval)
+GraphicsCacheItem::GraphicsCacheItem(GraphicsCacheItem const & gci)
{
- lyxerr << "callback, cmd="<<cmd<<", retval="<<retval<<endl;
-
- GraphicsCacheItem * item = callbackMap[cmd];
- callbackMap.erase(cmd);
-
- item->imageConverted(retval);
+ pimpl = 0;
+ copy(gci);
}
-void
-GraphicsCacheItem::imageConverted(int retval)
+GraphicsCacheItem const &
+GraphicsCacheItem::operator=(GraphicsCacheItem const & gci)
{
- lyxerr << "imageConverted, retval="<<retval<<endl;
+ // Are we trying to copy the object onto itself.
+ if (this == &gci)
+ return *this;
- if (retval) {
- imageStatus_ = ErrorConverting;
- return;
- }
+ // Destory old copy
+ destroy();
- // Do the actual image loading from XPM to memory.
- loadXPMImage();
-}
+ // And then copy new object.
+ copy(gci);
-/**********************/
+ return *this;
+}
-bool
-GraphicsCacheItem::renderXPM(string const & filename)
+void
+GraphicsCacheItem::copy(GraphicsCacheItem const & gci)
{
- // 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.
- xpmfile = TmpFileName(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;
+ pimpl = gci.pimpl;
+ ++(pimpl->refCount);
}
-// This function gets called from the callback after the image has been
-// converted successfully.
void
-GraphicsCacheItem::loadXPMImage()
+GraphicsCacheItem::destroy()
{
- if (! renderer->setFilename(xpmfile)) {
- return;
+ if (pimpl) {
+ --(pimpl->refCount);
+ if (pimpl->refCount == 0) {
+ delete pimpl;
+ GraphicsCache * gc = GraphicsCache::getInstance();
+ gc->removeFile(filename_);
+ }
}
+}
- if (renderer->renderImage()) {
- pixmap_ = renderer->getPixmap();
- width_ = renderer->getWidth();
- height_ = renderer->getHeight();
- imageStatus_ = Loaded;
- } else {
- imageStatus_ = ErrorReading;
- }
+GraphicsCacheItem::ImageStatus
+GraphicsCacheItem::getImageStatus() const { return pimpl->imageStatus_; }
- imageDone.emit();
+int
+GraphicsCacheItem::getHeight() const { return pimpl->height_; }
+
+int
+GraphicsCacheItem::getWidth() const { return pimpl->width_; }
- // remove the xpm file now.
- ::unlink(xpmfile.c_str());
- // and remove the reference to the filename.
- xpmfile = string();
-}
+Pixmap
+GraphicsCacheItem::getImage() const { return pimpl->pixmap_; }
#include XPM_H_LOCATION
#include "LString.h"
-#include "graphics/Renderer.h"
-#include "support/syscall.h"
#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
* independence, this will probably involve changing the Painter class too.
*/
-/* (Baruch Even 2000-08-05)
- * This should be made reference counted, but for the sake of initial design
- * I'll forego that and just make a first version that actually works, though
- * it may fail or leak in real document, this is an initial design to try
- * ideas on and be a testbed.
- * It may just as well be scraped later on to create a better design based on
- * the results of working with the current design.
- */
+class GraphicsCacheItem_pimpl;
+
/// A GraphicsCache item holder.
class GraphicsCacheItem {
public:
/// d-tor, frees the image structures.
~GraphicsCacheItem();
+ /// copy c-tor.
+ GraphicsCacheItem(GraphicsCacheItem const &);
+ /// Assignment operator.
+ GraphicsCacheItem const & operator=(GraphicsCacheItem const &);
/// Get the height of the image. Returns -1 on error.
- int getHeight() const { return height_; }
+ int getHeight() const;
/// Get the width of the image. Returns -1 on error.
- int getWidth() const { return width_; }
+ int getWidth() const;
/// Return a pixmap that can be displayed on X server.
- Pixmap getImage() const { return pixmap_; }
+ Pixmap getImage() const;
enum ImageStatus {
Loading = 1,
};
/// Is the pixmap ready for display?
- ImageStatus getImageStatus() const { return imageStatus_; }
+ ImageStatus getImageStatus() const;
/// Get a notification when the image conversion is done.
/// used by an internal callback mechanism.
void imageConverted(int retval);
- /// A signal objects can connect to in order to know when the image
- /// has arrived.
- Signal0<void> imageDone;
+
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);
- /// 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 GraphicsCache;
- /// The file name of the XPM file.
- string xpmfile;
- /// The image height
- int height_;
- /// The image width
- int width_;
- /// Is the pixmap loaded?
- ImageStatus imageStatus_;
- /// The image pixmap
- Pixmap pixmap_;
- /// The rendering object.
- Renderer * renderer;
-
- /// The system caller, runs the convertor.
- Systemcalls syscall;
+ GraphicsCacheItem_pimpl * pimpl;
+
+ /// The filename we refer too, this is used when removing ourselves
+ /// from the cache.
+ string filename_;
};
#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>
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+
+#include "GraphicsCacheItem.h"
+#include "GraphicsCacheItem_pimpl.h"
+
+#include "graphics/XPM_Renderer.h"
+#include "graphics/EPS_Renderer.h"
+#include "support/filetools.h"
+#include "debug.h"
+#include "support/LAssert.h"
+#include <unistd.h> // unlink
+
+#include <map>
+
+#include FORMS_H_LOCATION
+
+using std::endl;
+using std::map;
+
+
+GraphicsCacheItem_pimpl::GraphicsCacheItem_pimpl()
+ : height_(-1), width_(-1), imageStatus_(GraphicsCacheItem::Loading),
+ pixmap_(0), renderer(0), refCount(0)
+{}
+
+GraphicsCacheItem_pimpl::~GraphicsCacheItem_pimpl()
+{
+ if (imageStatus_ == GraphicsCacheItem::Loaded) {
+ XFreePixmap(fl_display, pixmap_);
+ }
+
+ delete renderer;
+}
+
+bool
+GraphicsCacheItem_pimpl::setFilename(string const & filename)
+{
+ imageStatus_ = GraphicsCacheItem::Loading;
+
+ renderer = new XPM_Renderer();
+ if (renderXPM(filename))
+ return true;
+
+ return false;
+}
+
+/*** Callback method ***/
+
+typedef map<string, GraphicsCacheItem_pimpl*> CallbackMap;
+static CallbackMap callbackMap;
+
+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) {
+ 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.
+ xpmfile = TmpFileName(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()
+{
+ if (! renderer->setFilename(xpmfile)) {
+ return;
+ }
+
+ if (renderer->renderImage()) {
+ pixmap_ = renderer->getPixmap();
+ width_ = renderer->getWidth();
+ height_ = renderer->getHeight();
+ imageStatus_ = GraphicsCacheItem::Loaded;
+ } else {
+ imageStatus_ = GraphicsCacheItem::ErrorReading;
+ }
+
+ // remove the xpm file now.
+ ::unlink(xpmfile.c_str());
+ // 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/Renderer.h"
+#include "support/syscall.h"
+
+#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.
+ */
+
+/// A GraphicsCache item holder.
+class GraphicsCacheItem_pimpl {
+public:
+ /// d-tor, frees the image structures.
+ ~GraphicsCacheItem_pimpl();
+
+ /// Get the height of the image. Returns -1 on error.
+ int getHeight() const;
+
+ /// Get the width of the image. Returns -1 on error.
+ int getWidth() const;
+
+ /// Return a pixmap that can be displayed on X server.
+ Pixmap getImage() const;
+
+ 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;
+ /// The image height
+ int height_;
+ /// The image width
+ int width_;
+ /// Is the pixmap loaded?
+ ImageStatus imageStatus_;
+ /// The image pixmap
+ Pixmap pixmap_;
+ /// The rendering object.
+ Renderer * renderer;
+
+ /// The system caller, runs the convertor.
+ Systemcalls syscall;
+
+ /// The reference count
+ int refCount;
+};
+
+#endif
Renderer.C \
XPM_Renderer.h \
XPM_Renderer.C \
+ EPS_Renderer.h \
+ EPS_Renderer.C \
GraphicsCache.h \
GraphicsCache.C \
GraphicsCacheItem.h \
- GraphicsCacheItem.C
+ GraphicsCacheItem.C \
+ GraphicsCacheItem_pimpl.h \
+ GraphicsCacheItem_pimpl.C \
#include "filedlg.h"
#include "support/FileInfo.h"
#include "support/filetools.h"
+#include "lyxtext.h"
#include "debug.h"
InsetGraphics::InsetGraphics()
#ifdef IG_OLDPARAMS
: use_bb(false), hiresbb(false), angle(0.0), origin(DEFAULT)
- ,keepaspectratio(false), scale(0.0), clip(false), draft(false)
+ ,keepaspectratio(false), scale(0.0), clip(false), draft(false)
+ ,cacheHandle(0)
#endif
- : cachehandle(0), bv_(0)
+ : pixmapInitialized(false),cacheHandle(0)
{}
InsetGraphics::~InsetGraphics()
int InsetGraphics::ascent(BufferView *, LyXFont const &) const
{
- if (cachehandle &&
- cachehandle->getImageStatus() == GraphicsCacheItem::Loaded)
- return cachehandle->getHeight();
+ if (pixmapInitialized)
+ return cacheHandle->getHeight();
else
return 50;
}
int InsetGraphics::width(BufferView *, LyXFont const &) const
{
- if (cachehandle &&
- cachehandle->getImageStatus() == GraphicsCacheItem::Loaded)
- return cachehandle->getWidth();
+ if (pixmapInitialized)
+ return cacheHandle->getWidth();
else
return 50;
}
void InsetGraphics::draw(BufferView * bv, LyXFont const & font,
- int baseline, float & x, bool) const
+ int baseline, float & x, bool) const
{
Painter & paint = bv->painter();
-
- // This will draw the graphics. As for now we only draw a
- // placeholder rectangele.
- if (cachehandle &&
- cachehandle->getImageStatus() == GraphicsCacheItem::Loaded) {
+ // This will draw the graphics. If the graphics has not been loaded yet,
+ // we draw just a rectangle.
+ if (pixmapInitialized) {
paint.pixmap(int(x)+2, baseline - ascent(bv, font),
width(bv, font) - 4,
- ascent(bv,font) + descent(bv,font),
- cachehandle->getImage());
+ ascent(bv,font) + descent(bv,font),
+ pixmap);
} else {
paint.rectangle(int(x)+2, baseline - ascent(bv, font),
width(bv, font) - 4,
ascent(bv, font) + descent(bv, font));
+ // Check if the image is now ready.
+ if (cacheHandle &&
+ (cacheHandle->getImageStatus() == GraphicsCacheItem::Loaded)) {
+ pixmap = cacheHandle->getImage();
+ pixmapInitialized = true;
+
+ // Tell BufferView we need to be updated!
+ bv->text->status = LyXText::CHANGED_IN_DRAW;
+ }
}
x += width(bv, font);
void InsetGraphics::Edit(BufferView *bv, int, int, unsigned int)
{
- bv_ = bv;
bv->owner()->getDialogs() -> showGraphics(this);
}
}
// How do we decide to what format should we export?
-// cachehandle->export(ImageType::EPS);
-// cachehandle->export(ImageType::PNG);
+// cacheHandle->>export(ImageType::EPS);
+// cacheHandle->>export(ImageType::PNG);
return 1;
}
if (!params.filename.empty()) {
temp = gc->addFile(params.filename);
- if (temp)
- temp->imageDone.connect(slot(this, &InsetGraphics::imageDone));
}
- delete cachehandle;
- cachehandle = temp;
-
-}
-
-void InsetGraphics::imageDone()
-{
- if (bv_)
- bv_->updateInset(this, false);
+ delete cacheHandle;
+ cacheHandle = temp;
}
bool InsetGraphics::setParams(InsetGraphicsParams const & params)
#include "insets/lyxinset.h"
#include "insets/insetgraphicsParams.h"
+#include "graphics/GraphicsCacheItem.h"
#include "LaTeXFeatures.h"
#endif
class Dialogs;
-class GraphicsCacheItem;
///
#ifdef SIGC_CXX_NAMESPACES
/// Update the inset after parameter change.
void updateInset();
- /// Get notified when the inline image processing has finished.
- void imageDone();
-
/// The graphics cache handle.
- GraphicsCacheItem * cachehandle;
-
- /// Holds the buffer view that we are associated with.
- BufferView * bv_;
+ GraphicsCacheItem * cacheHandle;
+ /// The pixmap
+ mutable Pixmap pixmap;
+ /// is the pixmap initialized?
+ mutable bool pixmapInitialized;
+
InsetGraphicsParams params;
// Baruch Even (baruch.even@writeme.com) 2000-07-17