Baruch's graphic-inset patch.

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@957 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Jürgen Vigna 2000-08-08 09:18:39 +00:00
parent 797d87b451
commit 9ab27bcd7e
17 changed files with 369 additions and 48 deletions

View File

@ -1,3 +1,18 @@
2000-08-07 Baruch Even <baruch.even@writeme.com>
* src/graphics/Renderer.h:
* src/graphics/Renderer.C: Added base class for rendering of different
image formats into Pixmaps.
* src/graphics/XPM_Renderer.h:
* src/graphics/XPM_Renderer.C: Taken from GraphicsCacheItem and placed
in a different class.
* src/graphics/GraphicsCacheItem.C: factored out the rendering in order to
easily add support for other formats.
* src/insets/figinset.C: plugged a leak of an X resource.
2000-08-07 Lars Gullik Bjønnes <larsbj@lyx.org>
* src/CutAndPaste.[Ch]: make all metods static.
@ -50,6 +65,24 @@
* src/tabular.C (UseParbox): new function
2000-08-06 Baruch Even <baruch.even@writeme.com>
* src/graphics/GraphicsCache.h:
* src/graphics/GraphicsCache.C:
* src/graphics/GraphicsCacheItem.h:
* src/graphics/GraphicsCacheItem.C: Made them to actually do something
usefull.
* src/insets/insetgraphics.h:
* src/insets/insetgraphics.C: Added the use of the GraphicsCache and the
drawing of the inline image.
* src/buffer.C: Fixed a bug where a loaded InsetGraphics would be loaded
into the wrong position.
* src/lyxfunc.C: When adding an InsetGraphics the edit dialog is now
launched.
2000-08-05 Lars Gullik Bjønnes <larsbj@lyx.org>
* src/support/translator.h: move all typedefs to public section

View File

@ -1039,8 +1039,8 @@ void Buffer::readInset(LyXLex & lex, LyXParagraph *& par,
} else if (tmptok == "GRAPHICS") {
Inset * inset = new InsetGraphics;
inset->Read(this, lex);
++pos;
par->InsertInset(pos, inset, font);
++pos;
} else if (tmptok == "LatexCommand") {
InsetCommandParams inscmd;
inscmd.Read(lex);

View File

@ -14,6 +14,7 @@
#endif
#include <config.h>
#include "lyx_gui_misc.h"
#include "gettext.h"
#include FORMS_H_LOCATION
@ -517,3 +518,4 @@ void FormGraphics::InputCB(FL_OBJECT * ob, long)
FormGraphics * pre = static_cast<FormGraphics*>(ob->form->u_vdata);
pre->input();
}

View File

@ -19,6 +19,7 @@
#define FORMGRAPHICS_H
#include <config.h>
#include "LString.h"
#include "frontends/DialogBase.h"
//#include "form_graphics.h"
@ -154,5 +155,3 @@ private:
};
#endif

View File

@ -1,5 +1,6 @@
// File modified by fdfix.sh for use by lyx (with xforms >= 0.88) and gettext
#include <config.h>
#include "lyx_gui_misc.h"
#include "gettext.h"
@ -102,4 +103,3 @@ FD_form_graphics * FormGraphics::build_graphics()
return fdui;
}
/*---------------------------------------*/

View File

@ -17,6 +17,7 @@
#include "GraphicsCache.h"
#include "support/LAssert.h"
GraphicsCache * GraphicsCache::singleton = 0;
@ -26,6 +27,7 @@ GraphicsCache::getInstance()
{
if (! singleton) {
singleton = new GraphicsCache;
Assert(singleton != 0);
}
return singleton;
@ -34,7 +36,13 @@ GraphicsCache::getInstance()
GraphicsCache::~GraphicsCache()
{
delete singleton;
// Free the map.
//std::foreach(map.begin(), map.end(), ...);
// This is not really needed, it will only happen on program close and in
// any case the OS will release those resources (not doing it may have
// a good effect on closing time).
delete singleton;
}
@ -46,8 +54,19 @@ GraphicsCache::addFile(string const & filename)
if (it != cache.end()) {
return (*it).second;
}
// INCOMPLETE!
return 0;
GraphicsCacheItem * cacheItem = new GraphicsCacheItem();
if (cacheItem == 0) {
return 0;
}
bool result = cacheItem->setFilename(filename);
if (!result)
return 0;
cache[filename] = cacheItem;
return cacheItem;
}

