]> git.lyx.org Git - features.git/commitdiff
Asymptotic approach to a well-designed graphics loader.
authorAngus Leeming <leeming@lyx.org>
Fri, 28 Jun 2002 11:22:56 +0000 (11:22 +0000)
committerAngus Leeming <leeming@lyx.org>
Fri, 28 Jun 2002 11:22:56 +0000 (11:22 +0000)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@4502 a592a061-630c-0410-9148-cb99ea01b6c8

39 files changed:
src/frontends/ChangeLog
src/frontends/Painter.h
src/frontends/controllers/ChangeLog
src/frontends/controllers/ControlGraphics.C
src/frontends/qt2/ChangeLog
src/frontends/qt2/QLPainter.C
src/frontends/qt2/QLPainter.h
src/frontends/screen.C
src/frontends/xforms/ChangeLog
src/frontends/xforms/Makefile.am
src/frontends/xforms/XPainter.C
src/frontends/xforms/XPainter.h
src/frontends/xforms/lyx_gui.C
src/frontends/xforms/xformsGImage.C [deleted file]
src/frontends/xforms/xformsGImage.h [deleted file]
src/frontends/xforms/xformsImage.C [new file with mode: 0644]
src/frontends/xforms/xformsImage.h [new file with mode: 0644]
src/graphics/ChangeLog
src/graphics/GraphicsCache.C
src/graphics/GraphicsCache.h
src/graphics/GraphicsCacheItem.C
src/graphics/GraphicsCacheItem.h
src/graphics/GraphicsConverter.C
src/graphics/GraphicsConverter.h
src/graphics/GraphicsImage.C
src/graphics/GraphicsImage.h
src/graphics/GraphicsImageXPM.C
src/graphics/GraphicsImageXPM.h
src/graphics/GraphicsLoader.C
src/graphics/GraphicsLoader.h
src/graphics/GraphicsParams.C
src/graphics/GraphicsParams.h
src/graphics/GraphicsTypes.h
src/insets/ChangeLog
src/insets/insetgraphics.C
src/insets/insetgraphicsParams.C
src/insets/insetgraphicsParams.h
src/mathed/ChangeLog
src/mathed/preview.h

index cc6df77f82e56a10855ae11a858d87466d5173e6..0453379efe7f798431ce69ea2fe2f86fea074966 100644 (file)
@@ -1,3 +1,9 @@
+2002-06-28  Angus Leeming  <leeming@lyx.org>
+
+       * Painter.h:
+       * screen.C: changes associated with the name change grfx::GImage ->
+       grfx::Image.
+
 2002-06-26  Angus Leeming  <leeming@lyx.org>
 
        * screen.C: moved the image loading stuff into a new class grfx::Loader.
