+2002-07-12 Angus Leeming <leeming@lyx.org>
+
+ * GraphicsLoader.[Ch]: smart loading of images. Images are loaded only
+ if visible 2 secs after the call to load them is first made.
+
+ * GraphicsSupport.[Ch]: new files. isInsetVisible interrogates the
+ BufferView to ascertain whether the inset is visible or not.
+
+ * Makefile.am: added GraphicsSupport.[Ch].
+
+ * PreviewImage.[Ch]: use this smart loader.
+
+ * PreviewLoader.C: don't load generated image files indiscimminantly.
+ Instead emit the imageReady signal and allow the image owner to decide.
+
2002-07-12 John Levon <moz@compsoc.man.ac.uk>
* GraphicsCache.C: remove init_graphics()
#include "GraphicsCacheItem.h"
#include "GraphicsImage.h"
#include "GraphicsParams.h"
+#include "GraphicsSupport.h"
+
+#include "frontends/Timeout.h"
#include <boost/bind.hpp>
#include <boost/signals/trackable.hpp>
+#include <list>
+
namespace grfx {
struct Loader::Impl : boost::signals::trackable {
///
void createPixmap();
+ ///
+ void startLoading(Inset const &, BufferView const &);
+
/// The loading status of the image.
ImageStatus status_;
/** Must store a copy of the cached item to ensure that it is not
private:
///
void statusChanged();
+ ///
+ void checkedLoading();
///
Params params_;
///
Loader & parent_;
+
+ ///
+ Timeout timer;
+ // Multiple Insets can share the same image
+ typedef std::list<Inset const *> InsetList;
+ ///
+ InsetList insets;
+ ///
+ BufferView const * view;
};
-Loader::Impl::Impl(Loader & parent, Params const & params)
- : status_(WaitingToLoad), params_(params), parent_(parent)
+Loader::Loader()
+ : pimpl_(new Impl(*this, Params()))
{}
+Loader::Loader(string const & file, DisplayType type)
+ : pimpl_(new Impl(*this, Params()))
+{
+ reset(file, type);
+}
+
+
+Loader::Loader(string const & file, Params const & params)
+ : pimpl_(new Impl(*this, params))
+{
+ reset(file, params);
+}
+
+
+Loader::~Loader()
+{}
+
+
+void Loader::reset(string const & file, DisplayType type)
+{
+ Params params;
+ params.display = type;
+ pimpl_->resetParams(params);
+
+ pimpl_->resetFile(file);
+ pimpl_->createPixmap();
+}
+
+
+void Loader::reset(string const & file, Params const & params)
+{
+ pimpl_->resetParams(params);
+ pimpl_->resetFile(file);
+ pimpl_->createPixmap();
+}
+
+
+void Loader::reset(Params const & params)
+{
+ pimpl_->resetParams(params);
+ pimpl_->createPixmap();
+}
+
+
+void Loader::startLoading()
+{
+ if (pimpl_->status_ != WaitingToLoad || !pimpl_->cached_item_.get())
+ return;
+ pimpl_->cached_item_->startLoading();
+}
+
+
+void Loader::startLoading(Inset const & inset, BufferView const & bv)
+{
+ if (pimpl_->status_ != WaitingToLoad || !pimpl_->cached_item_.get())
+ return;
+ pimpl_->startLoading(inset, bv);
+}
+
+
+string const & Loader::filename() const
+{
+ static string const empty;
+ return pimpl_->cached_item_.get() ?
+ pimpl_->cached_item_->filename() : empty;
+}
+
+
+ImageStatus Loader::status() const
+{
+ return pimpl_->status_;
+}
+
+
+Image const * Loader::image() const
+{
+ return pimpl_->image_.get();
+}
+
+
+Loader::Impl::Impl(Loader & parent, Params const & params)
+ : status_(WaitingToLoad), params_(params), parent_(parent),
+ timer(2000, Timeout::ONETIME), view(0)
+{
+ timer.timeout.connect(boost::bind(&Impl::checkedLoading, this));
+}
+
+
Loader::Impl::~Impl()
{
resetFile(string());
}
-Loader::Loader()
- : pimpl_(new Impl(*this, Params()))
-{}
-
-
-Loader::Loader(string const & file, DisplayType type)
- : pimpl_(new Impl(*this, Params()))
+void Loader::Impl::startLoading(Inset const & inset, BufferView const & bv)
{
- reset(file, type);
-}
+ if (status_ != WaitingToLoad || timer.running())
+ return;
+ InsetList::const_iterator it = insets.begin();
+ InsetList::const_iterator end = insets.end();
+ it = std::find(it, end, &inset);
+ if (it == end)
+ insets.push_back(&inset);
+ view = &bv;
-Loader::Loader(string const & file, Params const & params)
- : pimpl_(new Impl(*this, params))
-{
- reset(file, params);
+ timer.start();
}
-Loader::~Loader()
-{}
+namespace {
+struct FindVisibleInset {
-void Loader::reset(string const & file, DisplayType type)
-{
- Params params;
- params.display = type;
- pimpl_->resetParams(params);
-
- pimpl_->resetFile(file);
- pimpl_->createPixmap();
-}
-
-
-void Loader::reset(string const & file, Params const & params)
-{
- pimpl_->resetParams(params);
- pimpl_->resetFile(file);
- pimpl_->createPixmap();
-}
+ FindVisibleInset(std::list<VisibleParagraph> const & vps) : vps_(vps) {}
+ bool operator()(Inset const * inset_ptr)
+ {
+ if (!inset_ptr)
+ return false;
+ return isInsetVisible(*inset_ptr, vps_);
+ }
+
+private:
+ std::list<VisibleParagraph> const & vps_;
+};
-void Loader::reset(Params const & params)
-{
- pimpl_->resetParams(params);
- pimpl_->createPixmap();
-}
+} // namespace anon
-void Loader::startLoading()
+void Loader::Impl::checkedLoading()
{
- if (pimpl_->status_ != WaitingToLoad || !pimpl_->cached_item_.get())
+ if (insets.empty() || !view)
return;
- pimpl_->cached_item_->startLoading();
-}
+ std::list<VisibleParagraph> const vps = getVisibleParagraphs(*view);
-string const & Loader::filename() const
-{
- static string const empty;
- return pimpl_->cached_item_.get() ?
- pimpl_->cached_item_->filename() : empty;
-}
+ InsetList::const_iterator it = insets.begin();
+ InsetList::const_iterator end = insets.end();
+ it = std::find_if(it, end, FindVisibleInset(vps));
-ImageStatus Loader::status() const
-{
- return pimpl_->status_;
+ // One of the insets is visible, so start loading the image.
+ if (it != end)
+ cached_item_->startLoading();
}
-Image const * Loader::image() const
-{
- return pimpl_->image_.get();
-}
-
} // namespace grfx
#include <boost/signals/signal0.hpp>
#include <boost/scoped_ptr.hpp>
+class Inset;
+class BufferView;
+
namespace grfx {
class Image;
/// We are explicit about when we begin the loading process.
void startLoading();
+ /** starting loading of the image is conditional upon the
+ * inset being visible or not.
+ */
+ void startLoading(Inset const &, BufferView const &);
+
/// How far have we got in loading the image?
ImageStatus status() const;
--- /dev/null
+/**
+ * \file GraphicsSupport.C
+ * Copyright 2002 the LyX Team
+ * Read the file COPYING
+ *
+ * \author Angus Leeming <leeming@lyx.org>
+ */
+
+#include <config.h>
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+
+#include "GraphicsSupport.h"
+
+#include "BufferView.h"
+#include "lyxtext.h"
+#include "lyxrow.h"
+#include "paragraph.h"
+#include "frontends/Painter.h"
+
+
+typedef std::list<VisibleParagraph> VPList;
+
+
+VPList const getVisibleParagraphs(BufferView const & bv)
+{
+ // top_y is not const because it's reset by getRowNearY.
+ int top_y = bv.text->first_y;
+ Row const * row = bv.text->getRowNearY(top_y);
+
+ int const bv_height = bv.painter().paperHeight();
+
+ VPList vps;
+ Row const * last_row = 0;
+
+ for (int height = 0; row && height < bv_height; row = row->next()) {
+ height += row->height();
+
+ if (vps.empty() || vps.back().par != row->par()) {
+ vps.push_back(VisibleParagraph(row->par(),
+ row->pos(),
+ row->par()->size()));
+ }
+
+ last_row = row;
+ }
+
+ // If the end of the final paragraph is not visble,
+ // update vps.back().end
+ if (last_row && last_row->next() &&
+ last_row->par() == last_row->next()->par()) {
+ vps.back().end = last_row->next()->pos();
+ }
+
+ return vps;
+}
+
+
+namespace {
+
+struct InsetVisibleInParagraph {
+ InsetVisibleInParagraph(Inset const & inset) : inset_(inset) {}
+ bool operator()(VisibleParagraph const & vp)
+ {
+ Paragraph * par = vp.par;
+ Paragraph::inset_iterator it = par->inset_iterator_begin();
+ Paragraph::inset_iterator end = par->inset_iterator_end();
+
+ // Can't refactor this as a functor because we rely on the
+ // inset_iterator member function getPos().
+ for (; it != end; ++it) {
+ lyx::pos_type const pos = it.getPos();
+ if (pos >= vp.start && pos <= vp.end) {
+ if (*it == &inset_ ||
+ it->getInsetFromID(inset_.id()) != 0)
+ return true;
+ }
+ }
+ return false;
+ }
+
+private:
+ Inset const & inset_;
+};
+
+} // namespace anon
+
+
+bool isInsetVisible(Inset const & inset, VPList const & vps)
+{
+ if (vps.empty())
+ return false;
+
+ VPList::const_iterator it = vps.begin();
+ VPList::const_iterator end = vps.end();
+
+ it = std::find_if(it, end, InsetVisibleInParagraph(inset));
+
+ return it != end;
+}
--- /dev/null
+// -*- C++ -*-
+/**
+ * \file GraphicsSupport.h
+ * Copyright 2002 the LyX Team
+ * Read the file COPYING
+ *
+ * \author Angus Leeming <leeming@lyx.org>
+ */
+
+#ifndef GRAPHICSSUPPORT_H
+#define GRAPHICSSUPPORT_H
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "support/types.h"
+#include <list>
+
+class BufferView;
+class Inset;
+class Paragraph;
+
+/** A Paragraph * together with delimiters for the start and end positions
+ of visibility.
+ */
+struct VisibleParagraph {
+ ///
+ VisibleParagraph() : par(0), start(0), end(0) {}
+ ///
+ VisibleParagraph(Paragraph * p, lyx::pos_type s, lyx::pos_type e)
+ : par(p), start(s), end(e) {}
+ ///
+ Paragraph * par;
+ ///
+ lyx::pos_type start;
+ ///
+ lyx::pos_type end;
+};
+
+
+/// Returns a list of all Paragraphs currently visible in bv.
+std::list<VisibleParagraph> const getVisibleParagraphs(BufferView const & bv);
+
+/** Given this data, check whether inset lies within it and is, therefore,
+ * visible.
+ */
+bool isInsetVisible(Inset const & inset, std::list<VisibleParagraph> const &);
+
+#endif // GRAPHICSSUPPORT_H
GraphicsLoader.C \
$(GRAPHICSIMAGEXPM) GraphicsParams.C \
GraphicsParams.h \
+ GraphicsSupport.h \
+ GraphicsSupport.C \
GraphicsTypes.h \
PreviewImage.h \
PreviewImage.C \
* Copyright 2002 the LyX Team
* Read the file COPYING
*
- * \author Angus Leeming <a.leeming@ic.ac.uk>
+ * \author Angus Leeming <leeming@lyx.org>
*/
#include <config.h>
#include "GraphicsImage.h"
#include "GraphicsLoader.h"
-#include "debug.h"
-
#include "support/lyxlib.h"
#include <boost/bind.hpp>
///
~Impl();
///
- void startLoading();
- ///
- Image const * image();
+ Image const * image(Inset const &, BufferView const &);
///
void statusChanged();
///
PreviewLoader & ploader_;
///
- boost::scoped_ptr<Loader> const iloader_;
+ Loader iloader_;
///
string const snippet_;
///
{}
-void PreviewImage::startLoading()
-{
- return pimpl_->startLoading();
-}
-
-
string const & PreviewImage::snippet() const
{
return pimpl_->snippet_;
}
+
int PreviewImage::ascent() const
{
- Image const * const image = pimpl_->image();
+ Image const * const image = pimpl_->iloader_.image();
if (!image)
return 0;
int PreviewImage::descent() const
{
- Image const * const image = pimpl_->image();
+ Image const * const image = pimpl_->iloader_.image();
if (!image)
return 0;
int PreviewImage::width() const
{
- Image const * const image = pimpl_->image();
+ Image const * const image = pimpl_->iloader_.image();
return image ? image->getWidth() : 0;
}
-Image const * PreviewImage::image() const
+Image const * PreviewImage::image(Inset const & inset,
+ BufferView const & bv) const
{
- return pimpl_->image();
+ return pimpl_->image(inset, bv);
}
string const & s,
string const & bf,
double af)
- : parent_(p), ploader_(l), iloader_(new Loader(bf)),
+ : parent_(p), ploader_(l), iloader_(bf),
snippet_(s), ascent_frac_(af)
-{}
+{
+ iloader_.statusChanged.connect(
+ boost::bind(&Impl::statusChanged, this));
+}
PreviewImage::Impl::~Impl()
{
- lyx::unlink(iloader_->filename());
+ lyx::unlink(iloader_.filename());
}
-void PreviewImage::Impl::startLoading()
+Image const * PreviewImage::Impl::image(Inset const & inset,
+ BufferView const & bv)
{
- if (iloader_->status() != WaitingToLoad)
- return;
+ if (iloader_.status() == WaitingToLoad)
+ iloader_.startLoading(inset, bv);
- iloader_->statusChanged.connect(
- boost::bind(&Impl::statusChanged, this));
- iloader_->startLoading();
+ return iloader_.image();
}
-Image const * PreviewImage::Impl::image()
-{
-// startLoading();
- return iloader_->image();
-}
-
void PreviewImage::Impl::statusChanged()
{
- switch (iloader_->status()) {
+ switch (iloader_.status()) {
case WaitingToLoad:
case Loading:
case Converting:
case ErrorLoading:
case ErrorGeneratingPixmap:
case ErrorUnknown:
- //lyx::unlink(iloader_->filename());
+ //lyx::unlink(iloader_.filename());
ploader_.remove(snippet_);
break;
case Ready:
- lyx::unlink(iloader_->filename());
+ lyx::unlink(iloader_.filename());
ploader_.imageReady(parent_);
break;
}
* Copyright 2002 the LyX Team
* Read the file COPYING
*
- * \author Angus Leeming <a.leeming@ic.ac.uk>
+ * \author Angus Leeming <leeming@lyx.org>
*/
#ifndef PREVIEWIMAGE_H
#include "LString.h"
#include <boost/scoped_ptr.hpp>
+class Inset;
+class BufferView;
+
namespace grfx {
class PreviewLoader;
///
~PreviewImage();
- /// We are explicit about when we begin the loading process.
- void startLoading();
-
///
string const & snippet() const;
///
int descent() const;
///
int width() const;
- ///
- Image const * image() const;
+
+ /** If the image is not yet loaded (WaitingToLoad), then this method
+ * triggers that.
+ * inset and bv are passed so we can choose to load only
+ * those insets that are visible.
+ */
+ Image const * image(Inset const & inset, BufferView const & bv) const;
private:
/// Use the Pimpl idiom to hide the internals.
* Copyright 2002 the LyX Team
* Read the file COPYING
*
- * \author Angus Leeming <a.leeming@ic.ac.uk>
+ * \author Angus Leeming <leeming@lyx.org>
*/
#include <config.h>
if (retval > 0)
return;
+ // Paranoia check!
InProgressMap::iterator git = in_progress_.find(command);
if (git == in_progress_.end()) {
lyxerr << "PreviewLoader::finishedGenerating(): unable to find "
InProgressStore::const_iterator it = git->second.snippets.begin();
InProgressStore::const_iterator end = git->second.snippets.end();
+ std::list<PreviewImagePtr> newimages;
+
int metrics_counter = 0;
for (; it != end; ++it, ++metrics_counter) {
string const & snip = it->first;
PreviewImagePtr ptr(new PreviewImage(parent_, snip, file, af));
cache_[snip] = ptr;
- ptr->startLoading();
+ newimages.push_back(ptr);
}
// Remove the item from the list of still-executing processes.
in_progress_.erase(git);
+
+ // Tell the outside world
+ std::list<PreviewImagePtr>::const_iterator nit = newimages.begin();
+ std::list<PreviewImagePtr>::const_iterator nend = newimages.end();
+ for (; nit != nend; ++nit) {
+ parent_.imageReady(*nit->get());
+ }
}
+2002-07-12 Angus Leeming <leeming@lyx.org>
+
+ * insetgraphics.C: use the new smart loading capabilities of the image
+ loader.
+
2002-07-13 Dekel Tsur <dekelts@tau.ac.il>
* insettabular.C (edit): Move into correct cell when entering a
x += lwidth;
if (cache_->loader.status() == grfx::WaitingToLoad) {
- cache_->loader.startLoading();
+ cache_->loader.startLoading(*this, *bv);
}
// This will draw the graphics. If the graphics has not been loaded yet,
+2002-07-12 Angus Leeming <leeming@lyx.org>
+
+ * formula.C: use the new smart loading capabilities of the image loader.
+
2002-07-14 John Levon <moz@compsoc.man.ac.uk>
* mathformula.C: use Lsstream.h not sstream
void InsetFormula::draw(BufferView * bv, LyXFont const & font,
int y, float & xx, bool) const
{
+ // This initiates the loading of the preview, so should come
+ // before the metrics are computed.
+ bool const use_preview = preview_->usePreview();
+
int const x = int(xx);
int const w = width(bv, font);
int const d = descent(bv, font);
MathPainterInfo pi(bv->painter());
- if (preview_->usePreview()) {
+ if (use_preview) {
pi.pain.image(x + 1, y - a + 1, w - 2, h - 2,
- *(preview_->pimage_->image()));
+ *(preview_->pimage_->image(*this, *bv)));
} else {
//pi.base.style = display() ? LM_ST_DISPLAY : LM_ST_TEXT;
pi.base.style = LM_ST_TEXT;
if (!pimage_)
return false;
- return pimage_->image();
+ return pimage_->image(parent_, *view);
}