mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-10 20:04:46 +00:00
* Split the graphics loader into a frontend and a backend.
* Add frontend code to generate and display the pixmap to InsetGraphics. * Add (much simpler) frontend code to the LyXScreen to show the splash screen once more. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@4480 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
254272868f
commit
514156adbb
@ -1,3 +1,10 @@
|
||||
2002-06-25 Angus Leeming <leeming@lyx.org>
|
||||
|
||||
* lyxfunc.C (dispatch): Comment out the call to
|
||||
grfx::GCache::changeDisplay. The method no longer exists now that the
|
||||
pixmap generation part of the graphics loader has been moved into
|
||||
InsetGraphics.
|
||||
|
||||
2002-06-24 Lars Gullik Bjønnes <larsbj@birdstep.com>
|
||||
|
||||
* text2.C: layout as layout
|
||||
|
@ -1,3 +1,8 @@
|
||||
2002-06-25 Angus Leeming <leeming@lyx.org>
|
||||
|
||||
* ControlGraphics.C (readBB): Channges associated with the changed
|
||||
interface to the graphics cache.
|
||||
|
||||
2002-06-24 Lars Gullik Bjønnes <larsbj@birdstep.com>
|
||||
|
||||
* ControlParagraph.C: layout as layout
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include "graphics/GraphicsCache.h"
|
||||
#include "graphics/GraphicsConverter.h"
|
||||
#include "graphics/GraphicsImage.h"
|
||||
|
||||
#include "insets/insetgraphics.h"
|
||||
#include "insets/insetgraphicsParams.h"
|
||||
@ -110,10 +111,18 @@ string const ControlGraphics::readBB(string const & file)
|
||||
return readBB_from_PSFile(abs_file);
|
||||
|
||||
// we don't, so ask the Graphics Cache if it has loaded the file
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
grfx::GCache & gc = grfx::GCache::get();
|
||||
return ("0 0 " +
|
||||
tostr(gc.raw_width(abs_file)) + ' ' +
|
||||
tostr(gc.raw_height(abs_file)));
|
||||
grfx::ImagePtr const image = gc.image(abs_file);
|
||||
|
||||
if (image.get()) {
|
||||
width = image->getWidth();
|
||||
height = image->getHeight();
|
||||
}
|
||||
|
||||
return ("0 0 " + tostr(width) + ' ' + tostr(height));
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,6 +4,8 @@
|
||||
* Read the file COPYING
|
||||
*
|
||||
* \author John Levon <moz@compsoc.man.ac.uk>
|
||||
*
|
||||
* Splash screen code added by Angus Leeming
|
||||
*/
|
||||
|
||||
#ifdef __GNUG__
|
||||
@ -23,14 +25,152 @@
|
||||
#include "language.h"
|
||||
#include "debug.h"
|
||||
|
||||
// Splash screen-specific stuff
|
||||
#include "lyxfont.h"
|
||||
#include "version.h"
|
||||
|
||||
#include "graphics/GraphicsCache.h"
|
||||
#include "graphics/GraphicsCacheItem.h"
|
||||
#include "graphics/GraphicsImage.h"
|
||||
#include "graphics/GraphicsParams.h"
|
||||
|
||||
#include "support/filetools.h" // LibFileSearch
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
using std::min;
|
||||
using std::max;
|
||||
using std::endl;
|
||||
|
||||
namespace {
|
||||
|
||||
class SplashScreen : boost::noncopyable {
|
||||
public:
|
||||
/// This is a singleton class. Get the instance.
|
||||
static SplashScreen const & get();
|
||||
///
|
||||
grfx::GImage const * image() const { return image_.get(); }
|
||||
///
|
||||
string const & text() const { return text_; }
|
||||
///
|
||||
LyXFont const & font() const { return font_; }
|
||||
|
||||
private:
|
||||
/** Make the c-tor, d-tor private so we can control how many objects
|
||||
* are instantiated.
|
||||
*/
|
||||
SplashScreen();
|
||||
///
|
||||
~SplashScreen();
|
||||
|
||||
/** Connected to grfx::GCacheItem::statusChanged, so will generate the
|
||||
* pixmap as soon as the file is loaded into memory.
|
||||
*/
|
||||
void createPixmap();
|
||||
|
||||
/** Must store a copy of the cached item to ensure that it is not
|
||||
* erased unexpectedly by the cache itself.
|
||||
*/
|
||||
grfx::GraphicPtr graphic_;
|
||||
/** We generate a pixmap from a copy of the grfx::GImage * stored in
|
||||
* the cache.
|
||||
*/
|
||||
grfx::ImagePtr image_;
|
||||
/// The loading status of the image.
|
||||
grfx::ImageStatus status_;
|
||||
/// The text to be written on top of the pixmap
|
||||
string const text_;
|
||||
/// in this font...
|
||||
LyXFont font_;
|
||||
};
|
||||
|
||||
|
||||
SplashScreen const & SplashScreen::get()
|
||||
{
|
||||
static SplashScreen singleton;
|
||||
return singleton;
|
||||
}
|
||||
|
||||
|
||||
SplashScreen::SplashScreen()
|
||||
: status_(grfx::WaitingToLoad),
|
||||
text_(lyx_version ? lyx_version : "unknown")
|
||||
{
|
||||
string const file = LibFileSearch("images", "banner", "xpm");
|
||||
if (file.empty())
|
||||
return;
|
||||
|
||||
// The font used to display the version info
|
||||
font_.setFamily(LyXFont::SANS_FAMILY);
|
||||
font_.setSeries(LyXFont::BOLD_SERIES);
|
||||
font_.setSize(LyXFont::SIZE_NORMAL);
|
||||
font_.setColor(LColor::yellow);
|
||||
|
||||
// Load up the graphics file
|
||||
grfx::GCache & gc = grfx::GCache::get();
|
||||
if (!gc.inCache(file))
|
||||
gc.add(file);
|
||||
// We /must/ make a local copy of this.
|
||||
graphic_ = gc.graphic(file);
|
||||
|
||||
if (graphic_->status() == grfx::Loaded) {
|
||||
createPixmap();
|
||||
} else {
|
||||
graphic_->statusChanged.connect(
|
||||
boost::bind(&SplashScreen::createPixmap, this));
|
||||
graphic_->startLoading();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SplashScreen::~SplashScreen()
|
||||
{
|
||||
if (!graphic_.get())
|
||||
return;
|
||||
|
||||
string const file = graphic_->filename();
|
||||
graphic_.reset();
|
||||
|
||||
// If only the cache itself now references this item, then it will be
|
||||
// removed.
|
||||
grfx::GCache::get().remove(file);
|
||||
}
|
||||
|
||||
|
||||
void SplashScreen::createPixmap()
|
||||
{
|
||||
if (!graphic_.get() || image_.get())
|
||||
return;
|
||||
|
||||
if (graphic_->status() != grfx::Loaded)
|
||||
return;
|
||||
|
||||
if (status_ != grfx::WaitingToLoad)
|
||||
return;
|
||||
|
||||
// Strictly speaking, we need to create a copy only if we're going to
|
||||
// modify the image (scale, etc).
|
||||
image_.reset(graphic_->image()->clone());
|
||||
|
||||
bool const success = image_->setPixmap(grfx::GParams());
|
||||
|
||||
if (success) {
|
||||
status_ = grfx::Loaded;
|
||||
} else {
|
||||
image_.reset();
|
||||
status_ = grfx::ErrorScalingEtc;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace anon
|
||||
|
||||
|
||||
LyXScreen::LyXScreen()
|
||||
: force_clear_(true), cursor_visible_(false)
|
||||
{
|
||||
// Start loading the pixmap as soon as possible
|
||||
SplashScreen::get();
|
||||
}
|
||||
|
||||
|
||||
@ -297,42 +437,26 @@ void LyXScreen::greyOut()
|
||||
workarea().workHeight(),
|
||||
LColor::bottomarea);
|
||||
|
||||
// FIXME: pending GUIIzation / cleanup of graphics cache.
|
||||
// We should be using something like this.
|
||||
#if 0
|
||||
static bool first = true;
|
||||
if (first) {
|
||||
first = false;
|
||||
|
||||
splash_file_ = (lyxrc.show_banner) ?
|
||||
LibFileSearch("images", "banner", "xpm") : string();
|
||||
if (splash_file_) {
|
||||
grfx::GCache & gc = grfx::GCache::get();
|
||||
gc.add(splash_file_);
|
||||
gc.startLoading(splash_file_);
|
||||
}
|
||||
}
|
||||
|
||||
// Add a splash screen to the centre of the work area
|
||||
grfx::GCache & gc = grfx::GCache::get();
|
||||
grfx::ImagePtr const splash = gc.image(splash_file_);
|
||||
if (splash.get()) {
|
||||
int const w = splash->getWidth();
|
||||
int const h = splash->getHeight();
|
||||
SplashScreen const & splash = SplashScreen::get();
|
||||
grfx::GImage const * const splash_image = splash.image();
|
||||
if (splash_image) {
|
||||
int const w = splash_image->getWidth();
|
||||
int const h = splash_image->getHeight();
|
||||
|
||||
int const x = 0.5 * (workarea().workWidth() - w);
|
||||
int const y = 0.5 * (workarea().workHeight() - h);
|
||||
int x = 0.5 * (workarea().workWidth() - w);
|
||||
int y = 0.5 * (workarea().workHeight() - h);
|
||||
|
||||
workarea().getPainter().image(x, y, w, h, splash->getPixmap());
|
||||
workarea().getPainter().image(x, y, w, h, *splash_image);
|
||||
|
||||
string const & splash_text = splash.text();
|
||||
LyXFont const & splash_font = splash.font();
|
||||
|
||||
x += 260;
|
||||
y += 265;
|
||||
|
||||
workarea().getPainter().text(x, y, splash_text, splash_font);
|
||||
}
|
||||
#endif
|
||||
// Alternatively, we should compile this into the code.
|
||||
// I think that that is better here (so that the pixmap is displayed on
|
||||
// start-up).
|
||||
// Would need a new method
|
||||
// virtual Pixmap splashPixmap() = 0;
|
||||
// or some such.
|
||||
// Angus 21 June 2002
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,3 +1,10 @@
|
||||
2002-06-25 Angus Leeming <leeming@lyx.org>
|
||||
|
||||
* FormPreferences.C (LnFmisc::apply): Comment out the call to
|
||||
grfx::GCache::changeDisplay. The method no longer exists now that the
|
||||
pixmap generation part of the graphics loader has been moved into
|
||||
InsetGraphics.
|
||||
|
||||
2002-06-24 Lars Gullik Bjønnes <larsbj@birdstep.com>
|
||||
|
||||
* Toolbar_pimpl.C: layout as layout
|
||||
|
@ -1842,10 +1842,16 @@ void FormPreferences::LnFmisc::apply() const
|
||||
} else {
|
||||
lyxrc.display_graphics = "no";
|
||||
}
|
||||
|
||||
#ifdef WITH_WARNINGS
|
||||
#warning FIXME!! The graphics cache no longer has a changeDisplay method.
|
||||
#endif
|
||||
#if 0
|
||||
if (old_value != lyxrc.display_graphics) {
|
||||
grfx::GCache & gc = grfx::GCache::get();
|
||||
gc.changeDisplay();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,3 +1,15 @@
|
||||
2002-06-25 Angus Leeming <leeming@lyx.org>
|
||||
|
||||
* GraphicsCache.[Ch]:
|
||||
* GraphicsCacheItem.[Ch]:
|
||||
* GraphicsTypes.h: rewrite the graphics cache to just load a graphics
|
||||
file into memory. The cache no longer controls the generation of the
|
||||
pixmap. Instead, it just emits a signal when the loading status of an
|
||||
image changes.
|
||||
The cache no longer stores InsetGraphics pointers and nor does it
|
||||
assume responsibility for modifying an image (scaling, rotating etc).
|
||||
Instead, that must now be performed elsewhere.
|
||||
|
||||
2002-06-19 Angus Leeming <leeming@lyx.org>
|
||||
|
||||
* GraphicsConverter.C: add using std::endl directive.
|
||||
|
@ -16,8 +16,11 @@
|
||||
#include "GraphicsCache.h"
|
||||
#include "GraphicsCacheItem.h"
|
||||
#include "GraphicsImage.h"
|
||||
#include "GraphicsParams.h"
|
||||
#include "insets/insetgraphics.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include "support/filetools.h"
|
||||
|
||||
#include "frontends/lyx_gui.h"
|
||||
|
||||
namespace grfx {
|
||||
@ -49,145 +52,74 @@ GCache::~GCache()
|
||||
}
|
||||
|
||||
|
||||
void GCache::update(InsetGraphics const & inset, string const & filepath)
|
||||
std::vector<string> GCache::loadableFormats() const
|
||||
{
|
||||
// A subset only of InsetGraphicsParams is needed for display purposes.
|
||||
// The GraphicsParams c-tor also interrogates lyxrc to ascertain whether
|
||||
// to display or not.
|
||||
GParams params = inset.params().asGParams(filepath);
|
||||
|
||||
// Each inset can reference only one file, so check the cache for any
|
||||
// graphics files referenced by inset. If the name of this file is
|
||||
// different from that in params, then remove the reference.
|
||||
CacheType::iterator it = find(inset);
|
||||
|
||||
if (it != cache->end()) {
|
||||
CacheItemType item = it->second;
|
||||
if (item->filename() != params.filename) {
|
||||
item->remove(inset);
|
||||
if (item->empty())
|
||||
cache->erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
// Are we adding a new file or modifying the display of an existing one?
|
||||
it = cache->find(params.filename);
|
||||
|
||||
if (it != cache->end()) {
|
||||
it->second->modify(inset, params);
|
||||
return;
|
||||
}
|
||||
|
||||
CacheItemType item(new GCacheItem(inset, params));
|
||||
if (item.get() != 0)
|
||||
(*cache)[params.filename] = item;
|
||||
}
|
||||
|
||||
|
||||
void GCache::remove(InsetGraphics const & inset)
|
||||
{
|
||||
CacheType::iterator it = find(inset);
|
||||
if (it == cache->end())
|
||||
return;
|
||||
|
||||
CacheItemType item = it->second;
|
||||
item->remove(inset);
|
||||
if (item->empty()) {
|
||||
cache->erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GCache::startLoading(InsetGraphics const & inset)
|
||||
{
|
||||
CacheType::iterator it = find(inset);
|
||||
if (it == cache->end())
|
||||
return;
|
||||
|
||||
it->second->startLoading(inset);
|
||||
}
|
||||
|
||||
|
||||
ImagePtr const GCache::image(InsetGraphics const & inset) const
|
||||
{
|
||||
CacheType::const_iterator it = find(inset);
|
||||
if (it == cache->end())
|
||||
return ImagePtr();
|
||||
|
||||
return it->second->image(inset);
|
||||
}
|
||||
|
||||
|
||||
ImageStatus GCache::status(InsetGraphics const & inset) const
|
||||
{
|
||||
CacheType::const_iterator it = find(inset);
|
||||
if (it == cache->end())
|
||||
return ErrorUnknown;
|
||||
|
||||
return it->second->status(inset);
|
||||
}
|
||||
|
||||
|
||||
void GCache::changeDisplay(bool changed_background)
|
||||
{
|
||||
CacheType::iterator it = cache->begin();
|
||||
CacheType::iterator end = cache->end();
|
||||
for(; it != end; ++it)
|
||||
it->second->changeDisplay(changed_background);
|
||||
}
|
||||
|
||||
|
||||
GCache::CacheType::iterator
|
||||
GCache::find(InsetGraphics const & inset)
|
||||
{
|
||||
CacheType::iterator it = cache->begin();
|
||||
CacheType::iterator end = cache->end();
|
||||
for (; it != end; ++it) {
|
||||
if (it->second->referencedBy(inset))
|
||||
return it;
|
||||
}
|
||||
|
||||
return cache->end();
|
||||
}
|
||||
|
||||
|
||||
GCache::CacheType::const_iterator
|
||||
GCache::find(InsetGraphics const & inset) const
|
||||
{
|
||||
CacheType::const_iterator it = cache->begin();
|
||||
CacheType::const_iterator end = cache->end();
|
||||
for (; it != end; ++it) {
|
||||
if (it->second->referencedBy(inset))
|
||||
return it;
|
||||
}
|
||||
|
||||
return cache->end();
|
||||
}
|
||||
|
||||
|
||||
unsigned int GCache::raw_width(string const & filename) const
|
||||
{
|
||||
CacheType::const_iterator it = cache->find(filename);
|
||||
if (it == cache->end())
|
||||
return 0;
|
||||
|
||||
return it->second->raw_width();
|
||||
}
|
||||
|
||||
|
||||
unsigned int GCache::raw_height(string const & filename) const
|
||||
{
|
||||
CacheType::const_iterator it = cache->find(filename);
|
||||
if (it == cache->end())
|
||||
return 0;
|
||||
|
||||
return it->second->raw_height();
|
||||
}
|
||||
|
||||
|
||||
std::vector<string> GCache::loadableFormats() const {
|
||||
return GImage::loadableFormats();
|
||||
}
|
||||
|
||||
} // namespace grfx
|
||||
|
||||
void GCache::add(string const & file)
|
||||
{
|
||||
if (!AbsolutePath(file)) {
|
||||
lyxerr << "GCacheItem::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"
|
||||
<< "The file is already in the cache."
|
||||
<< std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
(*cache)[file] = GraphicPtr(new GCacheItem(file));
|
||||
}
|
||||
|
||||
|
||||
void GCache::remove(string const & file)
|
||||
{
|
||||
CacheType::iterator it = cache->find(file);
|
||||
if (it == cache->end())
|
||||
return;
|
||||
|
||||
GraphicPtr item = it->second;
|
||||
|
||||
if (item.use_count() == 1) {
|
||||
// The graphics file is in the cache, but nothing else
|
||||
// references it.
|
||||
cache->erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool GCache::inCache(string const & file) const
|
||||
{
|
||||
return cache->find(file) != cache->end();
|
||||
}
|
||||
|
||||
|
||||
GraphicPtr const GCache::graphic(string const & file) const
|
||||
{
|
||||
CacheType::const_iterator it = cache->find(file);
|
||||
if (it == cache->end())
|
||||
return GraphicPtr();
|
||||
|
||||
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
|
||||
|
@ -27,74 +27,64 @@
|
||||
#include <vector>
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
class InsetGraphics;
|
||||
|
||||
namespace grfx {
|
||||
|
||||
class GCacheItem;
|
||||
|
||||
class GCache : boost::noncopyable {
|
||||
public:
|
||||
|
||||
/// This is a singleton class. Get the instance.
|
||||
static GCache & get();
|
||||
|
||||
///
|
||||
~GCache();
|
||||
|
||||
/// Add a file to the cache (or modify an existing image).
|
||||
void update(InsetGraphics const &, string const & filepath);
|
||||
|
||||
/** Remove the data associated with this inset.
|
||||
* Called from the InsetGraphics d-tor.
|
||||
/** Which graphics formats can be loaded directly by the image loader.
|
||||
* Other formats can be loaded if a converter to a loadable format
|
||||
* can be defined.
|
||||
*/
|
||||
void remove(InsetGraphics const &);
|
||||
|
||||
/** No processing of the image will take place until this call is
|
||||
* received.
|
||||
*/
|
||||
void startLoading(InsetGraphics const &);
|
||||
|
||||
/** If (changed_background == true), then the background color of the
|
||||
* graphics inset has changed. Update all images.
|
||||
* Else, the preferred display type has changed.
|
||||
* Update the view of all insets whose display type is DEFAULT.
|
||||
*/
|
||||
void changeDisplay(bool changed_background = false);
|
||||
|
||||
/// Get the image referenced by a particular inset.
|
||||
ImagePtr const image(InsetGraphics const &) const;
|
||||
|
||||
/// How far have we got in loading the image?
|
||||
ImageStatus status(InsetGraphics const &) const;
|
||||
|
||||
// Used to ascertain the Bounding Box of non (e)ps files.
|
||||
unsigned int raw_width(string const & filename) const;
|
||||
///
|
||||
unsigned int raw_height(string const & filename) const;
|
||||
///
|
||||
std::vector<string> loadableFormats() const;
|
||||
|
||||
/// 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.
|
||||
*/
|
||||
void remove(string const & file);
|
||||
|
||||
/// Returns \c true if the file is in the cache.
|
||||
bool inCache(string const & file) const;
|
||||
|
||||
/** Get the cache item associated with file.
|
||||
* Returns an empty container if there is no such item.
|
||||
*
|
||||
* IMPORTANT: whatever uses an image must make a local copy of this
|
||||
* GraphicPtr. The boost::shared_ptr<>::use_count() function is
|
||||
* used to ascertain whether or not to remove the item from the cache
|
||||
* when remove(file) is called.
|
||||
*
|
||||
* 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;
|
||||
|
||||
private:
|
||||
/** Make the c-tor private so we can control how many objects
|
||||
/** Make the c-tor, d-tor private so we can control how many objects
|
||||
* are instantiated.
|
||||
*/
|
||||
GCache();
|
||||
|
||||
/// The cache contains data of this type.
|
||||
typedef boost::shared_ptr<GCacheItem> CacheItemType;
|
||||
///
|
||||
~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, CacheItemType> CacheType;
|
||||
|
||||
/// Search the cache by inset.
|
||||
CacheType::const_iterator find(InsetGraphics const &) const;
|
||||
///
|
||||
CacheType::iterator find(InsetGraphics const &);
|
||||
typedef std::map<string, GraphicPtr> CacheType;
|
||||
|
||||
/** Store a pointer to the cache so that we can forward declare
|
||||
* GCacheItem.
|
||||
|
@ -14,311 +14,44 @@
|
||||
#pragma implementation
|
||||
#endif
|
||||
|
||||
#include "graphics/GraphicsCache.h"
|
||||
#include "graphics/GraphicsCacheItem.h"
|
||||
#include "graphics/GraphicsImage.h"
|
||||
#include "graphics/GraphicsParams.h"
|
||||
#include "graphics/GraphicsConverter.h"
|
||||
|
||||
#include "insets/insetgraphics.h"
|
||||
|
||||
#include "BufferView.h"
|
||||
#include "debug.h"
|
||||
#include "gettext.h"
|
||||
#include "lyx_main.h" // for global dispatch method
|
||||
|
||||
#include "support/LAssert.h"
|
||||
#include "support/filetools.h"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
// Very, Very UGLY!
|
||||
extern BufferView * current_view;
|
||||
|
||||
using std::endl;
|
||||
|
||||
|
||||
namespace grfx {
|
||||
|
||||
GCacheItem::GCacheItem(InsetGraphics const & inset, GParams const & params)
|
||||
: filename_(params.filename), zipped_(false),
|
||||
GCacheItem::GCacheItem(string const & file)
|
||||
: filename_(file), zipped_(false),
|
||||
remove_loaded_file_(false), status_(WaitingToLoad)
|
||||
{
|
||||
ModifiedItemPtr item(new ModifiedItem(inset, params, image_));
|
||||
modified_images.push_back(item);
|
||||
}
|
||||
{}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
typedef GCacheItem::ModifiedItemPtr ModifiedItemPtr;
|
||||
|
||||
class Compare_Params {
|
||||
public:
|
||||
Compare_Params(GParams const & p) : p_(p) {}
|
||||
|
||||
bool operator()(ModifiedItemPtr const & ptr)
|
||||
{
|
||||
if (!ptr.get())
|
||||
return false;
|
||||
return ptr->params() == p_;
|
||||
}
|
||||
|
||||
private:
|
||||
GParams const & p_;
|
||||
};
|
||||
|
||||
class Find_Inset {
|
||||
public:
|
||||
Find_Inset(InsetGraphics const & i) : i_(i) {}
|
||||
|
||||
bool operator()(ModifiedItemPtr const & ptr)
|
||||
{
|
||||
if (!ptr.get())
|
||||
return false;
|
||||
return ptr->referencedBy(i_);
|
||||
}
|
||||
|
||||
private:
|
||||
InsetGraphics const & i_;
|
||||
};
|
||||
|
||||
} // namespace anon
|
||||
|
||||
|
||||
void GCacheItem::modify(InsetGraphics const & inset, GParams const & params)
|
||||
{
|
||||
// Does this inset currently reference an existing ModifiedItem with
|
||||
// different params?
|
||||
// If so, remove the inset from the ModifiedItem's internal list
|
||||
// of insets
|
||||
ListType::iterator begin = modified_images.begin();
|
||||
ListType::iterator end = modified_images.end();
|
||||
ListType::iterator it = begin;
|
||||
while (it != end) {
|
||||
it = std::find_if(it, end, Find_Inset(inset));
|
||||
if (it == end)
|
||||
break;
|
||||
if ((*it)->params() != params) {
|
||||
(*it)->remove(inset);
|
||||
if ((*it)->empty())
|
||||
it = modified_images.erase(it);
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
// Is there an existing ModifiedItem with these params?
|
||||
// If so, add inset to the list of insets referencing this ModifiedItem
|
||||
begin = modified_images.begin();
|
||||
end = modified_images.end();
|
||||
it = std::find_if(begin, end, Compare_Params(params));
|
||||
if (it != end) {
|
||||
(*it)->add(inset);
|
||||
return;
|
||||
}
|
||||
|
||||
// If no ModifiedItem exists with these params, then create one.
|
||||
ModifiedItemPtr item(new ModifiedItem(inset, params, image_));
|
||||
modified_images.push_back(item);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void GCacheItem::remove(InsetGraphics const & inset)
|
||||
{
|
||||
// search the list of ModifiedItems for one referenced by this inset.
|
||||
// If it is found, remove the reference.
|
||||
// If the ModifiedItem is now referenced by no insets, remove it.
|
||||
ListType::iterator begin = modified_images.begin();
|
||||
ListType::iterator end = modified_images.end();
|
||||
ListType::iterator it = std::find_if(begin, end, Find_Inset(inset));
|
||||
|
||||
if (it == end)
|
||||
return;
|
||||
|
||||
(*it)->remove(inset);
|
||||
if ((*it)->empty()) {
|
||||
modified_images.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GCacheItem::startLoading(InsetGraphics const & inset)
|
||||
void GCacheItem::startLoading()
|
||||
{
|
||||
if (status() != WaitingToLoad)
|
||||
return;
|
||||
|
||||
// Check that the image is referenced by this inset
|
||||
ListType::const_iterator begin = modified_images.begin();
|
||||
ListType::const_iterator end = modified_images.end();
|
||||
ListType::const_iterator it =
|
||||
std::find_if(begin, end, Find_Inset(inset));
|
||||
|
||||
if (it == end)
|
||||
return;
|
||||
|
||||
if ((*it)->params().display == GParams::NONE)
|
||||
return;
|
||||
|
||||
convertToDisplayFormat();
|
||||
}
|
||||
|
||||
|
||||
bool GCacheItem::empty() const
|
||||
{
|
||||
return modified_images.empty();
|
||||
}
|
||||
|
||||
|
||||
bool GCacheItem::referencedBy(InsetGraphics const & inset) const
|
||||
{
|
||||
// Is one of the list of ModifiedItems referenced by this inset?
|
||||
ListType::const_iterator begin = modified_images.begin();
|
||||
ListType::const_iterator end = modified_images.end();
|
||||
return std::find_if(begin, end, Find_Inset(inset)) != end;
|
||||
}
|
||||
|
||||
|
||||
string const & GCacheItem::filename() const
|
||||
{
|
||||
return filename_;
|
||||
}
|
||||
|
||||
|
||||
ImagePtr const GCacheItem::image(InsetGraphics const & inset) const
|
||||
{
|
||||
// find a ModifiedItem that is referenced by this inset.
|
||||
ListType::const_iterator begin = modified_images.begin();
|
||||
ListType::const_iterator end = modified_images.end();
|
||||
ListType::const_iterator it =
|
||||
std::find_if(begin, end, Find_Inset(inset));
|
||||
|
||||
// Someone's being daft.
|
||||
if (it == end)
|
||||
return ImagePtr();
|
||||
|
||||
// We are expressly requested to not render the image
|
||||
if ((*it)->params().display == GParams::NONE)
|
||||
return ImagePtr();
|
||||
|
||||
// If the original image has been loaded, return what's going on
|
||||
// in the ModifiedItem
|
||||
if (status() == Loaded)
|
||||
return (*it)->image();
|
||||
|
||||
return ImagePtr();
|
||||
}
|
||||
|
||||
|
||||
ImageStatus GCacheItem::status(InsetGraphics const & inset) const
|
||||
{
|
||||
// find a ModifiedItem that is referenced by this inset.
|
||||
ListType::const_iterator begin = modified_images.begin();
|
||||
ListType::const_iterator end = modified_images.end();
|
||||
ListType::const_iterator it =
|
||||
std::find_if(begin, end, Find_Inset(inset));
|
||||
|
||||
// Someone's being daft.
|
||||
if (it == end)
|
||||
return ErrorUnknown;
|
||||
|
||||
if (status() == Loaded)
|
||||
return (*it)->status();
|
||||
|
||||
return status();
|
||||
}
|
||||
|
||||
|
||||
// Called internally only. Use to ascertain the status of the loading of the
|
||||
// original image. No scaling etc.
|
||||
ImageStatus GCacheItem::status() const
|
||||
{
|
||||
return status_;
|
||||
}
|
||||
|
||||
|
||||
void GCacheItem::setStatus(ImageStatus new_status)
|
||||
{
|
||||
if (status_ == new_status)
|
||||
return;
|
||||
|
||||
status_ = new_status;
|
||||
|
||||
// Loop over all insets and tell the BufferView that it has changed.
|
||||
typedef ModifiedItem::ListType::const_iterator inset_iterator;
|
||||
|
||||
ListType::const_iterator it = modified_images.begin();
|
||||
ListType::const_iterator end = modified_images.end();
|
||||
for (; it != end; ++it) {
|
||||
inset_iterator it2 = (*it)->insets.begin();
|
||||
inset_iterator end2 = (*it)->insets.end();
|
||||
|
||||
for (; it2 != end2; ++it2) {
|
||||
InsetGraphics * inset =
|
||||
const_cast<InsetGraphics *>(*it2);
|
||||
|
||||
// Use of current_view is very, very Evil!!
|
||||
current_view->updateInset(inset, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GCacheItem::changeDisplay(bool changed_background)
|
||||
{
|
||||
ListType::iterator begin = modified_images.begin();
|
||||
ListType::iterator end = modified_images.end();
|
||||
|
||||
// The background has changed. Change all modified images.
|
||||
if (changed_background) {
|
||||
for (ListType::iterator it = begin; it != end; ++it) {
|
||||
(*it)->setPixmap();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ListType temp_list;
|
||||
|
||||
for (ListType::iterator it = begin; it != end; ++it) {
|
||||
// ModifiedItem::changeDisplay returns a full
|
||||
// ModifiedItemPtr if any of the insets have display=DEFAULT
|
||||
// and if that DEFAULT value has changed
|
||||
ModifiedItemPtr new_item = (*it)->changeDisplay();
|
||||
if (!new_item.get())
|
||||
continue;
|
||||
|
||||
temp_list.push_back(new_item);
|
||||
|
||||
// The original store may now be empty
|
||||
if ((*it)->insets.empty()) {
|
||||
it = modified_images.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
if (temp_list.empty())
|
||||
return;
|
||||
|
||||
// Recombine new_list and modified_images.
|
||||
begin = modified_images.begin();
|
||||
end = modified_images.end();
|
||||
|
||||
ListType::const_iterator tbegin = temp_list.begin();
|
||||
ListType::const_iterator tend = temp_list.end();
|
||||
|
||||
ListType append_list;
|
||||
|
||||
for (ListType::const_iterator tit = tbegin; tit != tend; ++tit) {
|
||||
GParams const & params = (*tit)->params();
|
||||
ListType::iterator it =
|
||||
std::find_if(begin, end, Compare_Params(params));
|
||||
if (it == end)
|
||||
append_list.push_back(*tit);
|
||||
else
|
||||
(*it)->insets.merge((*tit)->insets);
|
||||
}
|
||||
|
||||
if (append_list.empty())
|
||||
return;
|
||||
|
||||
modified_images.splice(modified_images.end(), append_list);
|
||||
statusChanged();
|
||||
}
|
||||
|
||||
|
||||
@ -386,31 +119,6 @@ void GCacheItem::imageLoaded(bool success)
|
||||
}
|
||||
|
||||
setStatus(Loaded);
|
||||
|
||||
// Loop over the list of modified images and create them.
|
||||
ListType::iterator it = modified_images.begin();
|
||||
ListType::iterator end = modified_images.end();
|
||||
for (; it != end; ++it) {
|
||||
(*it)->modify(image_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned int GCacheItem::raw_width() const
|
||||
{
|
||||
if (!image_.get())
|
||||
return 0;
|
||||
|
||||
return image_->getWidth();
|
||||
}
|
||||
|
||||
|
||||
unsigned int GCacheItem::raw_height() const
|
||||
{
|
||||
if (!image_.get())
|
||||
return 0;
|
||||
|
||||
return image_->getHeight();
|
||||
}
|
||||
|
||||
|
||||
@ -512,159 +220,4 @@ void GCacheItem::convertToDisplayFormat()
|
||||
graphics_converter.convert(filename, to_file_base, from, to, on_finish);
|
||||
}
|
||||
|
||||
|
||||
ModifiedItem::ModifiedItem(InsetGraphics const & new_inset,
|
||||
GParams const & new_params,
|
||||
ImagePtr const & new_image)
|
||||
: status_(ScalingEtc)
|
||||
{
|
||||
p_.reset(new GParams(new_params));
|
||||
insets.push_back(&new_inset);
|
||||
modify(new_image);
|
||||
}
|
||||
|
||||
|
||||
void ModifiedItem::add(InsetGraphics const & inset)
|
||||
{
|
||||
insets.push_back(&inset);
|
||||
insets.sort();
|
||||
}
|
||||
|
||||
|
||||
void ModifiedItem::remove(InsetGraphics const & inset)
|
||||
{
|
||||
ListType::iterator begin = insets.begin();
|
||||
ListType::iterator end = insets.end();
|
||||
ListType::iterator it = std::remove(begin, end, &inset);
|
||||
insets.erase(it, end);
|
||||
}
|
||||
|
||||
|
||||
bool ModifiedItem::referencedBy(InsetGraphics const & inset) const
|
||||
{
|
||||
ListType::const_iterator begin = insets.begin();
|
||||
ListType::const_iterator end = insets.end();
|
||||
return std::find(begin, end, &inset) != end;
|
||||
}
|
||||
|
||||
|
||||
ImagePtr const ModifiedItem::image() const
|
||||
{
|
||||
if (modified_image_.get())
|
||||
return modified_image_;
|
||||
|
||||
return original_image_;
|
||||
}
|
||||
|
||||
|
||||
void ModifiedItem::modify(ImagePtr const & new_image)
|
||||
{
|
||||
if (!new_image.get())
|
||||
return;
|
||||
|
||||
original_image_ = new_image;
|
||||
modified_image_.reset(original_image_->clone());
|
||||
|
||||
if (params().display == GParams::NONE) {
|
||||
setStatus(Loaded);
|
||||
return;
|
||||
}
|
||||
|
||||
setStatus(ScalingEtc);
|
||||
modified_image_->clip(params());
|
||||
modified_image_->rotate(params());
|
||||
modified_image_->scale(params());
|
||||
setPixmap();
|
||||
}
|
||||
|
||||
|
||||
void ModifiedItem::setPixmap()
|
||||
{
|
||||
if (!modified_image_.get())
|
||||
return;
|
||||
|
||||
if (params().display == GParams::NONE) {
|
||||
setStatus(Loaded);
|
||||
return;
|
||||
}
|
||||
|
||||
bool const success = modified_image_->setPixmap(params());
|
||||
|
||||
if (success) {
|
||||
setStatus(Loaded);
|
||||
} else {
|
||||
modified_image_.reset();
|
||||
setStatus(ErrorScalingEtc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ModifiedItem::setStatus(ImageStatus new_status)
|
||||
{
|
||||
status_ = new_status;
|
||||
|
||||
// Tell the BufferView that the inset has changed.
|
||||
// Very, Very Ugly!!
|
||||
ListType::const_iterator it = insets.begin();
|
||||
ListType::const_iterator end = insets.end();
|
||||
for (; it != end; ++it) {
|
||||
InsetGraphics * inset = const_cast<InsetGraphics *>(*it);
|
||||
current_view->updateInset(inset, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
struct Params_Changed {
|
||||
|
||||
Params_Changed(GParams const & p) : p_(p) {}
|
||||
|
||||
bool operator()(InsetGraphics const * inset)
|
||||
{
|
||||
string const path = OnlyPath(p_.filename);
|
||||
return inset->params().asGParams(path) != p_;
|
||||
}
|
||||
|
||||
private:
|
||||
GParams p_;
|
||||
};
|
||||
|
||||
} // namespace anon
|
||||
|
||||
// changeDisplay returns an initialised ModifiedItem if any of the insets
|
||||
// have display == DEFAULT and if that DEFAULT value has changed.
|
||||
// If this occurs, then (this) has these insets removed.
|
||||
ModifiedItemPtr ModifiedItem::changeDisplay()
|
||||
{
|
||||
// Loop over the list of insets. Compare the updated params for each
|
||||
// with params(). If different, move into a new list.
|
||||
ListType::iterator begin = insets.begin();
|
||||
ListType::iterator end = insets.end();
|
||||
ListType::iterator it =
|
||||
std::remove_if(begin, end, Params_Changed(params()));
|
||||
|
||||
if (it == end) {
|
||||
// No insets have changed params
|
||||
return ModifiedItemPtr();
|
||||
}
|
||||
|
||||
// it -> end have params that are changed. Move to the new list.
|
||||
ListType new_insets;
|
||||
new_insets.insert(new_insets.begin(), it, end);
|
||||
insets.erase(it, end);
|
||||
|
||||
// Create a new ModifiedItem with these new params. Note that
|
||||
// the only params that have changed are the display ones,
|
||||
// so we don't need to crop, rotate, scale.
|
||||
string const path = OnlyPath(p_->filename);
|
||||
|
||||
ModifiedItemPtr new_item(new ModifiedItem(*this));
|
||||
new_item->insets = new_insets;
|
||||
*(new_item->p_) = (*new_insets.begin())->params().asGParams(path);
|
||||
|
||||
new_item->setPixmap();
|
||||
return new_item;
|
||||
}
|
||||
|
||||
} // namespace grfx
|
||||
|
@ -39,65 +39,37 @@
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <boost/signals/signal0.hpp>
|
||||
#include <boost/signals/signal1.hpp>
|
||||
#include <boost/signals/connection.hpp>
|
||||
#include <boost/signals/trackable.hpp>
|
||||
|
||||
#include <list>
|
||||
|
||||
class InsetGraphics;
|
||||
|
||||
namespace grfx {
|
||||
|
||||
class GParams;
|
||||
class ModifiedItem;
|
||||
|
||||
/// A grfx::GCache item holder.
|
||||
class GCacheItem : boost::noncopyable, public boost::signals::trackable {
|
||||
public:
|
||||
/// the GCacheItem contains data of this type.
|
||||
typedef boost::shared_ptr<ModifiedItem> ModifiedItemPtr;
|
||||
|
||||
///
|
||||
GCacheItem(InsetGraphics const &, GParams const &);
|
||||
|
||||
/// The params have changed (but still refer to this file).
|
||||
void modify(InsetGraphics const &, GParams const &);
|
||||
|
||||
/// Remove the reference to this inset.
|
||||
void remove(InsetGraphics const &);
|
||||
GCacheItem(string const & file);
|
||||
|
||||
/// It's in the cache. Now start the loading process.
|
||||
void startLoading(InsetGraphics const &);
|
||||
void startLoading();
|
||||
|
||||
/// Is the cache item referenced by any insets at all?
|
||||
bool empty() const;
|
||||
|
||||
/// The name of the original image file.
|
||||
string const & filename() const;
|
||||
|
||||
/// Is this image file referenced by this inset?
|
||||
bool referencedBy(InsetGraphics const &) const;
|
||||
|
||||
/** Returns the image referenced by this inset (or an empty container
|
||||
* if it's not yet loaded.
|
||||
/** Get the image associated with filename_.
|
||||
If the image is not yet loaded, return a null pointer.
|
||||
*/
|
||||
ImagePtr const image(InsetGraphics const &) const;
|
||||
ImagePtr const image() const { return image_; }
|
||||
|
||||
/// The loading status of the image referenced by this inset.
|
||||
ImageStatus status(InsetGraphics const &) const;
|
||||
/// How far have we got in loading the image?
|
||||
ImageStatus status() const { return status_; }
|
||||
|
||||
/** If (changed_background == true), then the background color of the
|
||||
* graphics inset has changed. Update all images.
|
||||
* Else, the preferred display type has changed.
|
||||
* Update the view of all insets whose display type is DEFAULT.
|
||||
*/
|
||||
void changeDisplay(bool changed_background);
|
||||
/// This signal is emitted when the image loading status changes.
|
||||
boost::signal0<void> statusChanged;
|
||||
|
||||
/// Used to ascertain the Bounding Box of non (e)ps files.
|
||||
unsigned int raw_width() const;
|
||||
///
|
||||
unsigned int raw_height() const;
|
||||
string const & filename() const { return filename_; }
|
||||
|
||||
private:
|
||||
/** Start the image conversion process, checking first that it is
|
||||
@ -132,9 +104,6 @@ private:
|
||||
*/
|
||||
void imageLoaded(bool);
|
||||
|
||||
/// How far have we got in loading the original, unmodified image?
|
||||
ImageStatus status() const;
|
||||
|
||||
/** Sets the status of the loading process. Also notifies
|
||||
* listeners that the status has chacnged.
|
||||
*/
|
||||
@ -153,7 +122,7 @@ private:
|
||||
*/
|
||||
bool remove_loaded_file_;
|
||||
|
||||
/// The original, unmodified image and its loading status.
|
||||
/// The image and its loading status.
|
||||
ImagePtr image_;
|
||||
///
|
||||
ImageStatus status_;
|
||||
@ -163,7 +132,7 @@ private:
|
||||
* When the image has been loaded, the signal is emitted.
|
||||
*
|
||||
* We pass a shared_ptr because it is eminently possible for the
|
||||
* ModifiedItem to be destructed before the loading is complete and
|
||||
* 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.
|
||||
*/
|
||||
@ -186,76 +155,6 @@ private:
|
||||
|
||||
/// The connection of the signal passed to GConverter::convert.
|
||||
boost::signals::connection cc_;
|
||||
|
||||
/// The list of all modified images.
|
||||
typedef std::list<ModifiedItemPtr> ListType;
|
||||
///
|
||||
ListType modified_images;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
class ModifiedItem {
|
||||
public:
|
||||
///
|
||||
ModifiedItem(InsetGraphics const &, GParams const &, ImagePtr const &);
|
||||
|
||||
///
|
||||
GParams const & params() { return *p_.get(); }
|
||||
|
||||
/// Add inset to the list of insets.
|
||||
void add(InsetGraphics const & inset);
|
||||
|
||||
/// Remove inset from the list of insets.
|
||||
void remove(InsetGraphics const & inset);
|
||||
|
||||
///
|
||||
bool empty() const { return insets.empty(); }
|
||||
|
||||
/// Is this ModifiedItem referenced by inset?
|
||||
bool referencedBy(InsetGraphics const & inset) const;
|
||||
|
||||
///
|
||||
ImagePtr const image() const;
|
||||
|
||||
/// How far have we got in loading the modified image?
|
||||
ImageStatus status() const { return status_; }
|
||||
|
||||
/** Called from GCacheItem once the raw image is loaded.
|
||||
* Modifies the image in accord with p_.
|
||||
*/
|
||||
void modify(ImagePtr const &);
|
||||
|
||||
/// Updates the pixmap.
|
||||
void setPixmap();
|
||||
|
||||
/** changeDisplay returns a full ModifiedItemPtr if any of the
|
||||
* insets have display=DEFAULT and if that DEFAULT value has
|
||||
* changed.
|
||||
* If this occurs, then this has these insets removed.
|
||||
*/
|
||||
boost::shared_ptr<ModifiedItem> changeDisplay();
|
||||
|
||||
///
|
||||
typedef std::list<InsetGraphics const *> ListType;
|
||||
|
||||
/// Make these accessible for changeDisplay.
|
||||
ListType insets;
|
||||
|
||||
private:
|
||||
/** Sets the status of the loading process. Also notifies
|
||||
* listeners that the status has changed.
|
||||
*/
|
||||
void setStatus(ImageStatus new_status);
|
||||
|
||||
/// The original and modified images and its loading status.
|
||||
ImagePtr original_image_;
|
||||
///
|
||||
ImagePtr modified_image_;
|
||||
///
|
||||
ImageStatus status_;
|
||||
///
|
||||
boost::shared_ptr<GParams> p_;
|
||||
};
|
||||
|
||||
} // namespace grfx
|
||||
|
@ -20,7 +20,8 @@
|
||||
namespace grfx {
|
||||
|
||||
GParams::GParams()
|
||||
: width(0),
|
||||
: display(COLOR),
|
||||
width(0),
|
||||
height(0),
|
||||
scale(0),
|
||||
angle(0)
|
||||
|
@ -26,6 +26,10 @@ 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 {
|
||||
|
@ -1,3 +1,10 @@
|
||||
2002-06-25 Angus Leeming <leeming@lyx.org>
|
||||
|
||||
* insetgraphics.[Ch]: The inset now assumes the responsibility for
|
||||
generating a pixmap once the graphics file is loaded into memory.
|
||||
The current_view ugliness that was in grfx::ModifiedImage has been
|
||||
moved here now that grfx::ModifiedImage is no more.
|
||||
|
||||
2002-06-24 Lars Gullik Bjønnes <larsbj@birdstep.com>
|
||||
|
||||
* insettext.C: layout as layout
|
||||
|
@ -79,6 +79,7 @@ TODO Before initial production release:
|
||||
#include "insets/insetgraphicsParams.h"
|
||||
|
||||
#include "graphics/GraphicsCache.h"
|
||||
#include "graphics/GraphicsCacheItem.h"
|
||||
#include "graphics/GraphicsImage.h"
|
||||
|
||||
#include "frontends/LyXView.h"
|
||||
@ -103,8 +104,13 @@ TODO Before initial production release:
|
||||
#include "support/path.h"
|
||||
#include "support/systemcall.h"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <algorithm> // For the std::max
|
||||
|
||||
// Very, Very UGLY!
|
||||
extern BufferView * current_view;
|
||||
|
||||
extern string system_tempdir;
|
||||
|
||||
using std::ostream;
|
||||
@ -143,10 +149,173 @@ string const uniqueID()
|
||||
} // namespace anon
|
||||
|
||||
|
||||
struct InsetGraphics::Cache
|
||||
{
|
||||
///
|
||||
Cache(InsetGraphics &);
|
||||
///
|
||||
~Cache();
|
||||
///
|
||||
void reset(grfx::GraphicPtr const &);
|
||||
///
|
||||
bool empty() const { return !graphic_.get(); }
|
||||
///
|
||||
grfx::ImageStatus status() const;
|
||||
///
|
||||
void setStatus(grfx::ImageStatus);
|
||||
///
|
||||
grfx::GImage * image() const;
|
||||
///
|
||||
string const filename() const;
|
||||
///
|
||||
void update(string const & file_with_path);
|
||||
///
|
||||
void modify();
|
||||
|
||||
///
|
||||
int old_ascent;
|
||||
///
|
||||
grfx::GraphicPtr graphic_;
|
||||
|
||||
private:
|
||||
/// The connection to cache_->statusChanged.
|
||||
boost::signals::connection cc_;
|
||||
///
|
||||
grfx::ImageStatus status_;
|
||||
///
|
||||
grfx::GParams params_;
|
||||
///
|
||||
grfx::ImagePtr modified_image_;
|
||||
///
|
||||
InsetGraphics & parent_;
|
||||
};
|
||||
|
||||
|
||||
InsetGraphics::Cache::Cache(InsetGraphics & p)
|
||||
: old_ascent(0), status_(grfx::ErrorUnknown), parent_(p)
|
||||
{}
|
||||
|
||||
|
||||
InsetGraphics::Cache::~Cache()
|
||||
{
|
||||
string const old_file = filename();
|
||||
graphic_.reset();
|
||||
|
||||
if (!old_file.empty()) {
|
||||
grfx::GCache & gc = grfx::GCache::get();
|
||||
gc.remove(old_file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void InsetGraphics::Cache::reset(grfx::GraphicPtr const & graphic)
|
||||
{
|
||||
string const old_file = filename();
|
||||
string const new_file = graphic.get() ? graphic->filename() : string();
|
||||
if (old_file == new_file)
|
||||
return;
|
||||
|
||||
graphic_ = graphic;
|
||||
|
||||
if (!old_file.empty()) {
|
||||
grfx::GCache & gc = grfx::GCache::get();
|
||||
gc.remove(old_file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
grfx::ImageStatus InsetGraphics::Cache::status() const
|
||||
{
|
||||
return status_;
|
||||
}
|
||||
|
||||
|
||||
void InsetGraphics::Cache::setStatus(grfx::ImageStatus new_status)
|
||||
{
|
||||
status_ = new_status;
|
||||
}
|
||||
|
||||
|
||||
grfx::GImage * InsetGraphics::Cache::image() const
|
||||
{
|
||||
return modified_image_.get();
|
||||
}
|
||||
|
||||
|
||||
string const InsetGraphics::Cache::filename() const
|
||||
{
|
||||
return empty() ? string() : graphic_->filename();
|
||||
}
|
||||
|
||||
|
||||
void InsetGraphics::Cache::update(string const & file_with_path)
|
||||
{
|
||||
lyx::Assert(!file_with_path.empty());
|
||||
|
||||
// Check whether the file has changed.
|
||||
string current_file = filename();
|
||||
|
||||
if (current_file == file_with_path) {
|
||||
modify();
|
||||
return;
|
||||
}
|
||||
|
||||
// It /has/ changed.
|
||||
// Remove the connection to any previous grfx::CacheItems
|
||||
grfx::GCache & gc = grfx::GCache::get();
|
||||
if (!current_file.empty() && gc.inCache(current_file)) {
|
||||
graphic_.reset();
|
||||
gc.remove(current_file);
|
||||
cc_.disconnect();
|
||||
}
|
||||
|
||||
// Update the cache to point to the new file
|
||||
if (!gc.inCache(file_with_path))
|
||||
gc.add(file_with_path);
|
||||
|
||||
graphic_ = gc.graphic(file_with_path);
|
||||
cc_ = graphic_->statusChanged.connect(
|
||||
boost::bind(&InsetGraphics::statusChanged, &parent_));
|
||||
|
||||
setStatus(graphic_->status());
|
||||
if (status() == grfx::Loaded)
|
||||
modify();
|
||||
}
|
||||
|
||||
|
||||
void InsetGraphics::Cache::modify()
|
||||
{
|
||||
// The image has not been loaded from file
|
||||
if (!graphic_->image().get())
|
||||
return;
|
||||
|
||||
string const path = OnlyPath(filename());
|
||||
grfx::GParams params = parent_.params().asGParams(path);
|
||||
|
||||
if (params == params_)
|
||||
return;
|
||||
|
||||
params_ = params;
|
||||
setStatus(grfx::ScalingEtc);
|
||||
modified_image_.reset(graphic_->image()->clone());
|
||||
modified_image_->clip(params);
|
||||
modified_image_->rotate(params);
|
||||
modified_image_->scale(params);
|
||||
|
||||
bool const success = modified_image_->setPixmap(params);
|
||||
|
||||
if (success) {
|
||||
setStatus(grfx::Loaded);
|
||||
} else {
|
||||
modified_image_.reset();
|
||||
setStatus(grfx::ErrorScalingEtc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
InsetGraphics::InsetGraphics()
|
||||
: graphic_label(uniqueID()),
|
||||
cached_status_(grfx::ErrorUnknown), cache_filled_(false), old_asc(0)
|
||||
|
||||
cache_(new Cache(*this))
|
||||
{}
|
||||
|
||||
|
||||
@ -155,7 +324,7 @@ InsetGraphics::InsetGraphics(InsetGraphics const & ig,
|
||||
bool same_id)
|
||||
: Inset(ig, same_id),
|
||||
graphic_label(uniqueID()),
|
||||
cached_status_(grfx::ErrorUnknown), cache_filled_(false), old_asc(0)
|
||||
cache_(new Cache(*this))
|
||||
{
|
||||
setParams(ig.params(), filepath);
|
||||
}
|
||||
@ -163,10 +332,7 @@ InsetGraphics::InsetGraphics(InsetGraphics const & ig,
|
||||
|
||||
InsetGraphics::~InsetGraphics()
|
||||
{
|
||||
cached_image_.reset();
|
||||
grfx::GCache & gc = grfx::GCache::get();
|
||||
gc.remove(*this);
|
||||
|
||||
cache_->reset(grfx::GraphicPtr());
|
||||
// Emits the hide signal to the dialog connected (if any)
|
||||
hideDialog();
|
||||
}
|
||||
@ -176,7 +342,7 @@ string const InsetGraphics::statusMessage() const
|
||||
{
|
||||
string msg;
|
||||
|
||||
switch (cached_status_) {
|
||||
switch (cache_->status()) {
|
||||
case grfx::WaitingToLoad:
|
||||
msg = _("Waiting for draw request to start loading...");
|
||||
break;
|
||||
@ -187,7 +353,10 @@ string const InsetGraphics::statusMessage() const
|
||||
msg = _("Converting to loadable format...");
|
||||
break;
|
||||
case grfx::ScalingEtc:
|
||||
msg = _("Loaded. Scaling etc...");
|
||||
msg = _("Scaling etc...");
|
||||
break;
|
||||
case grfx::Loaded:
|
||||
msg = _("Loaded.");
|
||||
break;
|
||||
case grfx::ErrorNoFile:
|
||||
msg = _("No file found!");
|
||||
@ -204,43 +373,27 @@ string const InsetGraphics::statusMessage() const
|
||||
case grfx::ErrorUnknown:
|
||||
msg = _("No image");
|
||||
break;
|
||||
case grfx::Loaded:
|
||||
msg = _("Loaded but not displaying");
|
||||
break;
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
void InsetGraphics::setCache() const
|
||||
bool InsetGraphics::imageIsDrawable() const
|
||||
{
|
||||
if (cache_filled_)
|
||||
return;
|
||||
if (!cache_->image() || cache_->status() != grfx::Loaded)
|
||||
return false;
|
||||
|
||||
grfx::GCache & gc = grfx::GCache::get();
|
||||
cached_status_ = gc.status(*this);
|
||||
cached_image_ = gc.image(*this);
|
||||
}
|
||||
|
||||
|
||||
bool InsetGraphics::drawImage() const
|
||||
{
|
||||
setCache();
|
||||
Pixmap const pixmap =
|
||||
(cached_status_ == grfx::Loaded && cached_image_.get() != 0) ?
|
||||
cached_image_->getPixmap() : 0;
|
||||
|
||||
return pixmap != 0;
|
||||
return cache_->image()->getPixmap() != 0;
|
||||
}
|
||||
|
||||
|
||||
int InsetGraphics::ascent(BufferView *, LyXFont const &) const
|
||||
{
|
||||
old_asc = 50;
|
||||
if (drawImage())
|
||||
old_asc = cached_image_->getHeight();
|
||||
return old_asc;
|
||||
cache_->old_ascent = 50;
|
||||
if (imageIsDrawable())
|
||||
cache_->old_ascent = cache_->image()->getHeight();
|
||||
return cache_->old_ascent;
|
||||
}
|
||||
|
||||
|
||||
@ -252,8 +405,8 @@ int InsetGraphics::descent(BufferView *, LyXFont const &) const
|
||||
|
||||
int InsetGraphics::width(BufferView *, LyXFont const & font) const
|
||||
{
|
||||
if (drawImage())
|
||||
return cached_image_->getWidth();
|
||||
if (imageIsDrawable())
|
||||
return cache_->image()->getWidth();
|
||||
else {
|
||||
int font_width = 0;
|
||||
|
||||
@ -281,8 +434,7 @@ int InsetGraphics::width(BufferView *, LyXFont const & font) const
|
||||
void InsetGraphics::draw(BufferView * bv, LyXFont const & font,
|
||||
int baseline, float & x, bool) const
|
||||
{
|
||||
int oasc = old_asc;
|
||||
grfx::ImageStatus old_status_ = cached_status_;
|
||||
int oasc = cache_->old_ascent;
|
||||
|
||||
int ldescent = descent(bv, font);
|
||||
int lascent = ascent(bv, font);
|
||||
@ -301,20 +453,18 @@ void InsetGraphics::draw(BufferView * bv, LyXFont const & font,
|
||||
int old_x = int(x);
|
||||
x += lwidth;
|
||||
|
||||
// Initiate the loading of the graphics file
|
||||
if (cached_status_ == grfx::WaitingToLoad) {
|
||||
grfx::GCache & gc = grfx::GCache::get();
|
||||
gc.startLoading(*this);
|
||||
if (cache_->status() == grfx::WaitingToLoad) {
|
||||
cache_->graphic_->startLoading();
|
||||
}
|
||||
|
||||
// This will draw the graphics. If the graphics has not been loaded yet,
|
||||
// we draw just a rectangle.
|
||||
Painter & paint = bv->painter();
|
||||
|
||||
if (drawImage()) {
|
||||
if (imageIsDrawable()) {
|
||||
paint.image(old_x + 2, baseline - lascent,
|
||||
lwidth - 4, lascent + ldescent,
|
||||
*cached_image_.get());
|
||||
*cache_->image());
|
||||
|
||||
} else {
|
||||
|
||||
@ -343,24 +493,18 @@ void InsetGraphics::draw(BufferView * bv, LyXFont const & font,
|
||||
|
||||
// the status message may mean we changed size, so indicate
|
||||
// we need a row redraw
|
||||
#if 0
|
||||
if (old_status_ != grfx::ErrorUnknown && old_status_ != cached_status_) {
|
||||
bv->getLyXText()->status(bv, LyXText::CHANGED_IN_DRAW);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Reset the cache, ready for the next draw request
|
||||
#if 0
|
||||
cached_status_ = grfx::ErrorUnknown;
|
||||
cached_image_.reset();
|
||||
cache_filled_ = false;
|
||||
}
|
||||
|
||||
|
||||
// Update the inset after parameters changed (read from file or changed in
|
||||
// dialog. The grfx::GCache makes the decisions about whether or not to draw
|
||||
// (interogates lyxrc, ascertains whether file exists etc)
|
||||
void InsetGraphics::updateInset(string const & filepath) const
|
||||
{
|
||||
grfx::GCache & gc = grfx::GCache::get();
|
||||
gc.update(*this, filepath);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -400,7 +544,7 @@ void InsetGraphics::read(Buffer const * buf, LyXLex & lex)
|
||||
else
|
||||
lyxerr[Debug::GRAPHICS] << "Not a Graphics or Figure inset!\n";
|
||||
|
||||
updateInset(buf->filePath());
|
||||
cache_->update(MakeAbsPath(params().filename, buf->filePath()));
|
||||
}
|
||||
|
||||
|
||||
@ -864,6 +1008,16 @@ void InsetGraphics::validate(LaTeXFeatures & features) const
|
||||
}
|
||||
|
||||
|
||||
void InsetGraphics::statusChanged()
|
||||
{
|
||||
cache_->setStatus(cache_->graphic_->status());
|
||||
if (cache_->status() == grfx::Loaded)
|
||||
cache_->modify();
|
||||
|
||||
current_view->updateInset(this, false);
|
||||
}
|
||||
|
||||
|
||||
bool InsetGraphics::setParams(InsetGraphicsParams const & p,
|
||||
string const & filepath)
|
||||
{
|
||||
@ -876,7 +1030,7 @@ bool InsetGraphics::setParams(InsetGraphicsParams const & p,
|
||||
params_ = p;
|
||||
|
||||
// Update the inset with the new parameters.
|
||||
updateInset(filepath);
|
||||
cache_->update(MakeAbsPath(params().filename, filepath));
|
||||
|
||||
// We have changed data, report it.
|
||||
return true;
|
||||
|
@ -27,6 +27,8 @@
|
||||
#include <boost/signals/signal0.hpp>
|
||||
#include <boost/signals/trackable.hpp>
|
||||
|
||||
#include <memory> // auto_ptr
|
||||
|
||||
class Dialogs;
|
||||
class LaTeXFeatures;
|
||||
|
||||
@ -98,18 +100,19 @@ public:
|
||||
boost::signal0<void> hideDialog;
|
||||
|
||||
private:
|
||||
/// Set the cached variables
|
||||
void setCache() const;
|
||||
/// Is the image ready to draw, or should we display a message instead?
|
||||
bool drawImage() const;
|
||||
bool imageIsDrawable() const;
|
||||
|
||||
/** This method is connected to cache_->statusChanged, so we are
|
||||
informed when the image has been loaded.
|
||||
*/
|
||||
void statusChanged();
|
||||
|
||||
/// Read the inset native format
|
||||
void readInsetGraphics(LyXLex & lex);
|
||||
/// Read the FigInset file format
|
||||
void readFigInset(LyXLex & lex);
|
||||
|
||||
/// Update the inset after parameter change.
|
||||
void updateInset(string const & filepath) const;
|
||||
/// Get the status message, depends on the image loading status.
|
||||
string const statusMessage() const;
|
||||
/// Create the options for the latex command.
|
||||
@ -124,13 +127,13 @@ private:
|
||||
string const graphic_label;
|
||||
|
||||
/// The cached variables
|
||||
mutable grfx::ImageStatus cached_status_;
|
||||
///
|
||||
mutable grfx::ImagePtr cached_image_;
|
||||
///
|
||||
mutable bool cache_filled_;
|
||||
///
|
||||
mutable int old_asc;
|
||||
class Cache;
|
||||
friend class Cache;
|
||||
/** Can change the contents of the cache, but not the pointer.
|
||||
* Use std::auto_ptr not boost::scoped_ptr so we do not have to define
|
||||
* Cache in advance.
|
||||
*/
|
||||
std::auto_ptr<Cache> const cache_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1634,8 +1634,13 @@ string const LyXFunc::dispatch(kb_action action, string argument)
|
||||
lyxColorHandler->updateColor(lcolor.getFromLyXName(lyx_name));
|
||||
|
||||
if (graphicsbg_changed) {
|
||||
#ifdef WITH_WARNINGS
|
||||
#warning FIXME!! The graphics cache no longer has a changeDisplay method.
|
||||
#endif
|
||||
#if 0
|
||||
grfx::GCache & gc = grfx::GCache::get();
|
||||
gc.changeDisplay(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
owner->view()->repaint();
|
||||
|
Loading…
Reference in New Issue
Block a user