index ff5784f3342c18973a1da20be8a15aa72342f6f7..f629234f0b02466ea66a91016707f709bc51bcf9 100644 (file)
@@ -21,7 +21,7 @@
 class LyXFont;
 
 namespace grfx {
-       class GImage;
+       class Image;
 }
 
 /**
@@ -133,7 +133,7 @@ public:
        /// draw an image from the image cache
        virtual Painter & image(int x, int y,
                int w, int h,
-               grfx::GImage const & image) = 0;
+               grfx::Image const & image) = 0;
        
        /// draw a string at position x, y (y is the baseline)
        virtual Painter & text(int x, int y,
index c9b0953661978354c1471b8f77785a033f313eef..b1121f1e5335c25e6e268e14a7a92e29cc9716a2 100644 (file)
@@ -1,3 +1,8 @@
+2002-06-28  Angus Leeming  <leeming@lyx.org>
+
+       * ControlGraphics.C: changes associated with the name changes
+       grfx::GCache -> grfx::Cache and grfx::GImage -> grfx::Image.
+
 2002-06-25  Angus Leeming  <leeming@lyx.org>
 
        * ControlGraphics.C (readBB): Channges associated with the changed
index 6bc9979f828a30865d27092f1752b96c28d98901..f154cc197e3e833804e94f6510c8d9207f4c9ce5 100644 (file)
@@ -31,7 +31,7 @@
 #include "lyxrc.h"
 
 #include "graphics/GraphicsCache.h"
-#include "graphics/GraphicsConverter.h"
+#include "graphics/GraphicsCacheItem.h"
 #include "graphics/GraphicsImage.h"
 
 #include "insets/insetgraphics.h"
@@ -114,12 +114,14 @@ string const ControlGraphics::readBB(string const & file)
        int width = 0;
        int height = 0;
 
-       grfx::GCache & gc = grfx::GCache::get();
-       grfx::ImagePtr const image = gc.image(abs_file);
+       grfx::Cache & gc = grfx::Cache::get();
+       if (gc.inCache(abs_file)) {
+               grfx::Image const * image = gc.item(abs_file)->image();
 
-       if (image.get()) {
-               width  = image->getWidth();
-               height = image->getHeight();
+               if (image) {
+                       width  = image->getWidth();
+                       height = image->getHeight();
+               }
        }
 
        return ("0 0 " + tostr(width) + ' ' + tostr(height));
index 506046a1e3fe7ac3d80d522313b8faaf38e01fe8..6b401d7181ef51bee69af7cedb2492bc26c2f91c 100644 (file)
@@ -1,3 +1,8 @@
+2002-06-28  Angus Leeming  <leeming@lyx.org>
+
+       * QLPainter.[Ch]: changes associated with the name change
+       grfx::GImage -> grfx::Image.
+
 2002-06-21  Angus Leeming  <leeming@lyx.org>
 
        * Menubar_pimpl.C (c-tor): rename MenuBackend const & mb argument to
index 7baf657f8ee0108c006ee5f5e00d459029c489a4..d8faacf94295d5d07a80e43544fb3d1ee84b0551 100644 (file)
@@ -186,7 +186,7 @@ Painter & QLPainter::arc(int x, int y,
  
 Painter & QLPainter::image(int , int , 
        int , int ,
-       grfx::GImage const & )
+       grfx::Image const & )
 {
 #if 0 // FIXME
        XGCValues val;
index 7315af8106b36b38951a5f45dcbf3c8e46e863ad..5b27f38ca7279bf1c925f9aa0fff13743400e0f4 100644 (file)
@@ -101,7 +101,7 @@ public:
        /// draw an image from the image cache
        virtual Painter & image(int x, int y,
                int w, int h,
-               grfx::GImage const & image);
+               grfx::Image const & image);
        
        /// draw a string at position x, y (y is the baseline)
        virtual Painter & text(int x, int y,
index 2ef231de7f61d56fd5e3dddaa3a57aad6a561916..6f874d9f799fb7f904966357ec12e970bf30f777 100644 (file)
@@ -49,7 +49,7 @@ public:
        /// This is a singleton class. Get the instance.
        static SplashScreen const & get();
        ///
-       grfx::GImage const * image() const { return loader_.image(); }
+       grfx::Image const * image() const { return loader_.image(); }
        ///
        string const & text() const { return text_; }
        ///
@@ -376,7 +376,7 @@ void LyXScreen::greyOut()
 
        // Add a splash screen to the centre of the work area
        SplashScreen const & splash = SplashScreen::get();
-       grfx::GImage const * const splash_image = splash.image();
+       grfx::Image const * const splash_image = splash.image();
        if (splash_image) {
                int const w = splash_image->getWidth();
                int const h = splash_image->getHeight();
index 51045b9ce0a7d3fde7019cfe606d14715fd9aaeb..e891137b2607f1a91343b606802835f707bd7cf3 100644 (file)
@@ -1,3 +1,14 @@
+2002-06-28  Angus Leeming  <leeming@lyx.org>
+
+       * XPainter.[Ch]: changes associated with the name change
+       grfx::GImage -> grfx::Image.
+
+       * xformsGImage.[Ch]: deleted.
+       * xformsImage.[Ch]: new files, reflecting changed class name.
+
+       * Makefile.am:
+       * lyx_gui.C: associated changes.
+
 2002-06-27  Juergen Spitzmueller <j.spitzmueller@gmx.de>
 
        * FormPreferences.C
index 61e06182d432e7d5a72e493da09d0f73b5843169..f0441344480400aa3b7483da42b7d54b74c1e5b4 100644 (file)
@@ -9,11 +9,11 @@ INCLUDES = -I$(top_srcdir)/images -I$(top_srcdir)/src/ \
 
 SUBDIRS = forms
 
-EXTRA_DIST = xformsGImage.C xformsGImage.h
+EXTRA_DIST = xformsImage.C xformsImage.h
 
 if USE_BASIC_IMAGE_LOADER
 else
-XFORMSGIMAGE = xformsGImage.C xformsGImage.h
+XFORMSIMAGE = xformsImage.C xformsImage.h
 endif
 
 # Alphabetical order please.  It makes it easier to figure out what's missing.
@@ -38,7 +38,7 @@ libxforms_la_SOURCES = \
        xforms_helpers.h \
        xforms_resize.C \
        xforms_resize.h \
-       $(XFORMSGIMAGE) xformsBC.C \
+       $(XFORMSIMAGE) xformsBC.C \
        xformsBC.h \
        xscreen.C \
        xscreen.h \
index 68837a7d712b6572a239628b00b2929e9a9c3eac..f4692adaa028bea7481b18295367658b7e05093b 100644 (file)
@@ -150,7 +150,7 @@ Painter & XPainter::arc(int x, int y,
  
 Painter & XPainter::image(int x, int y, 
        int w, int h,
-       grfx::GImage const & image)
+       grfx::Image const & image)
 {
        XGCValues val;
        val.function = GXcopy;
index ddb5c3684bfff88f3e749c95030cf8ab69821e79..435359ae49da3ddb4b826607b980e30bae8e7915 100644 (file)
@@ -96,7 +96,7 @@ public:
        /// draw an image from the image cache
        virtual Painter & image(int x, int y,
                int w, int h,
-               grfx::GImage const & image);
+               grfx::Image const & image);
        
        /// draw a string at position x, y (y is the baseline)
        virtual Painter & text(int x, int y,
index f95ee8331d7c26c45f2febc20676771032be97ce..8703352decbfa43fd21ba6a87f4dd2cb31177a65 100644 (file)
@@ -32,7 +32,7 @@
 #include "ColorHandler.h"
 #include "xforms_helpers.h"
 #ifdef USE_XFORMS_IMAGE_LOADER
-#include "xformsGImage.h"
+#include "xformsImage.h"
 #else
 #include "graphics/GraphicsImageXPM.h"
 #endif
@@ -300,11 +300,11 @@ void lyx_gui::init_graphics()
 
 #ifdef USE_XFORMS_IMAGE_LOADER
        // connect the image loader based on the xforms library
-       GImage::newImage.connect(boost::bind(&xformsGImage::newImage));
-       GImage::loadableFormats.connect(boost::bind(&xformsGImage::loadableFormats));
+       Image::newImage.connect(boost::bind(&xformsImage::newImage));
+       Image::loadableFormats.connect(boost::bind(&xformsImage::loadableFormats));
 #else
        // connect the image loader based on the XPM library
-       GImage::newImage.connect(boost::bind(&GImageXPM::newImage));
-       GImage::loadableFormats.connect(boost::bind(&GImageXPM::loadableFormats));
+       Image::newImage.connect(boost::bind(&ImageXPM::newImage));
+       Image::loadableFormats.connect(boost::bind(&ImageXPM::loadableFormats));
 #endif
 }
diff --git a/src/frontends/xforms/xformsGImage.C b/src/frontends/xforms/xformsGImage.C
deleted file mode 100644 (file)
index a07b6c4..0000000
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * \file xformsGImage.C
- * Copyright 2002 the LyX Team
- * Read the file COPYING
- *
- * \author Angus Leeming, a.leeming@ic.ac.uk
- */
-
-#include <config.h>
-
-#ifdef __GNUG__
-#pragma implementation
-#endif
-
-#include "xformsGImage.h"
-#include "graphics/GraphicsParams.h"
-#include "LColor.h"
-#include "converter.h"              // formats
-#include "debug.h"
-#include "support/LAssert.h"
-#include "support/lyxfunctional.h"  // compare_memfun
-
-#include FORMS_H_LOCATION
-
-#ifdef HAVE_FLIMAGE_H
-# include <flimage.h>
-#else
-# ifdef HAVE_X11_FLIMAGE_H
-# include <X11/flimage.h>
-# endif
-#endif
-
-using std::find_if;
-
-namespace {
-
-void init_graphics();
-
-unsigned int packedcolor(LColor::color c);
-
-} // namespace anon
-
-
-namespace grfx {
-
-/// Access to this class is through this static method.
-ImagePtr xformsGImage::newImage()
-{
-       init_graphics();
-
-       ImagePtr ptr;
-       ptr.reset(new xformsGImage);
-       return ptr;
-}
-
-
-/// Return the list of loadable formats.
-GImage::FormatList xformsGImage::loadableFormats()
-{
-       static FormatList fmts;
-       if (!fmts.empty())
-               return fmts;
-
-       init_graphics();
-
-       // The formats recognised by LyX
-       Formats::const_iterator begin = formats.begin();
-       Formats::const_iterator end   = formats.end();
-
-       lyxerr[Debug::GRAPHICS]
-               << "\nThe image loader can load the following directly:\n";
-
-       // Don't forget the Fortran numbering used by xforms!
-       int const nformats = flimage_get_number_of_formats();
-       for (int i = 1; i <= nformats; ++i) {
-
-               FLIMAGE_FORMAT_INFO const * info = flimage_get_format_info(i);
-               string const formal_name =
-                       info->formal_name ? info->formal_name : string();
-               string ext =
-                       info->extension   ? info->extension   : string();
-
-               if (ext.empty() || ext == "gz")
-                       continue;
-
-               if (ext == "rgb") ext = "sgi";
-
-               lyxerr[Debug::GRAPHICS]
-                       << formal_name << ", extension \"" << ext << "\"\n";
-
-               Formats::const_iterator it =
-                       find_if(begin, end,
-                               lyx::compare_memfun(&Format::extension, ext));
-               if (it != end)
-                       fmts.push_back(it->name());
-       }
-
-       lyxerr[Debug::GRAPHICS]
-               << "\nOf these, LyX recognises the following formats:\n";
-
-       FormatList::const_iterator fbegin = fmts.begin();
-       FormatList::const_iterator fend   = fmts.end();
-       for (FormatList::const_iterator fit = fbegin; fit != fend; ++fit) {
-               if (fit != fbegin)
-                       lyxerr[Debug::GRAPHICS] << ", ";
-               lyxerr[Debug::GRAPHICS] << *fit;
-       }
-       lyxerr[Debug::GRAPHICS] << '\n' << std::endl;
-
-       return fmts;
-}
-
-
-xformsGImage::xformsGImage()
-       : image_(0),
-         pixmap_(0),
-         pixmap_status_(PIXMAP_UNINITIALISED)
-{}
-
-
-xformsGImage::xformsGImage(xformsGImage const & other)
-       : GImage(other),
-         image_(0),
-         pixmap_(0),
-         pixmap_status_(PIXMAP_UNINITIALISED)
-{
-       if (other.image_) {
-               image_ = flimage_dup(other.image_);
-               image_->u_vdata = this;
-       }
-}
-
-
-xformsGImage::~xformsGImage()
-{
-       if (image_)
-               flimage_free(image_);
-       if (pixmap_)
-               XFreePixmap(fl_get_display(), pixmap_);
-}
-
-
-GImage * xformsGImage::clone() const
-{
-       return new xformsGImage(*this);
-}
-
-
-unsigned int xformsGImage::getWidth() const
-{
-       if (!image_)
-               return 0;
-       return image_->w;
-}
-
-
-unsigned int xformsGImage::getHeight() const
-{
-       if (!image_)
-               return 0;
-       return image_->h;
-}
-
-
-Pixmap xformsGImage::getPixmap() const
-{
-       if (!pixmap_status_ == PIXMAP_SUCCESS)
-               return 0;
-       return pixmap_;
-}
-
-
-void xformsGImage::load(string const & filename, SignalTypePtr on_finish)
-{
-       if (image_) {
-               lyxerr[Debug::GRAPHICS]
-                       << "Image is loaded already!" << std::endl;
-               on_finish->operator()(false);
-               return;
-       }
-
-       image_ = flimage_open(filename.c_str());
-       if (!image_) {
-               lyxerr[Debug::GRAPHICS]
-                       << "Unable to open image" << std::endl;
-               on_finish->operator()(false);
-               return;
-       }
-
-       // Store the Signal that will be emitted once the image is loaded.
-       on_finish_ = on_finish;
-
-       // Set this now and we won't need to bother again.
-       image_->fill_color = packedcolor(LColor::graphicsbg);
-
-       // Used by the callback routines to return to this
-       image_->u_vdata = this;
-
-       // Begin the reading process.
-       flimage_read(image_);
-}
-
-
-bool xformsGImage::setPixmap(GParams const & params)
-{
-       if (!image_ || params.display == NoDisplay)
-               return false;
-
-       Display * display = fl_get_display();
-
-       if (pixmap_ && pixmap_status_ == PIXMAP_SUCCESS)
-               XFreePixmap(display, pixmap_);
-
-       int color_key;
-       switch (params.display) {
-       case MonochromeDisplay:
-               color_key = FL_IMAGE_MONO;
-               break;
-       case GrayscaleDisplay:
-               color_key = FL_IMAGE_GRAY;
-               break;
-       case ColorDisplay:
-       default: // NoDisplay cannot happen!
-               color_key = FL_IMAGE_RGB;
-               break;
-       }
-
-       if (color_key != FL_IMAGE_RGB) {
-               flimage_convert(image_, color_key, 0);
-       }
-
-       unsigned int fill = packedcolor(LColor::graphicsbg);
-       if (fill != image_->fill_color) {
-               // the background color has changed.
-               // Note that in grayscale/monochrome images the background is
-               // grayed also, so this call will have no visible effect. Sorry!
-               flimage_replace_pixel(image_, image_->fill_color, fill);
-               image_->fill_color = fill;
-       }
-
-       image_->xdisplay = display;
-       Screen * screen  = ScreenOfDisplay(display, fl_screen);
-
-       pixmap_ = flimage_to_pixmap(image_, XRootWindowOfScreen(screen));
-       pixmap_status_ = pixmap_ ? PIXMAP_SUCCESS : PIXMAP_FAILED;
-
-       return pixmap_status_ == PIXMAP_SUCCESS;
-}
-
-
-void xformsGImage::clip(GParams const & params)
-{
-       if (!image_)
-               return;
-
-       if (params.bb.empty())
-               // No clipping is necessary.
-               return;
-
-       int const new_width  = params.bb.xr - params.bb.xl;
-       int const new_height = params.bb.yt - params.bb.yb;
-
-       // No need to check if the width, height are > 0 because the
-       // Bounding Box would be empty() in this case.
-       if (new_width > image_->w || new_height > image_->h)
-               // Bounds are invalid.
-               return;
-
-       if (new_width == image_->w && new_height == image_->h)
-               // Bounds are unchanged.
-               return;
-
-       int const xoffset_l = std::max(0, params.bb.xl);
-       int const xoffset_r = std::max(0, image_->w - params.bb.xr);
-       int const yoffset_t = std::max(0, image_->h - params.bb.yt);
-       int const yoffset_b = std::max(0, params.bb.yb);
-
-       flimage_crop(image_, xoffset_l, yoffset_t, xoffset_r, yoffset_b);
-}
-
-
-void xformsGImage::rotate(GParams const & params)
-{
-       if (!image_)
-               return ;
-
-       if (!params.angle)
-               // No rotation is necessary.
-               return;
-
-       // The angle passed to flimage_rotate is the angle in one-tenth of a
-       // degree units.
-
-       // Work around xforms bug when params.angle == 270
-       // the 'InternalError: bad special angle' error.
-       // This bug fix is not needed in xforms 1.0 and greater.
-       if (params.angle == 270) {
-               flimage_rotate(image_,  900, FLIMAGE_SUBPIXEL);
-               flimage_rotate(image_, 1800, FLIMAGE_SUBPIXEL);
-       } else {
-               flimage_rotate(image_, params.angle * 10, FLIMAGE_SUBPIXEL);
-       }
-}
-
-
-void xformsGImage::scale(GParams const & params)
-{
-       if (!image_)
-               return;
-
-       // boost::tie produces horrible compilation errors on my machine
-       // Angus 25 Feb 2002
-       std::pair<unsigned int, unsigned int> d = getScaledDimensions(params);
-       unsigned int const width  = d.first;
-       unsigned int const height = d.second;
-
-       if (width == getWidth() && height == getHeight())
-               // No scaling needed
-               return;
-
-       flimage_scale(image_, width, height, FLIMAGE_SUBPIXEL);
-}
-
-
-void xformsGImage::statusCB(string const & status_message)
-{
-       if (status_message.empty() || !on_finish_.get())
-               return;
-
-       if (prefixIs(status_message, "Done Reading")) {
-               if (image_) {
-                       flimage_close(image_);
-               }
-
-               if (on_finish_.get()) {
-                       on_finish_->operator()(true);
-                       on_finish_.reset();
-               }
-       }
-}
-
-
-void xformsGImage::errorCB(string const & error_message)
-{
-       if (error_message.empty() || !on_finish_.get())
-               return;
-
-       if (image_) {
-               flimage_close(image_);
-       }
-
-       if (on_finish_.get()) {
-               on_finish_->operator()(false);
-               on_finish_.reset();
-       }
-}
-
-} // namespace grfx
-
-
-namespace {
-
-extern "C" {
-
-int status_report(FL_IMAGE * ob, const char *s)
-{
-       lyx::Assert(ob && ob->u_vdata);
-
-       string const str = s ? strip(s) : string();
-       if (str.empty())
-               return 0;
-
-       lyxerr[Debug::GRAPHICS]
-               << "xforms image loader. Status : " << str << std::endl;
-
-       grfx::xformsGImage * ptr =
-               static_cast<grfx::xformsGImage *>(ob->u_vdata);
-       ptr->statusCB(str);
-
-       return 0;
-}
-
-
-static void error_report(FL_IMAGE * ob, const char *s)
-{
-       lyx::Assert(ob && ob->u_vdata);
-
-       string const str = s ? strip(s) : string();
-       if (str.empty())
-               return;
-
-       lyxerr[Debug::GRAPHICS]
-               << "xforms image loader. Error : " << str << std::endl;
-
-       grfx::xformsGImage * ptr =
-               static_cast<grfx::xformsGImage *>(ob->u_vdata);
-       ptr->errorCB(str);
-}
-
-} // extern "C"
-
-
-void init_graphics()
-{
-       // Paranoia check
-       static bool initialised = false;
-       if (initialised)
-               return;
-       initialised = true;
-
-       flimage_enable_bmp();
-       flimage_enable_fits();
-       flimage_enable_gif();
-#ifdef HAVE_FLIMAGE_ENABLE_JPEG
-       flimage_enable_jpeg();
-#endif
-
-       // xforms itself uses pngtopnm to convert to a loadable format.
-       // We prefer to use our own conversion mechanism, therefore.
-       // flimage_enable_png();
-
-       flimage_enable_pnm();
-
-#ifdef HAVE_FLIMAGE_ENABLE_PS
-       // xforms recognises PS but not EPS
-       flimage_enable_ps();
-#endif
-
-       flimage_enable_sgi();
-       flimage_enable_tiff();
-       flimage_enable_xbm();
-       flimage_enable_xwd();
-       flimage_enable_xpm();
-
-       // xforms stores this permanently (does not make a copy) so
-       // this should never be destroyed.
-       static FLIMAGE_SETUP setup;
-       setup.visual_cue    = status_report;
-       setup.error_message = error_report;
-       flimage_setup(&setup);
-}
-
-
-unsigned int packedcolor(LColor::color c)
-{
-       string const x11color = lcolor.getX11Name(c);
-
-       Display * display = fl_get_display();
-       Colormap cmap     = fl_state[fl_get_vclass()].colormap;
-       XColor xcol;
-       XColor ccol;
-       if (XLookupColor(display, cmap, x11color.c_str(), &xcol, &ccol) == 0)
-               // Unable to parse x11color.
-               return FL_PACK(255,255,255);
-
-       // Note that X stores the RGB values in the range 0 - 65535
-       // whilst we require them in the range 0 - 255.
-       unsigned int const r = xcol.red   / 256;
-       unsigned int const g = xcol.green / 256;
-       unsigned int const b = xcol.blue  / 256;
-
-       return FL_PACK(r, g, b);
-}
-
-} // namespace anon
diff --git a/src/frontends/xforms/xformsGImage.h b/src/frontends/xforms/xformsGImage.h
deleted file mode 100644 (file)
index 4cef86e..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-// -*- C++ -*-
-/**
- *  \file xformsGImage.h
- *  Copyright 2002 the LyX Team
- *  Read the file COPYING
- *
- *  \author Angus Leeming, a.leeming@ic.ac.uk
- */
-
-/* An instantiation of GImage that makes use of the xforms lirary routines
- * to load and store the image in memory.
- */
-
-#ifndef XFORMS_GRAPHICSIMAGE_H
-#define XFORMS_GRAPHICSIMAGE_H
-
-#ifdef __GNUG__
-#pragma interface
-#endif
-
-#include "graphics/GraphicsImage.h"
-
-struct flimage_;
-typedef flimage_ FL_IMAGE;
-
-namespace grfx {
-
-class xformsGImage : public GImage
-{
-public:
-       /// Access to this class is through this static method.
-       static ImagePtr newImage();
-
-       /// Return the list of loadable formats.
-       static FormatList loadableFormats();
-
-       ///
-       ~xformsGImage();
-
-       /// Create a copy
-       GImage * clone() const;
-
-       ///
-       Pixmap getPixmap() const;
-
-       /// Get the image width
-       unsigned int getWidth() const;
-
-       /// Get the image height
-       unsigned int getHeight() const;
-
-       /** Load the image file into memory.
-        *  The process is asynchronous, so this method starts the loading
-        *  and saves the signal. It is emitted once loading is finished.
-        */
-       void load(string const & filename, SignalTypePtr);
-
-       /** Generate the pixmap, based on the current state of
-        *  image_ (clipped, rotated, scaled etc).
-        *  Uses the params to decide on color, grayscale etc.
-        *  Returns true if the pixmap is created.
-        */
-       bool setPixmap(GParams const & params);
-
-       /// Clip the image using params.
-       void clip(GParams const & params);
-
-       /// Rotate the image using params.
-       void rotate(GParams const & params);
-
-       /// Scale the image using params.
-       void scale(GParams const & params);
-
-       /// Internal callbacks.
-       void statusCB(string const &);
-       ///
-       void errorCB(string const &);
-
-private:
-       /// Access to the class is through newImage() and clone.
-       xformsGImage();
-       ///
-       xformsGImage(xformsGImage const &);
-
-       /// The xforms container.
-       FL_IMAGE * image_;
-
-       /// The pixmap itself.
-       Pixmap pixmap_;
-
-       /// Is the pixmap initialized?
-       enum PixmapStatus {
-               ///
-               PIXMAP_UNINITIALISED,
-               ///
-               PIXMAP_FAILED,
-               ///
-               PIXMAP_SUCCESS
-       };
-
-       PixmapStatus pixmap_status_;
-
-       /// Emit this signal when the loading process is finished.
-       GImage::SignalTypePtr on_finish_;
-};
-
-} // namespace grfx
-
-#endif // XFORMS_GRAPHICSIMAGE_H
diff --git a/src/frontends/xforms/xformsImage.C b/src/frontends/xforms/xformsImage.C
new file mode 100644 (file)
index 0000000..4c5847f
--- /dev/null
@@ -0,0 +1,456 @@
+/*
+ * \file xformsImage.C
+ * Copyright 2002 the LyX Team
+ * Read the file COPYING
+ *
+ * \author Angus Leeming, a.leeming@ic.ac.uk
+ */
+
+#include <config.h>
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+
+#include "xformsImage.h"
+#include "graphics/GraphicsParams.h"
+#include "LColor.h"
+#include "converter.h"              // formats
+#include "debug.h"
+#include "support/LAssert.h"
+#include "support/lyxfunctional.h"  // compare_memfun
+
+#include FORMS_H_LOCATION
+
+#ifdef HAVE_FLIMAGE_H
+# include <flimage.h>
+#else
+# ifdef HAVE_X11_FLIMAGE_H
+# include <X11/flimage.h>
+# endif
+#endif
+
+using std::find_if;
+
+namespace {
+
+void init_graphics();
+
+unsigned int packedcolor(LColor::color c);
+
+} // namespace anon
+
+
+namespace grfx {
+
+/// Access to this class is through this static method.
+Image::ImagePtr xformsImage::newImage()
+{
+       init_graphics();
+
+       ImagePtr ptr;
+       ptr.reset(new xformsImage);
+       return ptr;
+}
+
+
+/// Return the list of loadable formats.
+Image::FormatList xformsImage::loadableFormats()
+{
+       static FormatList fmts;
+       if (!fmts.empty())
+               return fmts;
+
+       init_graphics();
+
+       // The formats recognised by LyX
+       Formats::const_iterator begin = formats.begin();
+       Formats::const_iterator end   = formats.end();
+
+       lyxerr[Debug::GRAPHICS]
+               << "\nThe image loader can load the following directly:\n";
+
+       // Don't forget the Fortran numbering used by xforms!
+       int const nformats = flimage_get_number_of_formats();
+       for (int i = 1; i <= nformats; ++i) {
+
+               FLIMAGE_FORMAT_INFO const * info = flimage_get_format_info(i);
+               string const formal_name =
+                       info->formal_name ? info->formal_name : string();
+               string ext =
+                       info->extension   ? info->extension   : string();
+
+               if (ext.empty() || ext == "gz")
+                       continue;
+
+               if (ext == "rgb") ext = "sgi";
+
+               lyxerr[Debug::GRAPHICS]
+                       << formal_name << ", extension \"" << ext << "\"\n";
+
+               Formats::const_iterator it =
+                       find_if(begin, end,
+                               lyx::compare_memfun(&Format::extension, ext));
+               if (it != end)
+                       fmts.push_back(it->name());
+       }
+
+       lyxerr[Debug::GRAPHICS]
+               << "\nOf these, LyX recognises the following formats:\n";
+
+       FormatList::const_iterator fbegin = fmts.begin();
+       FormatList::const_iterator fend   = fmts.end();
+       for (FormatList::const_iterator fit = fbegin; fit != fend; ++fit) {
+               if (fit != fbegin)
+                       lyxerr[Debug::GRAPHICS] << ", ";
+               lyxerr[Debug::GRAPHICS] << *fit;
+       }
+       lyxerr[Debug::GRAPHICS] << '\n' << std::endl;
+
+       return fmts;
+}
+
+
+xformsImage::xformsImage()
+       : image_(0),
+         pixmap_(0),
+         pixmap_status_(PIXMAP_UNINITIALISED)
+{}
+
+
+xformsImage::xformsImage(xformsImage const & other)
+       : Image(other),
+         image_(0),
+         pixmap_(0),
+         pixmap_status_(PIXMAP_UNINITIALISED)
+{
+       if (other.image_) {
+               image_ = flimage_dup(other.image_);
+               image_->u_vdata = this;
+       }
+}
+
+
+xformsImage::~xformsImage()
+{
+       if (image_)
+               flimage_free(image_);
+       if (pixmap_)
+               XFreePixmap(fl_get_display(), pixmap_);
+}
+
+
+Image * xformsImage::clone() const
+{
+       return new xformsImage(*this);
+}
+
+
+unsigned int xformsImage::getWidth() const
+{
+       if (!image_)
+               return 0;
+       return image_->w;
+}
+
+
+unsigned int xformsImage::getHeight() const
+{
+       if (!image_)
+               return 0;
+       return image_->h;
+}
+
+
+Pixmap xformsImage::getPixmap() const
+{
+       if (!pixmap_status_ == PIXMAP_SUCCESS)
+               return 0;
+       return pixmap_;
+}
+
+
+void xformsImage::load(string const & filename)
+{
+       if (image_) {
+               lyxerr[Debug::GRAPHICS]
+                       << "Image is loaded already!" << std::endl;
+               finishedLoading(false);
+               return;
+       }
+
+       image_ = flimage_open(filename.c_str());
+       if (!image_) {
+               lyxerr[Debug::GRAPHICS]
+                       << "Unable to open image" << std::endl;
+               finishedLoading(false);
+               return;
+       }
+
+       // Set this now and we won't need to bother again.
+       image_->fill_color = packedcolor(LColor::graphicsbg);
+
+       // Used by the callback routines to return to this
+       image_->u_vdata = this;
+
+       // Begin the reading process.
+       flimage_read(image_);
+}
+
+
+bool xformsImage::setPixmap(Params const & params)
+{
+       if (!image_ || params.display == NoDisplay)
+               return false;
+
+       Display * display = fl_get_display();
+
+       if (pixmap_ && pixmap_status_ == PIXMAP_SUCCESS)
+               XFreePixmap(display, pixmap_);
+
+       int color_key;
+       switch (params.display) {
+       case MonochromeDisplay:
+               color_key = FL_IMAGE_MONO;
+               break;
+       case GrayscaleDisplay:
+               color_key = FL_IMAGE_GRAY;
+               break;
+       case ColorDisplay:
+       default: // NoDisplay cannot happen!
+               color_key = FL_IMAGE_RGB;
+               break;
+       }
+
+       if (color_key != FL_IMAGE_RGB) {
+               flimage_convert(image_, color_key, 0);
+       }
+
+       unsigned int fill = packedcolor(LColor::graphicsbg);
+       if (fill != image_->fill_color) {
+               // the background color has changed.
+               // Note that in grayscale/monochrome images the background is
+               // grayed also, so this call will have no visible effect. Sorry!
+               flimage_replace_pixel(image_, image_->fill_color, fill);
+               image_->fill_color = fill;
+       }
+
+       image_->xdisplay = display;
+       Screen * screen  = ScreenOfDisplay(display, fl_screen);
+
+       pixmap_ = flimage_to_pixmap(image_, XRootWindowOfScreen(screen));
+       pixmap_status_ = pixmap_ ? PIXMAP_SUCCESS : PIXMAP_FAILED;
+
+       return pixmap_status_ == PIXMAP_SUCCESS;
+}
+
+
+void xformsImage::clip(Params const & params)
+{
+       if (!image_)
+               return;
+
+       if (params.bb.empty())
+               // No clipping is necessary.
+               return;
+
+       int const new_width  = params.bb.xr - params.bb.xl;
+       int const new_height = params.bb.yt - params.bb.yb;
+
+       // No need to check if the width, height are > 0 because the
+       // Bounding Box would be empty() in this case.
+       if (new_width > image_->w || new_height > image_->h)
+               // Bounds are invalid.
+               return;
+
+       if (new_width == image_->w && new_height == image_->h)
+               // Bounds are unchanged.
+               return;
+
+       int const xoffset_l = std::max(0, params.bb.xl);
+       int const xoffset_r = std::max(0, image_->w - params.bb.xr);
+       int const yoffset_t = std::max(0, image_->h - params.bb.yt);
+       int const yoffset_b = std::max(0, params.bb.yb);
+
+       flimage_crop(image_, xoffset_l, yoffset_t, xoffset_r, yoffset_b);
+}
+
+
+void xformsImage::rotate(Params const & params)
+{
+       if (!image_)
+               return ;
+
+       if (!params.angle)
+               // No rotation is necessary.
+               return;
+
+       // The angle passed to flimage_rotate is the angle in one-tenth of a
+       // degree units.
+
+       // Work around xforms bug when params.angle == 270
+       // the 'InternalError: bad special angle' error.
+       // This bug fix is not needed in xforms 1.0 and greater.
+       if (params.angle == 270) {
+               flimage_rotate(image_,  900, FLIMAGE_SUBPIXEL);
+               flimage_rotate(image_, 1800, FLIMAGE_SUBPIXEL);
+       } else {
+               flimage_rotate(image_, params.angle * 10, FLIMAGE_SUBPIXEL);
+       }
+}
+
+
+void xformsImage::scale(Params const & params)
+{
+       if (!image_)
+               return;
+
+       // boost::tie produces horrible compilation errors on my machine
+       // Angus 25 Feb 2002
+       std::pair<unsigned int, unsigned int> d = getScaledDimensions(params);
+       unsigned int const width  = d.first;
+       unsigned int const height = d.second;
+
+       if (width == getWidth() && height == getHeight())
+               // No scaling needed
+               return;
+
+       flimage_scale(image_, width, height, FLIMAGE_SUBPIXEL);
+}
+
+
+void xformsImage::statusCB(string const & status_message)
+{
+       if (status_message.empty())
+               return;
+
+       if (prefixIs(status_message, "Done Reading")) {
+               if (image_) {
+                       flimage_close(image_);
+               }
+
+               finishedLoading(true);
+       }
+}
+
+
+void xformsImage::errorCB(string const & error_message)
+{
+       if (error_message.empty())
+               return;
+
+       if (image_) {
+               flimage_close(image_);
+       }
+
+       finishedLoading(false);
+}
+
+} // namespace grfx
+
+
+namespace {
+
+extern "C" {
+
+int status_report(FL_IMAGE * ob, const char *s)
+{
+       lyx::Assert(ob && ob->u_vdata);
+
+       string const str = s ? strip(s) : string();
+       if (str.empty())
+               return 0;
+
+       lyxerr[Debug::GRAPHICS]
+               << "xforms image loader. Status : " << str << std::endl;
+
+       grfx::xformsImage * ptr =
+               static_cast<grfx::xformsImage *>(ob->u_vdata);
+       ptr->statusCB(str);
+
+       return 0;
+}
+
+
+static void error_report(FL_IMAGE * ob, const char *s)
+{
+       lyx::Assert(ob && ob->u_vdata);
+
+       string const str = s ? strip(s) : string();
+       if (str.empty())
+               return;
+
+       lyxerr[Debug::GRAPHICS]
+               << "xforms image loader. Error : " << str << std::endl;
+
+       grfx::xformsImage * ptr =
+               static_cast<grfx::xformsImage *>(ob->u_vdata);
+       ptr->errorCB(str);
+}
+
+} // extern "C"
+
+
+void init_graphics()
+{
+       // Paranoia check
+       static bool initialised = false;
+       if (initialised)
+               return;
+       initialised = true;
+
+       flimage_enable_bmp();
+       flimage_enable_fits();
+       flimage_enable_gif();
+#ifdef HAVE_FLIMAGE_ENABLE_JPEG
+       flimage_enable_jpeg();
+#endif
+
+       // xforms itself uses pngtopnm to convert to a loadable format.
+       // We prefer to use our own conversion mechanism, therefore.
+       // flimage_enable_png();
+
+       flimage_enable_pnm();
+
+#ifdef HAVE_FLIMAGE_ENABLE_PS
+       // xforms recognises PS but not EPS
+       flimage_enable_ps();
+#endif
+
+       flimage_enable_sgi();
+       flimage_enable_tiff();
+       flimage_enable_xbm();
+       flimage_enable_xwd();
+       flimage_enable_xpm();
+
+       // xforms stores this permanently (does not make a copy) so
+       // this should never be destroyed.
+       static FLIMAGE_SETUP setup;
+       setup.visual_cue    = status_report;
+       setup.error_message = error_report;
+       flimage_setup(&setup);
+}
+
+
+unsigned int packedcolor(LColor::color c)
+{
+       string const x11color = lcolor.getX11Name(c);
+
+       Display * display = fl_get_display();
+       Colormap cmap     = fl_state[fl_get_vclass()].colormap;
+       XColor xcol;
+       XColor ccol;
+       if (XLookupColor(display, cmap, x11color.c_str(), &xcol, &ccol) == 0)
+               // Unable to parse x11color.
+               return FL_PACK(255,255,255);
+
+       // Note that X stores the RGB values in the range 0 - 65535
+       // whilst we require them in the range 0 - 255.
+       unsigned int const r = xcol.red   / 256;
+       unsigned int const g = xcol.green / 256;
+       unsigned int const b = xcol.blue  / 256;
+
+       return FL_PACK(r, g, b);
+}
+
+} // namespace anon
diff --git a/src/frontends/xforms/xformsImage.h b/src/frontends/xforms/xformsImage.h
new file mode 100644 (file)
index 0000000..ac922bd
--- /dev/null
@@ -0,0 +1,106 @@
+// -*- C++ -*-
+/**
+ *  \file xformsImage.h
+ *  Copyright 2002 the LyX Team
+ *  Read the file COPYING
+ *
+ *  \author Angus Leeming, a.leeming@ic.ac.uk
+ */
+
+/* An instantiation of Image that makes use of the xforms lirary routines
+ * to load and store the image in memory.
+ */
+
+#ifndef XFORMSIMAGE_H
+#define XFORMSIMAGE_H
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "graphics/GraphicsImage.h"
+
+struct flimage_;
+typedef flimage_ FL_IMAGE;
+
+namespace grfx {
+
+class xformsImage : public Image
+{
+public:
+       /// Access to this class is through this static method.
+       static ImagePtr newImage();
+
+       /// Return the list of loadable formats.
+       static FormatList loadableFormats();
+
+       ///
+       ~xformsImage();
+
+       /// Create a copy
+       Image * clone() const;
+
+       ///
+       Pixmap getPixmap() const;
+
+       /// Get the image width
+       unsigned int getWidth() const;
+
+       /// Get the image height
+       unsigned int getHeight() const;
+
+       /** Load the image file into memory.
+        *  The process is asynchronous, so this method starts the loading.
+        *  When finished, the Image::finishedLoading signal is emitted.
+        */
+       void load(string const & filename);
+
+       /** Generate the pixmap, based on the current state of
+        *  image_ (clipped, rotated, scaled etc).
+        *  Uses the params to decide on color, grayscale etc.
+        *  Returns true if the pixmap is created.
+        */
+       bool setPixmap(Params const & params);
+
+       /// Clip the image using params.
+       void clip(Params const & params);
+
+       /// Rotate the image using params.
+       void rotate(Params const & params);
+
+       /// Scale the image using params.
+       void scale(Params const & params);
+
+       /// Internal callbacks.
+       void statusCB(string const &);
+       ///
+       void errorCB(string const &);
+
+private:
+       /// Access to the class is through newImage() and clone.
+       xformsImage();
+       ///
+       xformsImage(xformsImage const &);
+
+       /// The xforms container.
+       FL_IMAGE * image_;
+
+       /// The pixmap itself.
+       Pixmap pixmap_;
+
+       /// Is the pixmap initialized?
+       enum PixmapStatus {
+               ///
+               PIXMAP_UNINITIALISED,
+               ///
+               PIXMAP_FAILED,
+               ///
+               PIXMAP_SUCCESS
+       };
+
+       PixmapStatus pixmap_status_;
+};
+
+} // namespace grfx
+
+#endif // XFORMSIMAGE_H
index 87389b69c09a1d4f1f5c794b8486f51308b77e52..7058c9c33f14fcbab37a1ea8a363bebd926249e5 100644 (file)
@@ -1,3 +1,38 @@
+2002-06-28  Angus Leeming  <leeming@lyx.org>
+
+       * GraphicsCacheItem.[Ch]: refactor some of the more convoluted logic
+       by moving those SignalPtrs into the grfx::Image and grfx::Converter
+       classes where they really belong.
+       Use the Pimpl idiom to hide the class internals from public view.
+
+       * GraphicsTypes: remove the typedefs, leaving only the enums.
+
+       * GraphicsImage.h: now has a finishedLoading signal, as opposed to being
+       passed a reference to one in the load() method.
+
+       * GraphicsConverter.[Ch]: totally refactored. An instance of
+       grfx::Converter now represents a single conversion process.
+       Thus grfx::CachItem now has a grfx::Converter * that is set when the
+       conversion is initiated and destroyed on completion.
+       
+       * GraphicsCache.[Ch]:
+       * GraphicsCacheItem.[Ch]:
+       * GraphicsConverter.[Ch]:
+       * GraphicsLoader.[Ch]: use the Pimpl idiom to hide the class internals
+       from public view.
+       Note that I have done this only after making the above changes,
+       so not only should we have a clean, minimal and well documented
+       interface to these classes in the header files, but the class internals
+       should be much clearer too.
+       
+       * Renamed classes
+       grfx::GCache -> grfx::Cache,
+       grfx::GCacheItem -> grfx::CacheItem,
+       grfx::GConverter -> grfx::Converter,
+       grfx::GImage -> grfx::Image,
+       grfx::GImageXPM -> grfx::ImageXPM,
+       grfx::GParams -> grfx::Params.
+
 2002-06-26  Angus Leeming  <leeming@lyx.org>
 
        * GraphicsLoader.[Ch]: use boost::scoped_ptr in preference to
