Baruch's patch + some fixes to it.

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@964 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Jürgen Vigna 2000-08-10 13:15:05 +00:00
parent 88ebef6dbc
commit 077ea832b5
11 changed files with 495 additions and 198 deletions

View File

@ -1,3 +1,27 @@
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

View File

@ -0,0 +1,60 @@
// -*- 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;
}

View File

@ -0,0 +1,36 @@
// -*- 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

View File

@ -52,31 +52,29 @@ 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);
// We do not destroy the GraphicsCacheItem since we are here because
// the last copy of it is being erased.
if (it != cache.end()) {
// INCOMPLETE!
// cache.erase(it);
}
if (cache.find(filename) != cache.end())
cache.erase(filename);
}

View File

@ -15,134 +15,78 @@
#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;
pimpl = 0;
copy(gci);
}
GraphicsCacheItem * item = callbackMap[cmd];
callbackMap.erase(cmd);
GraphicsCacheItem const &
GraphicsCacheItem::operator=(GraphicsCacheItem const & gci)
{
// Are we trying to copy the object onto itself.
if (this == &gci)
return *this;
item->imageConverted(retval);
// Destory old copy
destroy();
// And then copy new object.
copy(gci);
return *this;
}
void
GraphicsCacheItem::imageConverted(int retval)
GraphicsCacheItem::copy(GraphicsCacheItem const & gci)
{
lyxerr << "imageConverted, retval="<<retval<<endl;
if (retval) {
imageStatus_ = ErrorConverting;
return;
}
// Do the actual image loading from XPM to memory.
loadXPMImage();
pimpl = gci.pimpl;
++(pimpl->refCount);
}
/**********************/
bool
GraphicsCacheItem::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::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;
}
imageDone.emit();
// remove the xpm file now.
::unlink(xpmfile.c_str());
// and remove the reference to the filename.
xpmfile = string();
}
GraphicsCacheItem::ImageStatus
GraphicsCacheItem::getImageStatus() const { return pimpl->imageStatus_; }
int
GraphicsCacheItem::getHeight() const { return pimpl->height_; }
int
GraphicsCacheItem::getWidth() const { return pimpl->width_; }
Pixmap
GraphicsCacheItem::getImage() const { return pimpl->pixmap_; }

View File

@ -20,14 +20,13 @@
#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
@ -37,29 +36,27 @@ using SigC::Signal0;
* 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,
@ -69,46 +66,33 @@ public:
};
/// 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;
GraphicsCacheItem_pimpl * pimpl;
/// The system caller, runs the convertor.
Systemcalls syscall;
/// The filename we refer too, this is used when removing ourselves
/// from the cache.
string filename_;
};
#endif

View File

@ -0,0 +1,149 @@
// -*- 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();
}

View File

@ -0,0 +1,102 @@
// -*- 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

View File

@ -11,7 +11,11 @@ libgraphics_la_SOURCES = \
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 \

View File

@ -173,6 +173,7 @@ TODO Extended features:
#include "filedlg.h"
#include "support/FileInfo.h"
#include "support/filetools.h"
#include "lyxtext.h"
#include "debug.h"
@ -186,8 +187,9 @@ InsetGraphics::InsetGraphics()
#ifdef IG_OLDPARAMS
: use_bb(false), hiresbb(false), angle(0.0), origin(DEFAULT)
,keepaspectratio(false), scale(0.0), clip(false), draft(false)
,cacheHandle(0)
#endif
: cachehandle(0), bv_(0)
: pixmapInitialized(false),cacheHandle(0)
{}
InsetGraphics::~InsetGraphics()
@ -198,9 +200,8 @@ 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;
}
@ -215,9 +216,8 @@ int InsetGraphics::descent(BufferView *, LyXFont const &) const
int InsetGraphics::width(BufferView *, LyXFont const &) const
{
if (cachehandle &&
cachehandle->getImageStatus() == GraphicsCacheItem::Loaded)
return cachehandle->getWidth();
if (pixmapInitialized)
return cacheHandle->getWidth();
else
return 50;
}
@ -228,21 +228,28 @@ void InsetGraphics::draw(BufferView * bv, LyXFont const & font,
{
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());
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);
@ -251,7 +258,6 @@ void InsetGraphics::draw(BufferView * bv, LyXFont const & font,
void InsetGraphics::Edit(BufferView *bv, int, int, unsigned int)
{
bv_ = bv;
bv->owner()->getDialogs() -> showGraphics(this);
}
@ -584,8 +590,8 @@ int InsetGraphics::Latex(Buffer const *buf, ostream & os,
}
// 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;
}
@ -635,19 +641,10 @@ void InsetGraphics::updateInset()
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)

View File

@ -21,6 +21,7 @@
#include "insets/lyxinset.h"
#include "insets/insetgraphicsParams.h"
#include "graphics/GraphicsCacheItem.h"
#include "LaTeXFeatures.h"
@ -33,7 +34,6 @@ using SigC::Object;
#endif
class Dialogs;
class GraphicsCacheItem;
///
#ifdef SIGC_CXX_NAMESPACES
@ -103,14 +103,13 @@ private:
/// 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;
GraphicsCacheItem * cacheHandle;
/// Holds the buffer view that we are associated with.
BufferView * bv_;
/// The pixmap
mutable Pixmap pixmap;
/// is the pixmap initialized?
mutable bool pixmapInitialized;
InsetGraphicsParams params;