View File

@ -52,5 +52,10 @@ private:
typedef std::map<string, GraphicsCacheItem *> CacheType;
///
CacheType cache;
// We need this so that an Item can tell the cache that it should be
// deleted. (to call removeFile).
// It also helps removing a warning gcc emits.
friend GraphicsCacheItem;
};
#endif

View File

@ -17,3 +17,131 @@
#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;
GraphicsCacheItem::GraphicsCacheItem()
: height_(-1), width_(-1), imageStatus_(Loading),
pixmap_(0), renderer(0)
{}
GraphicsCacheItem::~GraphicsCacheItem()
{
if (imageStatus_ == Loaded) {
XFreePixmap(fl_display, pixmap_);
}
delete renderer;
}
bool
GraphicsCacheItem::setFilename(string const & filename)
{
imageStatus_ = Loading;
renderer = new XPM_Renderer();
if (renderXPM(filename))
return true;
return false;
}
/*** Callback method ***/
typedef map<string, GraphicsCacheItem*> CallbackMap;
static CallbackMap callbackMap;
void
callback(string cmd, int retval)
{
lyxerr << "callback, cmd="<<cmd<<", retval="<<retval<<endl;
GraphicsCacheItem * item = callbackMap[cmd];
callbackMap.erase(cmd);
item->imageConverted(retval);
}
void
GraphicsCacheItem::imageConverted(int retval)
{
lyxerr << "imageConverted, retval="<<retval<<endl;
if (retval) {
imageStatus_ = ErrorConverting;
return;
}
// Do the actual image loading from XPM to memory.
loadXPMImage();
}
/**********************/
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()
{
if (! renderer->setFilename(xpmfile)) {
return;
}
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();
}

View File

@ -12,18 +12,103 @@
#ifndef GRAPHICSCACHEITEM_H
#define GRAPHICSCACHEITEM_H
#include <config.h>
#ifdef __GNUG__
#pragma interface
#endif
///
#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.
*/
/* (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.
*/
/// A GraphicsCache item holder.
class GraphicsCacheItem {
public:
/// d-tor, frees the image structures.
~GraphicsCacheItem();
/// Get the height of the image. Returns -1 on error.
int getHeight() const { return height_; }
/// Get the width of the image. Returns -1 on error.
int getWidth() const { return width_; }
/// Return a pixmap that can be displayed on X server.
Pixmap getImage() const { return pixmap_; }
enum ImageStatus {
Loading = 1,
ErrorConverting,
ErrorReading,
Loaded
};
/// Is the pixmap ready for display?
ImageStatus getImageStatus() const { return imageStatus_; }
/// 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:
///
GraphicsCacheItem() {}
/// Private c-tor so that only GraphicsCache can create an instance.
GraphicsCacheItem();
/// 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;
};
#endif

View File

@ -7,6 +7,10 @@ ETAGS_ARGS = --lang=c++
INCLUDES = -I${srcdir}/../ $(SIGC_CFLAGS)
libgraphics_la_SOURCES = \
Renderer.h \
Renderer.C \
XPM_Renderer.h \
XPM_Renderer.C \
GraphicsCache.h \
GraphicsCache.C \
GraphicsCacheItem.h \

View File

@ -592,6 +592,8 @@ void runqueue()
prop[i]);
if (strcmp(p, "GHOSTVIEW") == 0) {
err = false;
// We free it when we leave so we don't leak.
XFree(p);
break;
}
XFree(p);

View File