index 16a3e2aa93225f98c8c3434b0e738c0085dac6a4..f56c3ae4ee123caea8c570755db1fe3a85177b1d 100644 (file)
 
 #include "frontends/lyx_gui.h"
 
+#include <map>
+
 namespace grfx {
 
-GCache & GCache::get()
+/** The cache contains one item per file, so use a map to find the
+ *  cache item quickly by filename.
+ */
+typedef std::map<string, Cache::ItemPtr> CacheType;
+
+struct Cache::Impl {
+       ///
+       CacheType cache;
+};
+
+       
+Cache & Cache::get()
 {
        static bool start = true;
        if (start) {
@@ -34,92 +47,76 @@ GCache & GCache::get()
        }
 
        // Now return the cache
-       static GCache singleton;
+       static Cache singleton;
        return singleton;
 }
 
 
-GCache::GCache()
-{
-       cache = new CacheType;
-}
+Cache::Cache()
+       : pimpl_(new Impl())
+{}
 
 
-// all elements are destroyed by the shared_ptr's in the map.
-GCache::~GCache()
-{
-       delete cache;
-}
+Cache::~Cache()
+{}
 
 
-std::vector<string> GCache::loadableFormats() const
+std::vector<string> Cache::loadableFormats() const
 {
-       return GImage::loadableFormats();
+       return Image::loadableFormats();
 }
 
 
-void GCache::add(string const & file)
+void Cache::add(string const & file)
 {
        if (!AbsolutePath(file)) {
-               lyxerr << "GCacheItem::add(" << file << "):\n"
+               lyxerr << "Cache::add(" << file << "):\n"
                       << "The file must be have an absolute path."
                       << std::endl;
                return;
        }
-       
+
        // Is the file in the cache already?
        if (inCache(file)) {
-               lyxerr[Debug::GRAPHICS] << "GCache::add(" << file << "):\n"
+               lyxerr[Debug::GRAPHICS] << "Cache::add(" << file << "):\n"
                                        << "The file is already in the cache."
                                        << std::endl;
                return;
        }
 
-       
-       (*cache)[file] = GraphicPtr(new GCacheItem(file));
+       pimpl_->cache[file] = ItemPtr(new CacheItem(file));
 }
 
 
-void GCache::remove(string const & file)
+void Cache::remove(string const & file)
 {
-       CacheType::iterator it = cache->find(file);
-       if (it == cache->end())
+       CacheType::iterator it = pimpl_->cache.find(file);
+       if (it == pimpl_->cache.end())
                return;
 
-       GraphicPtr item = it->second;
-       
+       ItemPtr & item = it->second;
+
        if (item.use_count() == 1) {
                // The graphics file is in the cache, but nothing else
                // references it.
-               cache->erase(it);
+               pimpl_->cache.erase(it);
        }
 }
 
 
-bool GCache::inCache(string const & file) const
+bool Cache::inCache(string const & file) const
 {
-       return cache->find(file) != cache->end();
+       return pimpl_->cache.find(file) != pimpl_->cache.end();
 }
 
 
-GraphicPtr const GCache::graphic(string const & file) const
+Cache::ItemPtr const Cache::item(string const & file) const
 {
-       CacheType::const_iterator it = cache->find(file);
-       if (it == cache->end())
-               return GraphicPtr();
+       CacheType::const_iterator it = pimpl_->cache.find(file);
+       if (it == pimpl_->cache.end())
+               return ItemPtr();
 
        return it->second;
 }
 
-
-ImagePtr const GCache::image(string const & file) const
-{
-       CacheType::const_iterator it = cache->find(file);
-       if (it == cache->end())
-               return ImagePtr();
-
-       return it->second->image();
-}
-
-
 } // namespace grfx
