+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.
class LyXFont;
namespace grfx {
- class GImage;
+ class Image;
}
/**
/// 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,
+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
#include "lyxrc.h"
#include "graphics/GraphicsCache.h"
-#include "graphics/GraphicsConverter.h"
+#include "graphics/GraphicsCacheItem.h"
#include "graphics/GraphicsImage.h"
#include "insets/insetgraphics.h"
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));
+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
Painter & QLPainter::image(int , int ,
int , int ,
- grfx::GImage const & )
+ grfx::Image const & )
{
#if 0 // FIXME
XGCValues val;
/// 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,
/// 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_; }
///
// 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();
+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
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.
xforms_helpers.h \
xforms_resize.C \
xforms_resize.h \
- $(XFORMSGIMAGE) xformsBC.C \
+ $(XFORMSIMAGE) xformsBC.C \
xformsBC.h \
xscreen.C \
xscreen.h \
Painter & XPainter::image(int x, int y,
int w, int h,
- grfx::GImage const & image)
+ grfx::Image const & image)
{
XGCValues val;
val.function = GXcopy;
/// 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,
#include "ColorHandler.h"
#include "xforms_helpers.h"
#ifdef USE_XFORMS_IMAGE_LOADER
-#include "xformsGImage.h"
+#include "xformsImage.h"
#else
#include "graphics/GraphicsImageXPM.h"
#endif
#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
}
+++ /dev/null
-/*
- * \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
+++ /dev/null
-// -*- 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
--- /dev/null
+/*
+ * \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
--- /dev/null
+// -*- 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
+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
#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) {
}
// 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
* \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
/// 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.
*
* 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
#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);
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;
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)
}
// 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;
}
} // anon namespace
-void GCacheItem::convertToDisplayFormat()
+namespace grfx {
+
+void CacheItem::Impl::convertToDisplayFormat()
{
setStatus(Converting);
// Make a local copy in case we unzip it
} 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!
// 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
* \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
-/*
- * \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,
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;
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
// -*- 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
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
#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;
/// 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
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";
}
-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;
}
-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;
}
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;
}
-void GImageXPM::clip(GParams const & params)
+void ImageXPM::clip(Params const & params)
{
if (image_.empty())
return;
}
-void GImageXPM::rotate(GParams const & params)
+void ImageXPM::rotate(Params const & params)
{
if (image_.empty())
return ;
}
-void GImageXPM::scale(GParams const & params)
+void ImageXPM::scale(Params const & params)
{
if (image_.empty())
return;
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;
}
-XpmImage GImageXPM::Data::get() const
+XpmImage ImageXPM::Data::get() const
{
XpmImage image;
image.width = width_;
}
-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;
}
-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;
}
-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) {
* \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.
*/
namespace grfx {
-class GImageXPM : public GImage
+class ImageXPM : public Image
{
public:
/// Access to this class is through this static method.
static FormatList loadableFormats();
///
- ~GImageXPM();
+ ~ImageXPM();
/// Create a copy
- GImage * clone() const;
+ Image * clone() const;
///
Pixmap getPixmap() const;
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
#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_);
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);
}
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;
}
}
-GImage const * Loader::image() const
+Image const * Loader::image() const
{
return pimpl_->image_.get();
}
*
* \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.
/// 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();
/// 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;
/** 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.
namespace grfx {
-GParams::GParams()
+Params::Params()
: display(ColorDisplay),
width(0),
height(0),
{}
-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 &&
}
-bool operator!=(GParams const & a, GParams const & b)
+bool operator!=(Params const & a, Params const & b)
{
return !(a == b);
}
bool operator==(BoundingBox const &, BoundingBox const &);
bool operator!=(BoundingBox const &, BoundingBox const &);
-struct GParams
+struct Params
{
- GParams();
+ Params();
DisplayType display;
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
* \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
+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
#include "graphics/GraphicsLoader.h"
#include "graphics/GraphicsImage.h"
+#include "graphics/GraphicsParams.h"
#include "frontends/LyXView.h"
#include "lyxtext.h"
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));
}
#include "insetgraphicsParams.h"
+#include "graphics/GraphicsParams.h"
+
#include "support/translator.h"
#include "support/filetools.h"
#include "support/lyxlib.h"
}
-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;
#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
// 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.
+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>
#define PREVIEW_H
#include "LString.h"
-#include "graphics/GraphicsTypes.h"
-bool preview(string const & str, grfx::GraphicPtr & graphic);
+bool preview(string const & str);
#endif