@ -43,10 +43,13 @@ Current PROBLEMS:
graphicx package docs it appears that it takes quite a bit of memory
on the side of TeXing.
* How do we handle the inline viewing? we may need to show the same image
in several formats (color, monochrome, grayscale) or even in different
sizes, not to mention rotations!
TODO Basics:
* Add support for more features so that it will be useable as a drop in
replacement to insetfig.
* Add support for more features so that it will be better than insetfig.
* Keep aspect ratio radio button
* Create the GraphicsCache and FormatTranslator
@ -80,6 +83,9 @@ TODO Extended features:
* If the dialog had no real change from previous time, do not mark document
as changed.
* Keep a tab on the image file, if it changes, update the lyx view.
* The image choosing dialog could show thumbnails of the image formats
it knows of, thus selection based on the image instead of based on
filename.
*/
/* NOTES:
@ -146,6 +152,7 @@ TODO Extended features:
* transferring the file around.
*/
#ifdef __GNUG__
#pragma implementation
#endif
@ -180,6 +187,7 @@ InsetGraphics::InsetGraphics()
: use_bb(false), hiresbb(false), angle(0.0), origin(DEFAULT)
,keepaspectratio(false), scale(0.0), clip(false), draft(false)
#endif
: cachehandle(0), bv_(0)
{}
InsetGraphics::~InsetGraphics()
@ -190,27 +198,28 @@ InsetGraphics::~InsetGraphics()
int InsetGraphics::ascent(BufferView *, LyXFont const &) const
{
return 25;
if (cachehandle &&
cachehandle->getImageStatus() == GraphicsCacheItem::Loaded)
return cachehandle->getHeight();
else
return 50;
}
int InsetGraphics::descent(BufferView *, LyXFont const &) const
{
// this is not true if viewport is used and clip is not.
return 25;
return 0;
}
int InsetGraphics::width(BufferView *, LyXFont const &) const
{
// Need to replace this with data coming from GraphicsCache
#ifdef IG_OLDPARAMS
if (bb.isSet()) {
return bb.urx - bb.llx + 2;
}
#endif
return 50;
if (cachehandle &&
cachehandle->getImageStatus() == GraphicsCacheItem::Loaded)
return cachehandle->getWidth();
else
return 50;
}
@ -219,16 +228,30 @@ 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.
paint.rectangle(int(x)+2, baseline - ascent(bv, font),
if (cachehandle &&
cachehandle->getImageStatus() == GraphicsCacheItem::Loaded) {
paint.pixmap(int(x)+2, baseline - ascent(bv, font),
width(bv, font) - 4,
ascent(bv,font) + descent(bv,font),
cachehandle->getImage());
} else {
paint.rectangle(int(x)+2, baseline - ascent(bv, font),
width(bv, font) - 4,
ascent(bv, font) + descent(bv, font));
}
x += width(bv, font);
}
void InsetGraphics::Edit(BufferView *bv, int, int, unsigned int)
{
bv_ = bv;
bv->owner()->getDialogs() -> showGraphics(this);
}
@ -241,7 +264,7 @@ Inset::EDITABLE InsetGraphics::Editable() const
void InsetGraphics::Write(Buffer const * buf, ostream & os) const
{
os << "Graphics FormatVersion 1" << endl;
os << "GRAPHICS FormatVersion 1" << endl;
params.Write(buf, os);
}
@ -606,16 +629,30 @@ void InsetGraphics::Validate(LaTeXFeatures & features) const
void InsetGraphics::updateInset()
{
// If file changed...
//graphicscache.addFile(params.filename);
//bb = graphicscache.getBB(params.filename);
//pixmap = graphicscache.getPixmap(params.filename);
GraphicsCache * gc = GraphicsCache::getInstance();
GraphicsCacheItem * temp = 0;
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);
}
bool InsetGraphics::setParams(InsetGraphicsParams const & params)
{
// TODO: Make it return true only when the data has been changed.
// for this to work we still need to implement operator == in
// InsetGraphicsParams
// If nothing is changed, just return and say so.
if (this->params == params)
return false;

View File

@ -12,10 +12,13 @@
#ifndef INSET_GRAPHICS_H
#define INSET_GRAPHICS_H
#ifdef __GNUG__
#pragma interface
#endif
#include <config.h>
#include "insets/lyxinset.h"
#include "insets/insetgraphicsParams.h"
@ -25,13 +28,19 @@
#include "sigc++/signal_system.h"
#ifdef SIGC_CXX_NAMESPACES
using SigC::Signal0;
using SigC::slot;
using SigC::Object;
#endif
class Dialogs;
class GraphicsCacheItem;
///
class InsetGraphics : public Inset {
#ifdef SIGC_CXX_NAMESPACES
class InsetGraphics : public Inset, public SigC::Object {
#else
class InsetGraphics : public Inset, public Object {
#endif
public:
///
InsetGraphics();
@ -94,9 +103,14 @@ 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;
/// Holds the buffer view that we are associated with.
BufferView * bv_;
InsetGraphicsParams params;

View File

@ -9,19 +9,19 @@
* This file Copyright 2000 Baruch Even
* ================================================= */
#ifdef __GNUG__
#pragma implementation
#endif
#include <config.h>
#include "insetgraphicsParams.h"
#include "support/translator.h"
#include "support/filetools.h"
#ifdef ENABLE_ASSERTIONS
#include "support/LAssert.h"
#endif
using std::endl;
@ -120,9 +120,7 @@ void InsetGraphicsParams::init()
rotateOrigin = DEFAULT;
rotateAngle = 0;
#ifdef ENABLE_ASSERTION
testInvariant();
#endif
}
void InsetGraphicsParams::copy(InsetGraphicsParams const & igp)
@ -140,14 +138,11 @@ void InsetGraphicsParams::copy(InsetGraphicsParams const & igp)
rotateOrigin = igp.rotateOrigin;
rotateAngle = igp.rotateAngle;
#ifdef ENABLE_ASSERTIONS
testInvariant();
#endif
}
void InsetGraphicsParams::testInvariant() const
{
#ifdef ENABLE_ASSERTIONS
// Filename might be empty (when the dialog is first created).
// Assert(!filename.empty());
@ -180,7 +175,6 @@ void InsetGraphicsParams::testInvariant() const
Assert(rotateAngle < 360);
Assert(rotateAngle > -360);
#endif
}
bool operator==(InsetGraphicsParams const & left,

View File

@ -17,6 +17,7 @@
#endif
#include <config.h>
#include "LString.h"
#include "buffer.h"

View File

@ -946,8 +946,9 @@ string LyXFunc::Dispatch(int ac,
if (!owner->view()->insertInset(new_inset)) {
delete new_inset;
} else {
// this is need because you don't use a inset->Edit()
owner->view()->updateInset(new_inset, true);
// this is need because you don't use a inset->Edit()
owner->view()->updateInset(new_inset, true);
new_inset->Edit(owner->view(), 0, 0, 0);
}
break;
}

View File

@ -12,12 +12,13 @@
#ifndef TRANSLATOR_H
#define TRANSLATOR_H
#include <vector>
#include <utility>
#include <algorithm>
#include <functional>
#include "support/LAssert.h"
// Functors used in the template.
template<typename T1, typename T2>
class equal_1st_in_pair {
@ -72,9 +73,7 @@ public:
/// Find the mapping for the first argument
T2 const & find(T1 const & first) const {
#ifdef ENABLE_ASSERTIONS
Assert( ! map.empty());
#endif
// For explanation see the next find() function.
Map::const_iterator it =
@ -91,9 +90,7 @@ public:
/// Find the mapping for the second argument
T1 const & find(T2 const & second) const {
#ifdef ENABLE_ASSERTIONS
Assert( ! map.empty());
#endif
// The idea is as follows:
// find_if() will try to compare the data in the vector with the value.