index 3c90ee312fe2159063e1a290c58955597017bf3b..1106e6b005f4ff1a24469cd307002e7c50afbc36 100644 (file)
@@ -7,10 +7,10 @@
  * \author Baruch Even <baruch.even@writeme.com>
  * \author Angus Leeming <a.leeming@ic.ac.uk>
  *
- *  grfx::GCache is the manager of the image cache.
- *  It is responsible for creating the grfx::GCacheItem's and maintaining them.
+ *  grfx::Cache is the manager of the image cache.
+ *  It is responsible for creating the grfx::CacheItem's and maintaining them.
  *
- *  grfx::GCache is a singleton class. It is possible to have only one
+ *  grfx::Cache is a singleton class. It is possible to have only one
  *  instance of it at any moment.
  */
 
 #endif
 
 #include "LString.h"
-#include "GraphicsTypes.h"
-#include <map>
 #include <vector>
 #include <boost/utility.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+
 
 namespace grfx {
 
-class GCache : boost::noncopyable {
+class CacheItem;
+
+class Cache : boost::noncopyable {
 public:
 
        /// This is a singleton class. Get the instance.
-       static GCache & get();
+       static Cache & get();
 
        /** Which graphics formats can be loaded directly by the image loader.
         *  Other formats can be loaded if a converter to a loadable format
@@ -44,10 +47,7 @@ public:
        /// Add a graphics file to the cache.
        void add(string const & file);
 
-       /** Remove a file from the cache.
-        *  Called from the InsetGraphics d-tor.
-        *  If we use reference counting, then this may become redundant.
-        */
+       /// Remove a file from the cache.
        void remove(string const & file);
 
        /// Returns \c true if the file is in the cache.
@@ -63,36 +63,24 @@ public:
         *
         *  You have been warned!
         */
-       GraphicPtr const graphic(string const & file) const;
-
-       /** Get the image associated with file.
-           If the image is not yet loaded, (or is not in the cache!) return
-           an empty container.
-        */
-       ImagePtr const image(string const & file) const;
+       typedef boost::shared_ptr<CacheItem> ItemPtr;
+       ///
+       ItemPtr const item(string const & file) const;
 
 private:
        /** Make the c-tor, d-tor private so we can control how many objects
         *  are instantiated.
         */
-       GCache();
+       Cache();
        ///
-       ~GCache();
-
-       /** The cache contains one item per file, so use a map to find the
-        *  cache item quickly by filename.
-        *  Note that each cache item can have multiple views, potentially one
-        *  per inset that references the original file.
-        */
-       typedef std::map<string, GraphicPtr> CacheType;
+       ~Cache();
 
-       /** Store a pointer to the cache so that we can forward declare
-        *  GCacheItem.
-        */
-       CacheType * cache;
+       /// Use the Pimpl idiom to hide the internals.
+       class Impl;
+       /// The pointer never changes although *pimpl_'s contents may.
+       boost::scoped_ptr<Impl> const pimpl_;
 };
 
 } // namespace grfx
 
-
 #endif // GRAPHICSCACHE_H
index 833f29b1690d0e84aaf88b780d534a3a6c0adfa6..a179917b2389636c577852564b1198b747445e7a 100644 (file)
 #include "support/LAssert.h"
 #include "support/filetools.h"
 
+#include <boost/shared_ptr.hpp>
 #include <boost/bind.hpp>
+#include <boost/signals/connection.hpp>
+#include <boost/signals/trackable.hpp>
 
 using std::endl;
 
-
 namespace grfx {
 
-GCacheItem::GCacheItem(string const & file)
-       : filename_(file), zipped_(false),
-         remove_loaded_file_(false), status_(WaitingToLoad)
+struct CacheItem::Impl : public boost::signals::trackable {
+
+       ///
+       Impl(CacheItem &, string const & file);
+
+       /** Start the image conversion process, checking first that it is
+        *  necessary. If it is necessary, then a conversion task is started.
+        *  CacheItem asumes that the conversion is asynchronous and so
+        *  passes a Signal to the converting routine. When the conversion
+        *  is finished, this Signal is emitted, returning the converted
+        *  file to this->imageConverted.
+        *
+        *  If no file conversion is needed, then convertToDisplayFormat() calls
+        *  loadImage() directly.
+        *
+        *  convertToDisplayFormat() will set the loading status flag as
+        *  approriate through calls to setStatus().
+        */
+       void convertToDisplayFormat();
+
+       /** Load the image into memory. This is called either from
+        *  convertToDisplayFormat() direct or from imageConverted().
+        */
+       void loadImage();
+
+       /** Get a notification when the image conversion is done.
+        *  Connected to a signal on_finish_ which is passed to
+        *  Converter::convert.
+        */
+       void imageConverted(bool);
+
+       /** Get a notification when the image loading is done.
+        *  Connected to a signal on_finish_ which is passed to
+        *  grfx::Image::loadImage.
+        */
+       void imageLoaded(bool);
+
+       /** Sets the status of the loading process. Also notifies
+        *  listeners that the status has chacnged.
+        */
+       void setStatus(ImageStatus new_status);
+
+       ///
+       CacheItem & parent_;
+
+       /// The filename we refer too.
+       string filename_;
+       /// Is the file compressed?
+       bool zipped_;
+       /// If so, store the uncompressed file in this temporary file.
+       string unzipped_filename_;
+       /// What file are we trying to load?
+       string file_to_load_;
+       /** Should we delete the file after loading? True if the file is
+        *  the result of a conversion process.
+        */
+       bool remove_loaded_file_;
+
+       /// The image and its loading status.
+       boost::shared_ptr<Image> image_;
+       ///
+       ImageStatus status_;
+
+       /// The connection to the signal Image::finishedLoading
+       boost::signals::connection cl_;
+
+       /// The connection of the signal ConvProcess::finishedConversion,
+       boost::signals::connection cc_;
+
+       ///
+       boost::scoped_ptr<Converter> converter_;
+};
+
+
+CacheItem::CacheItem(string const & file)
+       : pimpl_(new Impl(*this, file))
 {}
 
+                
+CacheItem::~CacheItem()
+{}
 
-void GCacheItem::startLoading()
+
+string const & CacheItem::filename() const
 {
-       if (status() != WaitingToLoad)
+       return pimpl_->filename_;
+}
+
+
+void CacheItem::startLoading()
+{
+       if (pimpl_->status_ != WaitingToLoad)
                return;
 
-       convertToDisplayFormat();
+       pimpl_->convertToDisplayFormat();
+}
+
+
+Image const * CacheItem::image() const
+{
+       return pimpl_->image_.get();
 }
 
 
-void GCacheItem::setStatus(ImageStatus new_status)
+ImageStatus CacheItem::status() const
+{
+       return pimpl_->status_;
+}
+
+
+//------------------------------
+// Implementation details follow
+//------------------------------
+
+
+CacheItem::Impl::Impl(CacheItem & p, string const & file)
+       : parent_(p), filename_(file), zipped_(false),
+         remove_loaded_file_(false), status_(WaitingToLoad)
+{}
+
+
+void CacheItem::Impl::setStatus(ImageStatus new_status)
 {
        if (status_ == new_status)
                return;
 
        status_ = new_status;
-       statusChanged();
+       parent_.statusChanged();
 }
 
 
-void GCacheItem::imageConverted(string const & file_to_load)
+void CacheItem::Impl::imageConverted(bool success)
 {
-       bool const success =
-               (!file_to_load.empty() && IsFileReadable(file_to_load));
-
        string const text = success ? "succeeded" : "failed";
        lyxerr[Debug::GRAPHICS] << "Image conversion " << text << "." << endl;
 
+       file_to_load_ = converter_.get() ?
+               converter_->convertedFile() : string();
+       converter_.reset();
+       cc_.disconnect();
+       
+       success = !file_to_load_.empty() && IsFileReadable(file_to_load_);
+       lyxerr[Debug::GRAPHICS] << "Unable to find converted file!" << endl;
+
        if (!success) {
                setStatus(ErrorConverting);
 
@@ -72,34 +185,27 @@ void GCacheItem::imageConverted(string const & file_to_load)
                return;
        }
 
-       cc_.disconnect();
-
-       // Do the actual image loading from file to memory.
-       file_to_load_ = file_to_load;
-
        loadImage();
 }
 
 
 // This function gets called from the callback after the image has been
 // converted successfully.
-void GCacheItem::loadImage()
+void CacheItem::Impl::loadImage()
 {
        setStatus(Loading);
        lyxerr[Debug::GRAPHICS] << "Loading image." << endl;
 
-       // Connect a signal to this->imageLoaded and pass this signal to
-       // GImage::loadImage.
-       SignalLoadTypePtr on_finish;
-       on_finish.reset(new SignalLoadType);
-       cl_ = on_finish->connect(boost::bind(&GCacheItem::imageLoaded, this, _1));
+       image_ = Image::newImage();
 
-       image_ = GImage::newImage();
-       image_->load(file_to_load_, on_finish);
+       cl_.disconnect();
+       cl_ = image_->finishedLoading.connect(
+               boost::bind(&Impl::imageLoaded, this, _1));
+       image_->load(file_to_load_);
 }
 
 
-void GCacheItem::imageLoaded(bool success)
+void CacheItem::Impl::imageLoaded(bool success)
 {
        string const text = success ? "succeeded" : "failed";
        lyxerr[Debug::GRAPHICS] << "Image loading " << text << "." << endl;
@@ -121,19 +227,21 @@ void GCacheItem::imageLoaded(bool success)
        setStatus(Loaded);
 }
 
+} // namespace grfx
+
 
 namespace {
 
 string const findTargetFormat(string const & from)
 {
-       typedef GImage::FormatList FormatList;
-       FormatList const formats = GImage::loadableFormats();
+       typedef grfx::Image::FormatList FormatList;
+       FormatList const formats = grfx::Image::loadableFormats();
 
        // There must be a format to load from.
        lyx::Assert(!formats.empty());
 
        // First ascertain if we can load directly with no conversion
-       FormatList::const_iterator it1  = formats.begin();
+       FormatList::const_iterator it1 = formats.begin();
        FormatList::const_iterator end = formats.end();
        for (; it1 != end; ++it1) {
                if (from == *it1)
@@ -141,11 +249,9 @@ string const findTargetFormat(string const & from)
        }
 
        // So, we have to convert to a loadable format. Can we?
-       grfx::GConverter const & graphics_converter = grfx::GConverter::get();
-
-       FormatList::const_iterator it2  = formats.begin();
+       FormatList::const_iterator it2 = formats.begin();
        for (; it2 != end; ++it2) {
-               if (graphics_converter.isReachable(from, *it2))
+               if (grfx::Converter::isReachable(from, *it2))
                        return *it2;
        }
 
@@ -157,7 +263,9 @@ string const findTargetFormat(string const & from)
 } // anon namespace
 
 
-void GCacheItem::convertToDisplayFormat()
+namespace grfx {
+
+void CacheItem::Impl::convertToDisplayFormat()
 {
        setStatus(Converting);
        // Make a local copy in case we unzip it
@@ -187,7 +295,7 @@ void GCacheItem::convertToDisplayFormat()
        } else
                lyxerr[Debug::GRAPHICS] 
                        << "\n\tThe file contains " << from << " format data." << endl;
-       string const to = grfx::findTargetFormat(from);
+       string const to = findTargetFormat(from);
 
        if (from == to) {
                // No conversion needed!
@@ -212,12 +320,10 @@ void GCacheItem::convertToDisplayFormat()
        // Connect a signal to this->imageConverted and pass this signal to
        // the graphics converter so that we can load the modified file
        // on completion of the conversion process.
-       SignalConvertTypePtr on_finish;
-       on_finish.reset(new SignalConvertType);
-       cc_ = on_finish->connect(boost::bind(&GCacheItem::imageConverted, this, _1));
-
-       GConverter & graphics_converter = GConverter::get();
-       graphics_converter.convert(filename, to_file_base, from, to, on_finish);
+       converter_.reset(new Converter(filename, to_file_base, from, to));
+       converter_->finishedConversion.connect(
+               boost::bind(&Impl::imageConverted, this, _1));
+       converter_->startConversion();
 }
 
 } // namespace grfx
index b3ccf7d8e282e52ff5d079f826e461558cda0037..2f89a796b9e64053f469f826c1b4943a00f2a5ee 100644 (file)
@@ -7,18 +7,20 @@
  * \author Baruch Even <baruch.even@writeme.com>
  * \author Angus Leeming <a.leeming@ic.ac.uk>
  *
- * The graphics cache is a container of GCacheItems. Each GCacheItem, defined
- * here represents a separate image file. The routines here can be used to
- * load the graphics file into memory at which point (status() == grfx::Loaded).
- * The user is then free to access image() in order to transform the image
- * (rotate, scale, clip) and to generate the pixmap.
+ * The graphics cache is a container of grfx::CacheItems.
+ * Each grfx::CacheItem, definedhere represents a separate image file.
+ *
+ * The routines here can be used to load the graphics file into memory at
+ * which point (status() == grfx::Loaded).
+ * The user is then free to access image() in order to copy it and to then
+ * transform the copy (rotate, scale, clip) and to generate the pixmap.
  *
  * The graphics cache supports fully asynchronous:
  * file conversion to a loadable format;
  * file loading.
  *
- * Whether you get that, of course, depends on grfx::GConverter and on the
- * grfx::GImage-derived image class.
+ * Whether you get that, of course, depends on grfx::Converter and on the
+ * grfx::Image-derived image class.
  */
 
 #ifndef GRAPHICSCACHEITEM_H
 #include "LString.h"
 
 #include <boost/utility.hpp>
-#include <boost/shared_ptr.hpp>
-
+#include <boost/scoped_ptr.hpp>
 #include <boost/signals/signal0.hpp>
-#include <boost/signals/signal1.hpp>
-#include <boost/signals/connection.hpp>
-#include <boost/signals/trackable.hpp>
 
 class InsetGraphics;
 
 namespace grfx {
 
-/// A grfx::GCache item holder.
-class GCacheItem : boost::noncopyable, public boost::signals::trackable {
+class Image;
+class Converter;
+
+/// A grfx::Cache item holder.
+class CacheItem : boost::noncopyable {
 public:
        ///
-       GCacheItem(string const & file);
+       CacheItem(string const & file);
+
+       /// Define an empty d-tor out-of-line to keep boost::scoped_ptr happy.
+       ~CacheItem();
+
+       ///
+       string const & filename() const;
 
        /// It's in the cache. Now start the loading process.
        void startLoading();
 
        /** Get the image associated with filename_.
-           If the image is not yet loaded, return a null pointer.
+        *  If the image is not yet loaded, returns 0.
+        *  This routine returns a pointer to const; if you want to modify it,
+        *  create a copy and modify that.
         */
-       ImagePtr const image() const { return image_; }
+       Image const * image() const;
 
        /// How far have we got in loading the image?
-       ImageStatus status() const { return status_; }
+       ImageStatus status() const;
 
        /// This signal is emitted when the image loading status changes.
        boost::signal0<void> statusChanged;
 
-       ///
-       string const & filename() const { return filename_; }
-
 private:
-       /** Start the image conversion process, checking first that it is
-        *  necessary. If it is necessary, then a conversion task is started.
-        *  GCacheItem asumes that the conversion is asynchronous and so
-        *  passes a Signal to the converting routine. When the conversion
-        *  is finished, this Signal is emitted, returning the converted
-        *  file to this->imageConverted.
-        *
-        *  If no file conversion is needed, then convertToDisplayFormat() calls
-        *  loadImage() directly.
-        *
-        *  convertToDisplayFormat() will set the loading status flag as
-        *  approriate through calls to setStatus().
-        */
-       void convertToDisplayFormat();
-
-       /** Load the image into memory. This is called either from
-        *  convertToDisplayFormat() direct or from imageConverted().
-        */
-       void loadImage();
-
-       /** Get a notification when the image conversion is done.
-        *  Connected to a signal on_finish_ which is passed to
-        *  GConverter::convert.
-        */
-       void imageConverted(string const & file_to_load);
-
-       /** Get a notification when the image loading is done.
-        *  Connected to a signal on_finish_ which is passed to
-        *  GImage::loadImage.
-        */
-       void imageLoaded(bool);
-
-       /** Sets the status of the loading process. Also notifies
-        *  listeners that the status has chacnged.
-        */
-       void setStatus(ImageStatus new_status);
-
-       /// The filename we refer too.
-       string filename_;
-       /// Is the file compressed?
-       bool zipped_;
-       /// If so, store the uncompressed file in this temporary file.
-       string unzipped_filename_;
-       /// What file are we trying to load?
-       string file_to_load_;
-       /** Should we delete the file after loading? True if the file is
-        *  the result of a conversion process.
-        */
-       bool remove_loaded_file_;
-
-       /// The image and its loading status.
-       ImagePtr image_;
-       ///
-       ImageStatus status_;
-
-       /** A SignalLoadTypePtr is connected to this->imageLoaded and
-        *  then passed to ImagePtr::load.
-        *  When the image has been loaded, the signal is emitted.
-        *
-        *  We pass a shared_ptr because it is eminently possible for the
-        *  GCacheItem to be destructed before the loading is complete and
-        *  the signal must remain in scope. It doesn't matter if the slot
-        *  disappears, SigC takes care of that.
-        */
-       typedef boost::signal1<void, bool> SignalLoadType;
-       ///
-       typedef boost::shared_ptr<SignalLoadType> SignalLoadTypePtr;
-
-       /// The connection of the signal passed to ImagePtr::loadImage.
-       boost::signals::connection cl_;
-
-       /** A SignalConvertTypePtr is connected to this->imageConverted and
-        *  then passed to GConverter::convert.
-        *  When the image has been converted to a loadable format, the signal
-        *  is emitted, returning the name of the loadable file to
-        *  imageConverted.
-        */
-       typedef boost::signal1<void, string const &> SignalConvertType;
-       ///
-       typedef boost::shared_ptr<SignalConvertType> SignalConvertTypePtr;
+       /// Use the Pimpl idiom to hide the internals.
+       class Impl;
 
-       /// The connection of the signal passed to GConverter::convert.
-       boost::signals::connection cc_;
+       /// The pointer never changes although *pimpl_'s contents may.
+       boost::scoped_ptr<Impl> const pimpl_;
 };
 
 } // namespace grfx
index fbf5f6759e1b049366e7eb1e8ae2d906371fc9e5..841d6d189103cc3c168dad0922c921125eeca2bc 100644 (file)
@@ -1,9 +1,9 @@
-/*
- * \file GraphicsConverter.C
- * Copyright 2002 the LyX Team
- * Read the file COPYING
+/**
+ *  \file GraphicsConverter.C
+ *  Copyright 2002 the LyX Team
+ *  Read the file COPYING
  *
- * \author Angus Leeming <a.leeming@ic.ac.uk>
+ *  \author Angus Leeming <a.leeming@ic.ac.uk>
  */
 
 #include <config.h>
 
 #include "converter.h"
 #include "debug.h"
-#include "gettext.h"
 
 #include "support/filetools.h"
 #include "support/forkedcall.h"
-#include "support/path.h"
+#include "support/lyxlib.h"
 
 #include <boost/bind.hpp>
+#include <boost/signals/trackable.hpp>
 
+#include "Lsstream.h"
 #include <fstream>
+#include <sys/types.h> // needed for pid_t
 
 using std::endl;
 
+namespace grfx {
 
-namespace {
+struct Converter::Impl : public boost::signals::trackable {
+       ///
+       Impl(Converter &,
+            string const &, string const &, string const &, string const &);
+
+       ///
+       void startConversion();
+
+       /** This method is connected to a signal passed to the forked call
+        *  class, passing control back here when the conversion is completed.
+        *  Cleans-up the temporary files, emits the finishedConversion
+        *  signal and removes the Converter from the list of all processes.
+        */
+       void converted(string const & cmd, pid_t pid, int retval);
+
+       ///
+       string script_command_;
+       ///
+       string script_file_;
+       ///
+       string to_file_;
+       ///
+       Converter & parent_;
+       ///
+       bool valid_process_;
+       ///
+       bool finished_;
+};
 
-string const move_file(string const & from_file, string const & to_file)
-{
-       if (from_file == to_file)
-               return string();
 
-       ostringstream command;
-       command << "fromfile=" << from_file << "\n"
-               << "tofile="   << to_file << "\n\n"
-               << "'mv' -f ${fromfile} ${tofile}\n"
-               << "if [ $? -ne 0 ]; then\n"
-               << "\t'cp' -f ${fromfile} ${tofile}\n"
-               << "\tif [ $? -ne 0 ]; then\n"
-               << "\t\texit 1\n"
-               << "\tfi\n"
-               << "\t'rm' -f ${fromfile}\n"
-               << "fi\n";
+Converter::Converter(string const & from_file,   string const & to_file_base,
+                    string const & from_format, string const & to_format)
+       : pimpl_(new Impl(*this,
+                         from_file, to_file_base, from_format, to_format))
+{}
 
-       return command.str().c_str();
-}
 
-} // namespace anon
+Converter::~Converter()
+{}
 
+void Converter::startConversion()
+{
+       pimpl_->startConversion();
+}
 
-namespace grfx {
 
-GConverter & GConverter::get()
+bool Converter::isReachable(string const & from_format_name,
+                           string const & to_format_name)
 {
-       static GConverter singleton;
-       return singleton;
+       return converters.isReachable(from_format_name, to_format_name);
 }
 
 
-bool GConverter::isReachable(string const & from_format_name,
-                            string const & to_format_name) const
+string const & Converter::convertedFile() const
 {
-       return converters.isReachable(from_format_name, to_format_name);
+       static string const empty;
+       return pimpl_->finished_ ? pimpl_->to_file_ : empty;
 }
+} // namespace grfx
+
+//------------------------------
+// Implementation details follow
+//------------------------------
+
+namespace {
+
+/** Build the conversion script, returning true if able to build it.
+ *  The script is output to the ostringstream 'script'.
+ */
+bool build_script(string const & from_file, string const & to_file_base,
+                 string const & from_format, string const & to_format,
+                 ostringstream & script);
+
+} // namespace anon
+
 
+namespace grfx {
 
-void GConverter::convert(string const & from_file, string const & to_file_base,
-                        string const & from_format, string const & to_format,
-                        SignalTypePtr on_finish)
+Converter::Impl::Impl(Converter & p,
+                     string const & from_file,   string const & to_file_base,
+                     string const & from_format, string const & to_format)
+       : parent_(p), valid_process_(false), finished_(false)
 {
-       lyxerr[Debug::GRAPHICS] << "[GraphicsConverter::convert]\n"
-               << "\tfrom_file:    " << from_file
+       lyxerr[Debug::GRAPHICS] << "Converter c-tor:\n"
+               << "\tfrom_file:      " << from_file
                << "\n\tto_file_base: " << to_file_base
                << "\n\tfrom_format:  " << from_format
                << "\n\tto_format:    " << to_format << endl;
+
        // The conversion commands are stored in a stringstream
        ostringstream script;
        script << "#!/bin/sh\n";
-       string script_command;
-       string script_file;
-
-       bool success = build_script(from_file, to_file_base,
-                                    from_format, to_format, script);
-
-       if (success) {
-               lyxerr[Debug::GRAPHICS] << "\tConversion script:\n"
-                       << "--------------------------------------\n"
-                       << script.str().c_str() 
-                       << "\n--------------------------------------\n";
-
-               // Output the script to file.
-               static int counter = 0;
-               script_file = OnlyPath(to_file_base) + "lyxconvert" +
-                       tostr(counter++) + ".sh";
-
-               std::ofstream fs(script_file.c_str());
-               if (!fs.good()) {
-                       // Unable to output the conversion script to file.
-                       success = false;
-               } else {
-
-                       fs << script.str().c_str();
-                       fs.close();
-
-                       // Create a dummy command for ease of understanding of the
-                       // list of forked processes.
-                       // Note that 'sh ' is absolutely essential, or execvp will fail.
-                       script_command =
-                               "sh " + script_file + " " +
-                               OnlyFilename(from_file) + " " + to_format;
-               }
-       }
+       bool const success = build_script(from_file, to_file_base,
+                                         from_format, to_format, script);
 
-       string const to_file =
-               ChangeExtension(to_file_base, formats.extension(to_format));
-
-       if (!success) {
-               script_file = string();
-               script_command = 
-                       "convert -depth 8 " +
-                       from_format + ':' + from_file + ' ' +
-                       to_format + ':' + to_file;
-               lyxerr[Debug::GRAPHICS] 
-                       << "\tNo converter defined! I use convert from ImageMagic:\n\t"
-                       << script_command << endl;
-       }       
-
-       // Launch the conversion process.
-       ConvProcessPtr shared_ptr;
-       shared_ptr.reset(new ConvProcess(script_file, script_command,
-                                        to_file, on_finish));
-       all_processes_.push_back(shared_ptr);
-}
+       if (!success)
+               return;
 
+       lyxerr[Debug::GRAPHICS] << "\tConversion script:"
+                               << "\n--------------------------------------\n"
+                               << script.str().c_str() 
+                               << "\n--------------------------------------\n";
 
-namespace {
+       // Output the script to file.
+       static int counter = 0;
+       script_file_ = OnlyPath(to_file_base) + "lyxconvert" +
+                      tostr(counter++) + ".sh";
 
-typedef boost::shared_ptr<ConvProcess> ConvProcessPtr;
+       std::ofstream fs(script_file_.c_str());
+       if (!fs.good())
+               return;
 
-class Find_Ptr {
-public:
-       Find_Ptr(ConvProcess * ptr) : ptr_(ptr) {}
+       fs << script.str().c_str();
+       fs.close();
 
-       bool operator()(ConvProcessPtr const & ptr)
-       {
-               return ptr.get() == ptr_;
-       }
+       // The converted image is to be stored in this file
+       to_file_ = ChangeExtension(to_file_base, formats.extension(to_format));
 
-private:
-       ConvProcess * ptr_;
-};
+       // The command needed to run the conversion process
+       // We create a dummy command for ease of understanding of the
+       // list of forked processes.
+       // Note that 'sh ' is absolutely essential, or execvp will fail.
+       script_command_ = "sh " + script_file_ + " " +
+                         OnlyFilename(from_file) + " " + to_format;
 
-} // namespace anon
+       // All is ready to go
+       valid_process_ = true;
+}
 
 
-void GConverter::erase(ConvProcess * process)
+void Converter::Impl::startConversion()
 {
-       std::list<ConvProcessPtr>::iterator begin = all_processes_.begin();
-       std::list<ConvProcessPtr>::iterator end   = all_processes_.end();
-       std::list<ConvProcessPtr>::iterator it =
-               std::find_if(begin, end, Find_Ptr(process));
+       if (!valid_process_) {
+               converted(string(), 0, 1);
+               return;
+       }
+               
+       // Initiate the conversion
+       Forkedcall::SignalTypePtr convert_ptr;
+       convert_ptr.reset(new Forkedcall::SignalType);
+
+       convert_ptr->connect(
+               boost::bind(&Impl::converted, this, _1, _2, _3));
+
+       Forkedcall call;
+       int retval = call.startscript(script_command_, convert_ptr);
+       if (retval > 0) {
+               // Unable to even start the script, so clean-up the mess!
+               converted(string(), 0, 1);
+       }
+}
+
 
-       if (it == end)
+void Converter::Impl::converted(string const & /* cmd */,
+                               pid_t /* pid */, int retval)
+{
+       if (finished_)
+               // We're done already!
                return;
 
-       all_processes_.erase(it);
+       finished_ = true;
+       // Clean-up behind ourselves
+       lyx::unlink(script_file_);
+
+       if (retval > 0) {
+               lyx::unlink(to_file_);
+               to_file_.erase();
+               parent_.finishedConversion(false);
+       } else {
+               parent_.finishedConversion(true);
+       }
 }
 
+} // namespace grfx
+
+namespace {
+
+string const move_file(string const & from_file, string const & to_file)
+{
+       if (from_file == to_file)
+               return string();
+
+       ostringstream command;
+       command << "fromfile=" << from_file << "\n"
+               << "tofile="   << to_file << "\n\n"
+               << "'mv' -f ${fromfile} ${tofile}\n"
+               << "if [ $? -ne 0 ]; then\n"
+               << "\t'cp' -f ${fromfile} ${tofile}\n"
+               << "\tif [ $? -ne 0 ]; then\n"
+               << "\t\texit 1\n"
+               << "\tfi\n"
+               << "\t'rm' -f ${fromfile}\n"
+               << "fi\n";
+
+       return command.str().c_str();
+}
 
-bool GConverter::build_script(string const & from_file,
-                             string const & to_file_base,
-                             string const & from_format,
-                             string const & to_format,
-                             ostringstream & script) const
+bool build_script(string const & from_file,
+                 string const & to_file_base,
+                 string const & from_format,
+                 string const & to_format,
+                 ostringstream & script)
 {
-       lyxerr[Debug::GRAPHICS] << "[GraphicsConverter::build_script] ... ";
+       lyxerr[Debug::GRAPHICS] << "build_script ... ";
        typedef Converters::EdgePath EdgePath;
 
        string const to_file = ChangeExtension(to_file_base,
@@ -216,7 +274,7 @@ bool GConverter::build_script(string const & from_file,
        EdgePath::const_iterator it  = edgepath.begin();
        EdgePath::const_iterator end = edgepath.end();
        for (; it != end; ++it) {
-               Converter const & conv = converters.get(*it);
+               ::Converter const & conv = converters.get(*it);
 
                // Build the conversion command
                string const infile      = outfile;
@@ -269,44 +327,5 @@ bool GConverter::build_script(string const & from_file,
 
        return true;
 }
-
-
-ConvProcess::ConvProcess(string const & script_file,
-                        string const & script_command,
-                        string const & to_file, SignalTypePtr on_finish)
-       : script_file_(script_file), to_file_(to_file), on_finish_(on_finish)
-{
-       Forkedcall::SignalTypePtr convert_ptr;
-       convert_ptr.reset(new Forkedcall::SignalType);
-
-       convert_ptr->connect(boost::bind(&ConvProcess::converted, this, _1, _2, _3));
-
-       Forkedcall call;
-       int retval = call.startscript(script_command, convert_ptr);
-       if (retval > 0) {
-               // Unable to even start the script, so clean-up the mess!
-               converted(string(), 0, 1);
-       }
-}
-
-
-void ConvProcess::converted(string const &/* cmd */,
-                           pid_t /* pid */, int retval)
-{
-       // Clean-up behind ourselves
-       lyx::unlink(script_file_);
-
-       if (retval > 0) {
-               lyx::unlink(to_file_);
-               to_file_.erase();
-       }
-
-       if (on_finish_.get()) {
-               on_finish_->operator()(to_file_);
-       }
-
-       grfx::GConverter::get().erase(this);
-}
-
-
-} // namespace grfx
+} // namespace anon
index 3acd25998cd0ed9dd7b2e00072134724680a9de4..17ca2be966c220fc9d0fde681f2a7c8ecba3c748 100644 (file)
 // -*- C++ -*-
-/*
- * \file GraphicsConverter.h
- * Copyright 2002 the LyX Team
- * Read the file COPYING
+/**
+ *  \file GraphicsConverter.h
+ *  Copyright 2002 the LyX Team
+ *  Read the file COPYING
  *
- * \author Angus Leeming <a.leeming@ic.ac.uk>
+ *  \author Angus Leeming <a.leeming@ic.ac.uk>
  *
- * class grfx::GConverter enables graphics files to be converted asynchronously
- * to a loadable format. It does this by building a shell script of all
- * the conversion commands needed for the transformation. This script is then
- * sent to the forked calls controller for non-blocking execution. When it
- * is finished a signal is emitted, thus informing us to proceed with the
- * loading of the image.
- *
- * Ultimately, this class should be wrapped back into Dekel's converter class.
+ *  The controller of a conversion process from file AA of format A to
+ *  file BB of format B.
+ *  Once finished, the signal finishdConversion is emitted to inform the
+ *  instigator where to find file BB.
+ *  If the conversion is unsuccessful, then finishedConversion will pass
+ *  an empty string.
  */
 
 #ifndef GRAPHICSCONVERTER_H
 #define GRAPHICSCONVERTER_H
 
-#include "LString.h"
-#include "Lsstream.h"
-
-#include <boost/shared_ptr.hpp>
-#include <boost/utility.hpp>
-
-#include <boost/signals/signal1.hpp>
-#include <boost/signals/trackable.hpp>
-
-#include <list>
-
-#include <sys/types.h> // needed for pid_t
-
 #ifdef __GNUG__
 #pragma interface
 #endif
 
-namespace grfx {
+#include "LString.h"
+#include <boost/signals/signal1.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/utility.hpp>
 
-class ConvProcess;
+namespace grfx {
 
-class GConverter : boost::noncopyable {
+class Converter : boost::noncopyable {
 public:
-
-       /// This is a singleton class. Get the instance.
-       static GConverter & get();
-
        /// Can the conversion be performed?
-       bool isReachable(string const & from_format_name,
-                        string const & to_format_name) const;
+       static bool isReachable(string const & from_format_name,
+                               string const & to_format_name);
 
-       /** Convert the file and at the end return it by emitting this signal
-        *  If successful, the returned string will be the name of the
-        *  converted file (to_file_base + extension(to_format_name)).
-        *  If unsuccessful, the string will be empty.
+       /** One Converter per conversion ensures that finishedConversion
+        *  is always connected to the expected slot.
         */
-       typedef boost::signal1<void, string const &> SignalType;
-       ///
-       typedef boost::shared_ptr<SignalType> SignalTypePtr;
-       ///
-       void convert(string const & from_file,   string const & to_file_base,
-                    string const & from_format, string const & to_format,
-                    SignalTypePtr on_finish);
+       Converter(string const & from_file,   string const & to_file_base,
+                 string const & from_format, string const & to_format);
 
-private:
-       /** Make the c-tor private so we can control how many objects
-        *  are instantiated.
-        */
-       GConverter() {}
+       /// Define an empty d-tor out-of-line to keep boost::scoped_ptr happy.
+       ~Converter();
 
-       /** Build the conversion script, returning true if able to build it.
-        *  The script is output to the ostringstream 'script'.
-        */
-       bool build_script(string const & from_file, string const & to_file_base,
-                         string const & from_format, string const & to_format,
-                         ostringstream & script) const;
+       /// We are explicit about when we begin the conversion process.
+       void startConversion();
 
-       /** Remove the ConvProcess from the list of all processes.
-        *  Called by ConvProcess::converted.
+       /** At the end of the conversion process inform the outside world
+        *  by emitting a signal.
         */
-       friend class ConvProcess;
+       typedef boost::signal1<void, bool> SignalType;
        ///
-       void erase(ConvProcess *);
-
-       /// The list of all conversion processs
-       typedef boost::shared_ptr<ConvProcess> ConvProcessPtr;
-       ///
-       std::list<ConvProcessPtr> all_processes_;
-};
-
-
-/// Each ConvProcess represents a single conversion process.
-struct ConvProcess : public boost::signals::trackable
-{
-       ///
-       typedef GConverter::SignalTypePtr SignalTypePtr;
-
-       /** Each ConvProcess represents a single conversion process.
-        *  It is passed :
-        *  1. The name of the script_file, which it deletes once the
-        *     conversion is comlpeted;
-        *  2. The script command itself, which it passes on to the forked
-        *     call process;
-        *  3. The name of the output file, which it returns to the calling
-        *     process on successfull completion, by emitting
-        *  4. The signal on_finish.
+       SignalType finishedConversion;
+       
+       /** If the convsion is succesful (finishedConversion returns \c true),
+        *  this returns the name of the resulting file.
+        *  If conversion fails, however, it returns an empty string.
         */
-       ConvProcess(string const & script_file, string const & script_command,
-                   string const & to_file, SignalTypePtr on_finish);
+       string const & convertedFile() const;
 
-       /** This method is connected to a signal passed to the forked call
-        *  class, passing control back here when the conversion is completed.
-        *  Cleans-up the temporary files, emits the on_finish signal and
-        *  removes the ConvProcess from the list of all processes.
-        */
-       void converted(string const & cmd, pid_t pid, int retval);
+private:
+       /// Use the Pimpl idiom to hide the internals.
+       class Impl;
 
-       ///
-       string script_file_;
-       ///
-       string to_file_;
-       ///
-       SignalTypePtr on_finish_;
+       /// The pointer never changes although *pimpl_'s contents may.
+       boost::scoped_ptr<Impl> const pimpl_;
 };
-
 } // namespace grfx
 
 #endif // GRAPHICSCONVERTER_H
index de72597796fd8ff439330f75fea8dee71c653b7b..a87ad49a5540a48433592ee93be88d40da949bb5 100644 (file)
 
 namespace grfx {
 
-// This will be connected to a function that will return whichever
-// whichever derived class we desire.
-boost::signal0<ImagePtr> GImage::newImage;
+// This is to be connected to a function that will return a new
+// instance of a viable derived class.
+boost::signal0<Image::ImagePtr> Image::newImage;
 
 /// Return the list of loadable formats.
-boost::signal0<GImage::FormatList> GImage::loadableFormats;
+boost::signal0<Image::FormatList> Image::loadableFormats;
 
 std::pair<unsigned int, unsigned int>
-GImage::getScaledDimensions(GParams const & params) const
+Image::getScaledDimensions(Params const & params) const
 {
        if (params.scale == 0 && params.width == 0 && params.height == 0)
                // No scaling
index a9931ef7217260f8b336cdb3e8ed8593b991a160..5c9077679373d9370f190bf757f87ffca67c927c 100644 (file)
 #define GRAPHICSIMAGE_H
 
 #include "LString.h"
-#include "GraphicsTypes.h"
 
 #include <boost/shared_ptr.hpp>
-
 #include <boost/signals/signal0.hpp>
 #include <boost/signals/signal1.hpp>
 
-#include <X11/X.h>
+#include <X11/X.h> // for Pixmap :-(
 
 #include <vector>
 #include <utility>
 
 namespace grfx {
 
-class GParams;
+class Params;
 
-class GImage
-{
+class Image {
 public:
-       /// A list of supported formats.
-       typedef std::vector<string> FormatList;
-       /** This will be connected to a function that will return whichever
-        *  derived class we desire.
+       /** This is to be connected to a function that will return a new
+        *  instance of a viable derived class.
         */
+       typedef boost::shared_ptr<Image> ImagePtr;
+       ///
        static boost::signal0<ImagePtr> newImage;
 
        /// Return the list of loadable formats.
+       typedef std::vector<string> FormatList;
+       ///
        static boost::signal0<FormatList> loadableFormats;
 
+       /// Must define default c-tor explicitly as we define a copy c-tor.
+       Image() {}
+       /// Don't copy the signal finishedLoading
+       Image(Image const &) {}
        ///
-       virtual ~GImage() {}
+       virtual ~Image() {}
 
        /// Create a copy
-       virtual GImage * clone() const = 0;
+       virtual Image * clone() const = 0;
 
        ///
        virtual Pixmap getPixmap() const = 0;
@@ -71,37 +74,41 @@ public:
        /// Get the image height
        virtual unsigned int getHeight() const = 0;
 
-       /** At the end of the loading or modification process, return the new
-        *  image by emitting this signal */
+       /** At the end of the loading process inform the outside world
+        *  by emitting a signal.
+        */
        typedef boost::signal1<void, bool> SignalType;
        ///
-       typedef boost::shared_ptr<SignalType> SignalTypePtr;
+       SignalType finishedLoading;
 
-       /// Start loading the image file.
-       virtual void load(string const & filename, SignalTypePtr) = 0;
+       /** Start loading the image file.
+        *  The caller should expect this process to be asynchronous and
+        *  so should connect to the "finished" signal above.
+        */
+       virtual void load(string const & filename) = 0;
 
        /** Generate the pixmap.
         *  Uses the params to decide on color, grayscale etc.
         *  Returns true if the pixmap is created.
         */
-       virtual bool setPixmap(GParams const & params) = 0;
+       virtual bool setPixmap(Params const & params) = 0;
 
        /// Clip the image using params.
-       virtual void clip(GParams const & params) = 0;
+       virtual void clip(Params const & params) = 0;
 
        /// Rotate the image using params.
-       virtual void rotate(GParams const & params) = 0;
+       virtual void rotate(Params const & params) = 0;
 
        /// Scale the image using params.
-       virtual void scale(GParams const & params) = 0;
+       virtual void scale(Params const & params) = 0;
 
 protected:
        /** Uses the params to ascertain the dimensions of the scaled image.
         *  Returned as make_pair(width, height).
-        *  If something geso wrong, returns make_pair(getWidth(), getHeight())
+        *  If something goes wrong, returns make_pair(getWidth(), getHeight())
         */
        std::pair<unsigned int, unsigned int>
-       getScaledDimensions(GParams const & params) const;
+       getScaledDimensions(Params const & params) const;
 };
 
 } // namespace grfx
index 7332be23a8f4134261dfb883d6e7c083bbc2a2fe..9bdef0b368616ebf5d2212a120911b40052a453e 100644 (file)
@@ -37,16 +37,16 @@ using std::strlen;
 namespace grfx {
 
 /// Access to this class is through this static method.
-ImagePtr GImageXPM::newImage()
+Image::ImagePtr ImageXPM::newImage()
 {
        ImagePtr ptr;
-       ptr.reset(new GImageXPM);
+       ptr.reset(new ImageXPM);
        return ptr;
 }
 
 
 /// Return the list of loadable formats.
-GImage::FormatList GImageXPM::loadableFormats()
+Image::FormatList ImageXPM::loadableFormats()
 {
        FormatList formats(1);
        formats[0] = "xpm";
@@ -54,46 +54,46 @@ GImage::FormatList GImageXPM::loadableFormats()
 }
 
 
-GImageXPM::GImageXPM()
+ImageXPM::ImageXPM()
        : pixmap_(0),
          pixmap_status_(PIXMAP_UNINITIALISED)
 {}
 
 
-GImageXPM::GImageXPM(GImageXPM const & other)
-       : GImage(other),
+ImageXPM::ImageXPM(ImageXPM const & other)
+       : Image(other),
          image_(other.image_),
          pixmap_(0),
          pixmap_status_(PIXMAP_UNINITIALISED)
 {}
 
 
-GImageXPM::~GImageXPM()
+ImageXPM::~ImageXPM()
 {
        if (pixmap_)
                XFreePixmap(fl_get_display(), pixmap_);
 }
 
 
-GImage * GImageXPM::clone() const
+Image * ImageXPM::clone() const
 {
-       return new GImageXPM(*this);
+       return new ImageXPM(*this);
 }
 
 
-unsigned int GImageXPM::getWidth() const
+unsigned int ImageXPM::getWidth() const
 {
        return image_.width();
 }
 
 
-unsigned int GImageXPM::getHeight() const
+unsigned int ImageXPM::getHeight() const
 {
        return image_.height();
 }
 
 
-Pixmap GImageXPM::getPixmap() const
+Pixmap ImageXPM::getPixmap() const
 {
        if (!pixmap_status_ == PIXMAP_SUCCESS)
                return 0;
@@ -101,17 +101,17 @@ Pixmap GImageXPM::getPixmap() const
 }
 
 
-void GImageXPM::load(string const & filename, GImage::SignalTypePtr on_finish)
+void ImageXPM::load(string const & filename)
 {
        if (filename.empty()) {
-               on_finish->operator()(false);
+               finishedLoading(false);
                return;
        }
 
        if (!image_.empty()) {
                lyxerr[Debug::GRAPHICS]
                        << "Image is loaded already!" << std::endl;
-               on_finish->operator()(false);
+               finishedLoading(false);
                return;
        }
 
@@ -151,11 +151,11 @@ void GImageXPM::load(string const & filename, GImage::SignalTypePtr on_finish)
                image_.reset(*xpm_image);
        }
 
-       on_finish->operator()(success == XpmSuccess);
+       finishedLoading(success == XpmSuccess);
 }
 
 
-bool GImageXPM::setPixmap(GParams const & params)
+bool ImageXPM::setPixmap(Params const & params)
 {
        if (image_.empty() || params.display == NoDisplay) {
                return false;
@@ -235,7 +235,7 @@ bool GImageXPM::setPixmap(GParams const & params)
 }
 
 
-void GImageXPM::clip(GParams const & params)
+void ImageXPM::clip(Params const & params)
 {
        if (image_.empty())
                return;
@@ -279,7 +279,7 @@ void GImageXPM::clip(GParams const & params)
 }
 
 
-void GImageXPM::rotate(GParams const & params)
+void ImageXPM::rotate(Params const & params)
 {
        if (image_.empty())
                return ;
@@ -349,7 +349,7 @@ void GImageXPM::rotate(GParams const & params)
 }
 
 
-void GImageXPM::scale(GParams const & params)
+void ImageXPM::scale(Params const & params)
 {
        if (image_.empty())
                return;
@@ -419,19 +419,19 @@ void mapcolor(char const * c_color, char ** g_color_ptr, char ** m_color_ptr);
 
 namespace grfx {
 
-GImageXPM::Data::Data()
+ImageXPM::Data::Data()
        : width_(0), height_(0), cpp_(0), ncolors_(0)
 {}
 
 
-GImageXPM::Data::~Data()
+ImageXPM::Data::~Data()
 {
        if (colorTable_.unique())
                free_color_table(colorTable_.get(), ncolors_);
 }
 
 
-void GImageXPM::Data::reset(XpmImage & image)
+void ImageXPM::Data::reset(XpmImage & image)
 {
        width_ = image.width;
        height_ = image.height;
@@ -511,7 +511,7 @@ void GImageXPM::Data::reset(XpmImage & image)
 }
 
 
-XpmImage GImageXPM::Data::get() const
+XpmImage ImageXPM::Data::get() const
 {
        XpmImage image;
        image.width = width_;
@@ -524,7 +524,7 @@ XpmImage GImageXPM::Data::get() const
 }
 
 
-void GImageXPM::Data::resetData(int w, int h, unsigned int * d)
+void ImageXPM::Data::resetData(int w, int h, unsigned int * d)
 {
        width_  = w;
        height_ = h;
@@ -532,7 +532,7 @@ void GImageXPM::Data::resetData(int w, int h, unsigned int * d)
 }
 
 
-unsigned int * GImageXPM::Data::initialisedData(int w, int h) const
+unsigned int * ImageXPM::Data::initialisedData(int w, int h) const
 {
        size_t const data_size = w * h;
 
@@ -546,7 +546,7 @@ unsigned int * GImageXPM::Data::initialisedData(int w, int h) const
 }
 
 
-unsigned int GImageXPM::Data::color_none_id() const
+unsigned int ImageXPM::Data::color_none_id() const
 {
        XpmColor * table = colorTable_.get();
        for (size_t i = 0; i < ncolors_; ++i) {
index 4d3c88638bb9ef5dca631ab1b056144db1512d08..ce4eccbcd6b7ab098624b1d8dc38377ac6dc878b 100644 (file)
@@ -7,7 +7,7 @@
  *  \author Baruch Even <baruch.even@writeme.com>
  *  \author Angus Leeming <a.leeming@ic.ac.uk>
  *
- *  An instantiation of GImage that makes use of libXPM to load and store
+ *  An instantiation of Image that makes use of libXPM to load and store
  *  the image in memory.
  */
 
@@ -24,7 +24,7 @@
 
 namespace grfx {
 
-class GImageXPM : public GImage
+class ImageXPM : public Image
 {
 public:
        /// Access to this class is through this static method.
@@ -34,10 +34,10 @@ public:
        static FormatList loadableFormats();
 
        ///
-       ~GImageXPM();
+       ~ImageXPM();
 
        /// Create a copy
-       GImage * clone() const;
+       Image * clone() const;
 
        ///
        Pixmap getPixmap() const;
@@ -49,31 +49,31 @@ public:
        unsigned int getHeight() const;
 
        /** Load the image file into memory.
-        *  In this case (GImageXPM), the process is blocking.
+        *  In this case (ImageXPM), the process is blocking.
         */
-       void load(string const & filename, SignalTypePtr);
+       void load(string const & filename);
 
        /** Generate the pixmap, based on the current state of the
         *  xpm_image_ (clipped, rotated, scaled etc).
         *  Uses the params to decide on color, grayscale etc.
         *  Returns true if the pixmap is created.
         */
-       bool setPixmap(GParams const & params);
+       bool setPixmap(Params const & params);
 
        /// Clip the image using params.
-       void clip(GParams const & params);
+       void clip(Params const & params);
 
        /// Rotate the image using params.
-       void rotate(GParams const & params);
+       void rotate(Params const & params);
 
        /// Scale the image using params.
-       void scale(GParams const & params);
+       void scale(Params const & params);
 
 private:
        /// Access to the class is through newImage() and clone.
-       GImageXPM();
+       ImageXPM();
        ///
-       GImageXPM(GImageXPM const &);
+       ImageXPM(ImageXPM const &);
 
        /** Contains the data read from file.
         *  This class is a wrapper for a XpmImage struct, but all views
index d0c582ce06f2e5b49f407fbe8983b570416d198f..9464960690d1dc5a3e417065bbcd87ba675a3390 100644 (file)
 #include "GraphicsParams.h"
 
 #include <boost/bind.hpp>
+#include <boost/signals/trackable.hpp>
 
 namespace grfx {
 
-struct Loader::Impl {
+struct Loader::Impl : boost::signals::trackable {
        ///
-       Impl(Loader &, GParams const &);
+       Impl(Loader &, Params const &);
        ///
        ~Impl();
        ///
-       void setFile(string const & file);
+       void resetFile(string const &);
        ///
-       void unsetOldFile();
+       void resetParams(Params const &);
        ///
        void createPixmap();
-       ///
-       void statusChanged();
 
-       ///
-       Loader & parent_;
        /// The loading status of the image.
        ImageStatus status_;
        /** Must store a copy of the cached item to ensure that it is not
         *  erased unexpectedly by the cache itself.
         */
-       GraphicPtr graphic_;
-       ///
-       GParams params_;
+       Cache::ItemPtr cached_item_;
        /// We modify a local copy of the image once it is loaded.
-       ImagePtr image_;
+       Image::ImagePtr image_;
+
+private:
+       ///
+       void statusChanged();
+       
+       ///
+       Params params_;
+       ///
+       Loader & parent_;
 };
 
 
-Loader::Impl::Impl(Loader & parent, GParams const & params)
-       : parent_(parent), status_(WaitingToLoad), params_(params)
+Loader::Impl::Impl(Loader & parent, Params const & params)
+       : status_(WaitingToLoad), params_(params), parent_(parent)
 {}
 
 
 Loader::Impl::~Impl()
 {
-       unsetOldFile();
+       resetFile(string());
 }
 
 
-void Loader::Impl::setFile(string const & file)
+void Loader::Impl::resetFile(string const & file)
 {
-       if (file.empty())
+       string const old_file = cached_item_.get() ?
+               cached_item_->filename() : string();
+
+       if (file == old_file)
                return;
 
-       GCache & gc = GCache::get();
+       if (!old_file.empty()) {
+               cached_item_.reset();
+               Cache::get().remove(old_file);
+       }
+
+       status_ = cached_item_.get() ? cached_item_->status() : WaitingToLoad;
+       image_.reset();
+       
+       if (cached_item_.get() || file.empty())
+               return;
+
+       Cache & gc = Cache::get();
        if (!gc.inCache(file))
                gc.add(file);
 
        // We /must/ make a local copy of this.
-       graphic_ = gc.graphic(file);
-       status_ = graphic_->status();
-
-       if (status_ == Loaded) {
-               createPixmap();
-       }
+       cached_item_ = gc.item(file);
+       status_ = cached_item_->status();
 
-       // It's easiest to do this without checking
-       parent_.statusChanged();
+       cached_item_->statusChanged.connect(
+               boost::bind(&Impl::statusChanged, this));
 }
 
 
-void Loader::Impl::unsetOldFile()
+void Loader::Impl::resetParams(Params const & params)
 {
-       if (!graphic_.get())
+       if (params == params_)
                return;
 
-       string const old_file = graphic_->filename();
-       graphic_.reset();
-       GCache::get().remove(old_file);
-
-       status_ = WaitingToLoad;
-       params_ = GParams();
+       params_ = params;
+       status_ = cached_item_.get() ? cached_item_->status() : WaitingToLoad;
        image_.reset();
 }
 
 
 void Loader::Impl::statusChanged()
 {
-       status_ = graphic_->status();
-       if (status_ == Loaded)
-               createPixmap();
-
+       status_ = cached_item_.get() ? cached_item_->status() : WaitingToLoad;
+       createPixmap();
        parent_.statusChanged();
 }
 
 
 void Loader::Impl::createPixmap()
 {
-       if (!graphic_.get() || image_.get() ||
+       if (!cached_item_.get() || image_.get() ||
            params_.display == NoDisplay || status_ != Loaded)
                return;
 
-       image_.reset(graphic_->image()->clone());
+       image_.reset(cached_item_->image()->clone());
 
        // These do nothing if there's nothing to do
        image_->clip(params_);
@@ -134,22 +142,21 @@ void Loader::Impl::createPixmap()
 
 
 Loader::Loader()
-       : pimpl_(new Impl(*this, GParams()))
+       : pimpl_(new Impl(*this, Params()))
 {}
 
 
 Loader::Loader(string const & file, DisplayType type)
-       : pimpl_(new Impl(*this, GParams()))
+       : pimpl_(new Impl(*this, Params()))
 {
-       pimpl_->params_.display = type;
-       pimpl_->setFile(file);
+       reset(file, type);
 }
 
 
-Loader::Loader(string const & file, GParams const & params)
+Loader::Loader(string const & file, Params const & params)
        : pimpl_(new Impl(*this, params))
 {
-       pimpl_->setFile(file);
+       reset(file, params);
 }
 
 
@@ -159,48 +166,43 @@ Loader::~Loader()
 
 void Loader::reset(string const & file, DisplayType type)
 {
-       pimpl_->unsetOldFile();
+       Params params;
+       params.display = type;
+       pimpl_->resetParams(params);
 
-       pimpl_->params_ = GParams();
-       pimpl_->params_.display = type;
-       pimpl_->setFile(file);
+       pimpl_->resetFile(file);
+       pimpl_->createPixmap();
 }
 
 
-void Loader::reset(string const & file, GParams const & params)
+void Loader::reset(string const & file, Params const & params)
 {
-       pimpl_->unsetOldFile();
-
-       pimpl_->params_ = params;
-       pimpl_->setFile(file);
+       pimpl_->resetParams(params);
+       pimpl_->resetFile(file);
+       pimpl_->createPixmap();
 }
 
 
-void Loader::reset(GParams const & params)
+void Loader::reset(Params const & params)
 {
-       pimpl_->params_ = params;
-
-       if (pimpl_->status_ == Loaded)
-               pimpl_->createPixmap();
+       pimpl_->resetParams(params);
+       pimpl_->createPixmap();
 }
 
 
 void Loader::startLoading()
 {
-       if (pimpl_->status_ != WaitingToLoad || !pimpl_->graphic_.get())
+       if (pimpl_->status_ != WaitingToLoad || !pimpl_->cached_item_.get())
                return;
-
-       pimpl_->graphic_->statusChanged.connect(
-               boost::bind(&Loader::Impl::statusChanged,
-                           pimpl_.get()));
-       pimpl_->graphic_->startLoading();
+       pimpl_->cached_item_->startLoading();
 }
 
 
 string const & Loader::filename() const
 {
        static string const empty;
-       return pimpl_->graphic_.get() ? pimpl_->graphic_->filename() : empty;
+       return pimpl_->cached_item_.get() ?
+               pimpl_->cached_item_->filename() : empty;
 }
 
 
@@ -210,7 +212,7 @@ ImageStatus Loader::status() const
 }
 
 
-GImage const * Loader::image() const
+Image const * Loader::image() const
 {
        return pimpl_->image_.get();
 }
index 8cb1408bf96e0b156a77a88c6379b91b7bfb3420..b20d5af914ae1885746988576102430c79d23a95 100644 (file)
@@ -6,7 +6,8 @@
  *
  *  \author Angus Leeming <leeming@lyx.org>
  *
- *  The public view of the graphics cache.
+ *  The public face of the graphics cache.
+ *
  *  * The user supplies an image file and the display parameters.
  *  * He can change the file or the display parameters through a reset() method.
  *  * He must start the loading process explicitly with startLoading().
 
 namespace grfx {
 
-class GParams;
+class Image;
+class Params;
 
-/** One image, one instance of grfx::Loader, although the image can be
- *  changed.
- */
 class Loader {
 public:
        /// Must use the reset methods to make this instance usable.
@@ -44,7 +43,7 @@ public:
        /// The image is not transformed, just displayed as-is.
        Loader(string const & file_with_path, DisplayType = ColorDisplay);
        /// The image is transformed before display.
-       Loader(string const & file_with_path, GParams const &);
+       Loader(string const & file_with_path, Params const &);
 
        /// Define an empty d-tor out-of-line to keep boost::scoped_ptr happy.
        ~Loader();
@@ -52,9 +51,9 @@ public:
        /// The file can be changed, or the display params, or both.
        void reset(string const & file_with_path, DisplayType = ColorDisplay);
        ///
-       void reset(string const & file_with_path, GParams const &);
+       void reset(string const & file_with_path, Params const &);
        ///
-       void reset(GParams const &);
+       void reset(Params const &);
 
        /// Returns the absolute path of the loaded (loading?) file.
        string const & filename() const;
@@ -73,7 +72,7 @@ public:
        /** The loaded image with Pixmap set.
         *  If the Pixmap is not yet set (see status() for why...), returns 0.
         */
-       GImage const * image() const;
+       Image const * image() const;
 
 private:
        /// Use the Pimpl idiom to hide the internals.
index 1f7dfc9d5e4b7cd78d1cc2599368b52bb3f70861..a952895e93cde7900fe58375d930f48a5e25e3b2 100644 (file)
@@ -19,7 +19,7 @@
 
 namespace grfx {
 
-GParams::GParams()
+Params::Params()
        : display(ColorDisplay),
          width(0),
          height(0),
@@ -28,7 +28,7 @@ GParams::GParams()
 {}
 
 
-bool operator==(GParams const & a, GParams const & b)
+bool operator==(Params const & a, Params const & b)
 {
        return (a.filename == b.filename &&
                a.display  == b.display &&
@@ -40,7 +40,7 @@ bool operator==(GParams const & a, GParams const & b)
 }
 
 
-bool operator!=(GParams const & a, GParams const & b)
+bool operator!=(Params const & a, Params const & b)
 {
        return !(a == b);
 }
index 0517ee21cd1f2cb7e96f705a8ae861a4d5bc0bef..d25d5de543caa8edd65667c5a40b8a28cdc5311c 100644 (file)
@@ -43,9 +43,9 @@ struct BoundingBox {
 bool operator==(BoundingBox const &, BoundingBox const &);
 bool operator!=(BoundingBox const &, BoundingBox const &);
 
-struct GParams
+struct Params
 {
-       GParams();
+       Params();
 
        DisplayType display;
 
@@ -69,8 +69,8 @@ struct GParams
        int angle;
 };
 
-bool operator==(GParams const &, GParams const &);
-bool operator!=(GParams const &, GParams const &);
+bool operator==(Params const &, Params const &);
+bool operator!=(Params const &, Params const &);
 
 } // namespace grfx
 
index 18db9210b1f899e6041d6129f5ab47dc9ff7e1c0..fbfcbbcf11205bec3e3ccc0c79eb526ec180ed57 100644 (file)
@@ -7,30 +7,18 @@
  *  \author Angus Leeming <a.leeming@ic.ac.uk>
  *
  *  All that header files outside the graphics subdirectory should need to
- *  access. That just leaves insetgraphics.C to access GraphicsCache.h.
- *  It also makes life easier for files inside the graphics subdirectory!
+ *  access.
  */
 
 #ifndef GRAPHICSTYPES_H
 #define GRAPHICSTYPES_H
 
-#include <boost/shared_ptr.hpp>
-
 #ifdef __GNUG__
 #pragma interface
 #endif
 
 namespace grfx {
 
-       ///
-       class GImage;
-       ///
-       typedef boost::shared_ptr<GImage> ImagePtr;
-       ///
-       class GCacheItem;
-       /// The cache contains data of this type.
-       typedef boost::shared_ptr<GCacheItem> GraphicPtr;
-
        /// The status of the loading process
        enum ImageStatus {
                /** The data is in the cache, but no request to display it
index fe4f2da56d6d5c01b7c5b3920aa31872f49b9466..c9f5ee0a4f0a31193c38bd182842fa6732911c07 100644 (file)
@@ -1,3 +1,10 @@
+2002-06-28  Angus Leeming  <leeming@lyx.org>
+
+       * insetgraphicsParams.[Ch]: forward declare grfx::Params.
+       rename asGParams -> as_grfxParams.
+
+       * insetgraphics.C: reflect above change.
+
 2002-06-26  Angus Leeming  <leeming@lyx.org>
 
        * insetgraphics.h: use boost::scoped_ptr in preference to
index dccbbe27a2cd5cbd420683369feedfe38642c701..364fb9fa97505c3ddc5cf456a64792e4f718add1 100644 (file)
@@ -80,6 +80,7 @@ TODO Before initial production release:
 
 #include "graphics/GraphicsLoader.h"
 #include "graphics/GraphicsImage.h"
+#include "graphics/GraphicsParams.h"
 
 #include "frontends/LyXView.h"
 #include "lyxtext.h"
@@ -181,7 +182,7 @@ void InsetGraphics::Cache::update(string const & file_with_path)
        lyx::Assert(!file_with_path.empty());
 
        string const path = OnlyPath(file_with_path);
-       loader.reset(file_with_path, parent_.params().asGParams(path));
+       loader.reset(file_with_path, parent_.params().as_grfxParams(path));
 }
 
 
index fa5117d25547429372116b9bea798aec5711adaa..13952b2bd78dfcdeb33e881f01a51c2e170767c6 100644 (file)
@@ -18,6 +18,8 @@
 
 #include "insetgraphicsParams.h"
 
+#include "graphics/GraphicsParams.h"
+
 #include "support/translator.h"
 #include "support/filetools.h"
 #include "support/lyxlib.h"
@@ -307,9 +309,9 @@ bool InsetGraphicsParams::Read(LyXLex & lex, string const & token)
 }
 
 
-grfx::GParams InsetGraphicsParams::asGParams(string const & filepath) const
+grfx::Params InsetGraphicsParams::as_grfxParams(string const & filepath) const
 {
-       grfx::GParams pars;
+       grfx::Params pars;
        pars.width    = 0;
        pars.height   = 0;
        pars.scale    = 0;
index c7a3b9de787834e45d96ad11bf9a38bc50ecc818..1591b5980b809f452274a245e4713dd7ef8a8f1f 100644 (file)
@@ -22,8 +22,9 @@
 #include "buffer.h"
 #include "lyxlex.h"
 
-#include "graphics/GraphicsParams.h"
-
+namespace grfx {
+       class Params;
+}
 
 /// This struct holds all the parameters needed by insetGraphics.
 struct InsetGraphicsParams
@@ -98,7 +99,7 @@ struct InsetGraphicsParams
   // Only a subset of InsetGraphicsParams is needed for display purposes.
   // This function also interrogates lyxrc to ascertain whether
   // to display or not.
-       grfx::GParams asGParams(string const & filepath) const;
+       grfx::Params as_grfxParams(string const & filepath) const;
 
 private:
        /// Initialize the object to a default status.
index 83599121ee99fbb5c4ca44eaf1fbf7af66c8143b..b6b3c4cc09cd3375951aa39f552dffbce282ea5d 100644 (file)
@@ -1,3 +1,6 @@
+2002-06-28  Angus Leeming  <leeming@lyx.org>
+
+       * preview.h (preview): don't pass grfx::GraphicPtr & anymore.
 
 2002-06-24  André Pönitz <poenitz@gmx.net>
 
index 5ba7fd7fd0894f7af14fdd5b26a5af5ba011ab56..9ce6b42217dbd35dd3b0bdc7907ef58e063c67f5 100644 (file)
@@ -2,8 +2,7 @@
 #define PREVIEW_H
 
 #include "LString.h"
-#include "graphics/GraphicsTypes.h"
 
-bool preview(string const & str, grfx::GraphicPtr & graphic);
+bool preview(string const & str);
 
 #endif