+2002-07-05 Angus Leeming <leeming@lyx.org>
+
+ * scripts/lyxpreview2ppm.sh: added.
+ * scripts/lyxpreview2xpm: removed.
+
2002-06-19 Herbert Voss <voss@perce.de>
* configure.m4: add converters for epsi and (x)fig
--- /dev/null
+#!/bin/sh
+
+# This script takes a LaTeX file and generates PPM files, one per page.
+# The idea is to use it with preview.sty to create small bitmap previews of
+# things like math equations.
+
+# The script takes two arguments, the name of the file to be converted and
+# the resolution of the generated image, to be passed to gs.
+if [ $# -ne 2 ]; then
+ exit 1
+fi
+
+# A couple of helper functions
+FIND_EXECUTABLE=""
+FIND_IT () {
+ which ${FIND_EXECUTABLE} > /dev/null
+ STATUS=$?
+ if [ ${STATUS} -ne 0 ]; then
+ echo "Unable to find \"${FIND_EXECUTABLE}\". Please install."
+ exit 1
+ fi
+}
+
+CHECK_STATUS () {
+ if [ ${STATUS} -ne 0 ]; then
+ echo "${EXECUTABLE} failed."
+ # Remove everything except the original .tex file.
+ FILES=`ls ${BASE}* | sed -e "/${BASE}.tex/d"`
+ rm -f ${FILES}
+ exit ${STATUS}
+ fi
+}
+
+# We use latex, dvips and gs, so check that they're all there.
+FIND_EXECUTABLE=latex; FIND_IT
+FIND_EXECUTABLE=dvips; FIND_IT
+FIND_EXECUTABLE=gs; FIND_IT
+
+# Initialise some variables.
+TEXFILE=$1
+RESOLUTION=$2
+
+DIR=`dirname ${TEXFILE}`
+BASE=`basename ${TEXFILE} .tex`
+DVIFILE=${BASE}.dvi
+PSFILE=${BASE}.ps
+METRICS=${BASE}.metrics
+
+# Perform the conversion.
+cd ${DIR}
+latex -interaction=batchmode ${TEXFILE}
+
+STATUS=$?
+EXECUTABLE="latex ${TEXFILE}"; CHECK_STATUS
+
+dvips -o ${PSFILE} ${DVIFILE}
+
+STATUS=$?
+EXECUTABLE="dvips ${DVIFILE}"; CHECK_STATUS
+
+# Older versions of gs have problems with a large degree of anti-aliasing
+# at high resolutions
+ALPHA=4
+if [ ${RESOLUTION} -gt 150 ]; then
+ ALPHA=2
+fi
+
+gs -q -dNOPAUSE -dBATCH -dSAFER -sDEVICE=pnm -sOutputFile=${BASE}%03d.ppm \
+ -dGraphicsAlphaBit=${ALPHA} -dTextAlphaBits=${ALPHA} -r${RESOLUTION} \
+ ${PSFILE}
+
+STATUS=$?
+EXECUTABLE="gs ${PSFILE}"; CHECK_STATUS
+
+# Attempt to generate a file ${METRICS} that contains only the tightpage
+# bounding box info, extract from ${PSFILE}
+
+# 1. Create a file containing the sed instructions
+SEDSCRIPT=bbox.sed
+cat - > ${SEDSCRIPT} <<EOF
+# Delete everything that's enclosed between %%BeginDocument and %%EndDocument
+/^\%\%BeginDocument/,/^\%\%EndDocument/d
+
+# Extract the tightpage bounding box info.
+# Given this snippet:
+# %%Page: 1 1
+# 1 0 bop
+# -32890 -32890 32890 32890 492688 0 744653
+# The sed command gives this:
+# %%Page 1: -32890 -32890 32890 32890 492688 0 744653
+
+/^\%\%Page:/{
+ s/\: \(.*\) .*$/ \1: /;N;N
+ s/\n[^\n]*\n//p
+}
+
+# Delete everything (so only the stuff that's printed, above, goes into the
+# metrics file).
+d
+EOF
+
+# 2. Run sed!
+sed -f ${SEDSCRIPT} < ${PSFILE} > ${METRICS}
+STATUS=$?
+rm -f ${SEDSCRIPT}
+EXECUTABLE="extracting metrics"; CHECK_STATUS
+
+# All was successful, so remove everything except the ppm files and the
+# metrics file.
+FILES=`ls ${BASE}* | sed -e "/${BASE}.metrics/d" -e "/${BASE}.*.ppm/d"`
+rm -f ${FILES}
+++ /dev/null
-#!/bin/bash
-
-# converts a single inset's TeX representation to an .xpm
-
-dir=`dirname $2`
-base=${dir}/`basename $2 .xpm`
-
-cp $1 ${base}.tex
-#(cd ${dir} ; latex ${base})
-(cd ${dir} ; pdflatex --interaction batchmode ${base})
-dvips -x 1750 -R -o ${base}.ps ${base}.dvi
-convert -crop 0x0 ${base}.ps ${base}.xpm
-rm ${base}.tex ${base}.aux ${base}.dvi ${base}.log ${base}.eps || true
-
-exit 0
#include "mathed/formulabase.h"
+#include "graphics/Previews.h"
+
#include "support/LAssert.h"
#include "support/lstrings.h"
#include "support/filetools.h"
owner_->updateToolbar();
owner_->updateLayoutChoice();
owner_->updateWindowTitle();
+
+ if (grfx::Previews::activated() && buffer_)
+ grfx::Previews::get().generateBufferPreviews(buffer_);
}
+2002-07-05 Angus Leeming <leeming@lyx.org>
+
+ * BufferView_pimpl.C (buffer): generate previews if desired.
+
+ * LColor.h: add "preview" to the color enum.
+
+ * LColor.C (LColor): add a corresponding entry to the items array.
+
+ * buffer.C (~Buffer): remove any previewed LaTeX snippets assocoated
+ with this buffer.
+
2002-07-05 Angus Leeming <leeming@lyx.org>
* buffer.[Ch] (makeLaTeXFile): create two methods where there was one.
{ foreground, N_("text"), "foreground", "black", "foreground" },
{ selection, N_("selection"), "selection", "LightBlue", "selection" },
{ latex, N_("latex text"), "latex", "DarkRed", "latex" },
+ { preview, N_("previewed snippet"), "preview", "black", "preview" },
{ note, N_("note"), "note", "yellow", "note" },
{ notebg, N_("note background"), "notebg", "yellow", "notebg" },
{ depthbar, N_("depth bar"), "depthbar", "IndianRed", "depthbar" },
selection,
/// Text color in LaTeX mode
latex,
+ /// The color used for previews
+ preview,
/// Text color for notes
note,
#include "frontends/Dialogs.h"
#include "frontends/Alert.h"
+#include "graphics/Previews.h"
+
#include "support/textutils.h"
#include "support/filetools.h"
#include "support/path.h"
par = tmppar;
}
paragraph = 0;
+
+ // Remove any previewed LaTeX snippets assocoated with this buffer.
+ grfx::Previews::get().removeLoader(this);
}
+2002-07-05 Angus Leeming <leeming@lyx.org>
+
+ * lyx_gui.h (hexname): new function.
+
2002-07-04 Lars Gullik Bjønnes <larsbj@birdstep.com>
* screen.C (SplashScreen): we change
#ifndef LYX_GUI_H
#define LYX_GUI_H
-
-#include <config.h>
-
-#include "LString.h"
-
+
+#include "LColor.h"
+#include "LString.h"
#include <vector>
class Dialogs;
/// initialise graphics
void init_graphics();
+
+ /** Eg, passing LColor::black returns "000000",
+ * passing LColor::white returns "ffffff".
+ */
+ string const hexname(LColor::color col);
}
#endif // LYX_GUI_H
+2002-07-05 Angus Leeming <leeming@lyx.org>
+
+ * lyx_gui.C (hexname): new function.
+
2002-07-04 Lars Gullik Bjønnes <larsbj@birdstep.com>
* lyx_gui.C (init_graphics): boost::function assign, not
#include "graphics/GraphicsImageXPM.h"
#endif
-
+#include "Lsstream.h"
+#include <iomanip>
#include <fcntl.h>
-
#include <boost/bind.hpp>
#ifndef CXX_GLOBAL_CSTD
using std::vector;
using std::hex;
using std::endl;
+using std::setbase;
+using std::setfill;
+using std::setw;
extern bool finished;
extern BufferList bufferlist;
Image::loadableFormats = boost::bind(&ImageXPM::loadableFormats);
#endif
}
+
+
+string const lyx_gui::hexname(LColor::color col)
+{
+ string const name = lcolor.getX11Name(col);
+ Display * const display = fl_get_display();
+ Colormap const cmap = fl_state[fl_get_vclass()].colormap;
+ XColor xcol, ccol;
+
+ if (XLookupColor(display, cmap, name.c_str(), &xcol, &ccol) == 0) {
+ lyxerr << "X can't find color \""
+ << lcolor.getLyXName(col)
+ << "\"" << endl;
+ return string();
+ }
+
+ ostringstream os;
+
+ // Note that X stores the RGB values in the range 0 - 65535
+ // whilst we require them in the range 0 - 255.
+ os << setbase(16) << setfill('0')
+ << setw(2) << (xcol.red / 256)
+ << setw(2) << (xcol.green / 256)
+ << setw(2) << (xcol.blue / 256);
+
+ return os.str().c_str();
+}
+
+2002-07-05 Angus Leeming <leeming@lyx.org>
+
+ * PreviewImage.h:
+ * PreviewImage.C:
+ * PreviewLoader.h:
+ * PreviewLoader.C:
+ * PreviewMetrics.h:
+ * PreviewMetrics.C:
+ * Previews.h:
+ * Previews.C: new files. The previewed LaTeX snippet stuff.
+
+ * Makefile.am: add these files.
+
2002-07-05 Angus Leeming <leeming@lyx.org>
* GraphicsLoader.h: whitespace.
GraphicsLoader.C \
$(GRAPHICSIMAGEXPM) GraphicsParams.C \
GraphicsParams.h \
- GraphicsTypes.h
+ GraphicsTypes.h \
+ PreviewImage.h \
+ PreviewImage.C \
+ PreviewLoader.h \
+ PreviewLoader.C \
+ PreviewMetrics.h \
+ PreviewMetrics.C \
+ Previews.h \
+ Previews.C
+
--- /dev/null
+/**
+ * \file PreviewImage.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 "PreviewImage.h"
+#include "PreviewLoader.h"
+#include "GraphicsImage.h"
+#include "GraphicsLoader.h"
+
+#include "debug.h"
+
+#include "support/lyxlib.h"
+
+#include <boost/bind.hpp>
+#include <boost/signals/trackable.hpp>
+
+
+namespace grfx {
+
+struct PreviewImage::Impl : public boost::signals::trackable {
+ ///
+ Impl(PreviewImage & p, PreviewLoader & l,
+ string const & s, string const & f, double af);
+ ///
+ void startLoading();
+ ///
+ Image const * image() const { return iloader_->image(); }
+ ///
+ void statusChanged();
+
+ ///
+ PreviewImage const & parent_;
+ ///
+ PreviewLoader & ploader_;
+ ///
+ boost::scoped_ptr<Loader> const iloader_;
+ ///
+ string const snippet_;
+ ///
+ double const ascent_frac_;
+};
+
+
+PreviewImage::PreviewImage(PreviewLoader & l,
+ string const & s,
+ string const & f,
+ double af)
+ : pimpl_(new Impl(*this, l, s, f, af))
+{}
+
+
+PreviewImage::~PreviewImage()
+{}
+
+
+void PreviewImage::startLoading()
+{
+ return pimpl_->startLoading();
+}
+
+
+string const & PreviewImage::snippet() const
+{
+ return pimpl_->snippet_;
+}
+
+int PreviewImage::ascent() const
+{
+ Image const * const image = pimpl_->image();
+ if (!image)
+ return 0;
+
+ return int(pimpl_->ascent_frac_ * double(image->getHeight()));
+}
+
+
+int PreviewImage::descent() const
+{
+ Image const * const image = pimpl_->image();
+ if (!image)
+ return 0;
+
+ return int((1.0 - pimpl_->ascent_frac_) * double(image->getHeight()));
+}
+
+
+int PreviewImage::width() const
+{
+ Image const * const image = pimpl_->image();
+ return image ? image->getWidth() : 0;
+}
+
+
+Image const * PreviewImage::image() const
+{
+ return pimpl_->image();
+}
+
+
+PreviewImage::Impl::Impl(PreviewImage & p, PreviewLoader & l,
+ string const & s,
+ string const & bf,
+ double af)
+ : parent_(p), ploader_(l), iloader_(new Loader(bf)),
+ snippet_(s), ascent_frac_(af)
+{}
+
+
+void PreviewImage::Impl::startLoading()
+{
+ if (iloader_->status() != WaitingToLoad)
+ return;
+
+ iloader_->statusChanged.connect(
+ boost::bind(&Impl::statusChanged, this));
+ iloader_->startLoading();
+}
+
+
+void PreviewImage::Impl::statusChanged()
+{
+ switch (iloader_->status()) {
+ case WaitingToLoad:
+ case Loading:
+ case Converting:
+ case Loaded:
+ case ScalingEtc:
+ break;
+
+ case ErrorNoFile:
+ case ErrorConverting:
+ case ErrorLoading:
+ case ErrorGeneratingPixmap:
+ case ErrorUnknown:
+ //lyx::unlink(iloader_->filename());
+ ploader_.remove(snippet_);
+ break;
+
+ case Ready:
+ lyx::unlink(iloader_->filename());
+ ploader_.imageReady(parent_);
+ break;
+ }
+}
+
+} // namespace grfx
--- /dev/null
+// -*- C++ -*-
+/**
+ * \file PreviewImage.h
+ * Copyright 2002 the LyX Team
+ * Read the file COPYING
+ *
+ * \author Angus Leeming <a.leeming@ic.ac.uk>
+ */
+
+#ifndef PREVIEWIMAGE_H
+#define PREVIEWIMAGE_H
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "LString.h"
+#include <boost/scoped_ptr.hpp>
+
+namespace grfx {
+
+class PreviewLoader;
+class Image;
+
+class PreviewImage {
+public:
+ /** ascent = height * ascent_frac
+ * descent = height * (1 - ascent_frac)
+ */
+ PreviewImage(PreviewLoader & parent,
+ string const & latex_snippet,
+ string const & bitmap_file,
+ double ascent_frac);
+ ///
+ ~PreviewImage();
+
+ /// We are explicit about when we begin the loading process.
+ void startLoading();
+
+ ///
+ string const & snippet() const;
+ ///
+ int ascent() const;
+ ///
+ int descent() const;
+ ///
+ int width() const;
+ ///
+ Image const * image() const;
+
+private:
+ /// 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 // PREVIEWIMAGE_H
--- /dev/null
+/*
+ * \file PreviewLoader.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 "PreviewLoader.h"
+#include "PreviewImage.h"
+#include "PreviewMetrics.h"
+
+#include "buffer.h"
+#include "bufferparams.h"
+#include "converter.h"
+#include "debug.h"
+#include "lyxrc.h"
+#include "LColor.h"
+
+#include "insets/inset.h"
+
+#include "frontends/lyx_gui.h" // hexname
+
+#include "support/filetools.h"
+#include "support/forkedcall.h"
+#include "support/lstrings.h"
+#include "support/lyxlib.h"
+
+#include <boost/bind.hpp>
+#include <boost/signals/trackable.hpp>
+
+#include <fstream>
+#include <iomanip>
+#include <map>
+
+using std::endl;
+using std::ofstream;
+using std::ostream;
+using std::setfill;
+using std::setw;
+
+
+namespace {
+
+string const unique_filename()
+{
+
+ static string dir;
+ if (dir.empty()) {
+ string const tmp = lyx::tempName();
+ lyx::unlink(tmp);
+ dir = OnlyPath(tmp);
+ }
+
+ static int theCounter = 0;
+ ostringstream os;
+ os << dir << theCounter++ << "lyxpreview";
+
+ return os.str().c_str();
+}
+
+} // namespace anon
+
+
+namespace grfx {
+
+struct PreviewLoader::Impl : public boost::signals::trackable {
+ ///
+ Impl(PreviewLoader & p, Buffer const & b);
+ ///
+ PreviewImage const * preview(string const & latex_snippet) const;
+ ///
+ PreviewLoader::Status status(string const & latex_snippet) const;
+ ///
+ void add(string const & latex_snippet);
+ ///
+ void remove(string const & latex_snippet);
+ ///
+ void startLoading();
+
+private:
+ /// Called by the Forkedcall process that generated the bitmap files.
+ void finishedGenerating(string const &, pid_t, int);
+ ///
+ void dumpPreamble(ostream &) const;
+ ///
+ void dumpData(ostream &) const;
+
+ ///
+ static void setConverter();
+ /// We don't own this
+ static Converter const * pconverter_;
+
+ /** The cache allows easy retrieval of already-generated images
+ * using the LaTeX snippet as the identifier.
+ */
+ typedef boost::shared_ptr<PreviewImage> PreviewImagePtr;
+ ///
+ typedef std::map<string, PreviewImagePtr> Cache;
+ ///
+ Cache cache_;
+
+ /** The map stores the LaTeX snippet and the name of the generated
+ * bitmap image file.
+ */
+ typedef std::map<string, string> PendingMap;
+ ///
+ PendingMap pending_;
+
+ /// Store info on a currently executing, forked process.
+ struct InProgress {
+ ///
+ typedef std::map<string, string> PendingMap;
+ ///
+ InProgress() {}
+ ///
+ InProgress(string const & mf, PendingMap const & s)
+ : metrics_file(mf), snippets(s)
+ {}
+ ///
+ string metrics_file;
+ ///
+ PendingMap snippets;
+ };
+ friend class InProgress;
+
+ /// Store all forked processes so that we can proceed thereafter.
+ typedef std::map<string, InProgress> InProgressMap;
+ ///
+ InProgressMap in_progress_;
+
+ ///
+ string filename_base_;
+ ///
+ PreviewLoader & parent_;
+ ///
+ Buffer const & buffer_;
+};
+
+
+Converter const * PreviewLoader::Impl::pconverter_;
+
+
+PreviewLoader::PreviewLoader(Buffer const & b)
+ : pimpl_(new Impl(*this, b))
+{}
+
+
+PreviewLoader::~PreviewLoader()
+{}
+
+
+PreviewImage const * PreviewLoader::preview(string const & latex_snippet) const
+{
+ return pimpl_->preview(latex_snippet);
+}
+
+
+PreviewLoader::Status PreviewLoader::status(string const & latex_snippet) const
+{
+ return pimpl_->status(latex_snippet);
+}
+
+
+void PreviewLoader::add(string const & latex_snippet)
+{
+ pimpl_->add(latex_snippet);
+}
+
+
+void PreviewLoader::remove(string const & latex_snippet)
+{
+ pimpl_->remove(latex_snippet);
+}
+
+
+void PreviewLoader::startLoading()
+{
+ pimpl_->startLoading();
+}
+
+
+void PreviewLoader::Impl::setConverter()
+{
+ if (pconverter_)
+ return;
+
+ string const from = "lyxpreview";
+
+ Formats::FormatList::const_iterator it = formats.begin();
+ Formats::FormatList::const_iterator end = formats.end();
+
+ for (; it != end; ++it) {
+ string const to = it->name();
+ if (from == to)
+ continue;
+ Converter const * ptr = converters.getConverter(from, to);
+ if (ptr) {
+ pconverter_ = ptr;
+ break;
+ }
+ }
+
+ if (pconverter_)
+ return;
+
+ static bool first = true;
+ if (!first)
+ return;
+
+ first = false;
+ lyxerr << "PreviewLoader::startLoading()\n"
+ << "No converter from \"lyxpreview\" format has been defined."
+ << endl;
+}
+
+
+PreviewLoader::Impl::Impl(PreviewLoader & p, Buffer const & b)
+ : filename_base_(unique_filename()), parent_(p), buffer_(b)
+{}
+
+
+PreviewImage const *
+PreviewLoader::Impl::preview(string const & latex_snippet) const
+{
+ Cache::const_iterator it = cache_.find(latex_snippet);
+ return (it == cache_.end()) ? 0 : it->second.get();
+}
+
+
+PreviewLoader::Status
+PreviewLoader::Impl::status(string const & latex_snippet) const
+{
+ Cache::const_iterator cit = cache_.find(latex_snippet);
+ if (cit != cache_.end())
+ return PreviewLoader::Ready;
+
+ PendingMap::const_iterator pit = pending_.find(latex_snippet);
+ if (pit != pending_.end())
+ return PreviewLoader::InQueue;
+
+ InProgressMap::const_iterator git = in_progress_.begin();
+ InProgressMap::const_iterator gend = in_progress_.end();
+
+ for (; git != gend; ++git) {
+ PendingMap::const_iterator pit =
+ git->second.snippets.find(latex_snippet);
+ if (pit != git->second.snippets.end())
+ return PreviewLoader::Processing;
+ }
+
+ return PreviewLoader::NotFound;
+}
+
+
+void PreviewLoader::Impl::add(string const & latex_snippet)
+{
+ if (!pconverter_) {
+ setConverter();
+ if (!pconverter_)
+ return;
+ }
+
+ Cache::const_iterator cit = cache_.find(latex_snippet);
+ if (cit != cache_.end())
+ return;
+
+ PendingMap::const_iterator pit = pending_.find(latex_snippet);
+ if (pit != pending_.end())
+ return;
+
+ int const snippet_counter = int(pending_.size()) + 1;
+ ostringstream os;
+ os << filename_base_
+ << setfill('0') << setw(3) << snippet_counter
+ << "." << pconverter_->to;
+ string const image_filename = os.str().c_str();
+
+ pending_[latex_snippet] = image_filename;
+}
+
+
+void PreviewLoader::Impl::remove(string const & latex_snippet)
+{
+ Cache::iterator cit = cache_.find(latex_snippet);
+ if (cit != cache_.end())
+ cache_.erase(cit);
+
+ PendingMap::iterator pit = pending_.find(latex_snippet);
+ if (pit != pending_.end())
+ pending_.erase(pit);
+
+ InProgressMap::iterator git = in_progress_.begin();
+ InProgressMap::iterator gend = in_progress_.end();
+
+ while (git != gend) {
+ InProgressMap::iterator curr = git;
+ ++git;
+
+ PendingMap::iterator pit =
+ curr->second.snippets.find(latex_snippet);
+ if (pit != curr->second.snippets.end())
+ curr->second.snippets.erase(pit);
+
+ if (curr->second.snippets.empty())
+ in_progress_.erase(curr);
+ }
+}
+
+
+void PreviewLoader::Impl::startLoading()
+{
+ if (pending_.empty())
+ return;
+
+ if (!pconverter_) {
+ setConverter();
+ if (!pconverter_)
+ return;
+ }
+
+ lyxerr[Debug::GRAPHICS] << "PreviewLoader::startLoading()" << endl;
+
+ // Output the LaTeX file.
+ string const latexfile = filename_base_ + ".tex";
+
+ ofstream of(latexfile.c_str());
+ dumpPreamble(of);
+ of << "\n\\begin{document}\n";
+ dumpData(of);
+ of << "\n\\end{document}\n";
+ of.close();
+
+ // The conversion command.
+ ostringstream cs;
+ cs << pconverter_->command << " " << latexfile << " "
+ << tostr(0.01 * lyxrc.dpi * lyxrc.zoom);
+
+ // Store the generation process in a list of all generating processes
+ // (I anticipate that this will be small!)
+ string const command = cs.str().c_str();
+ string const metrics_file = filename_base_ + ".metrics";
+ in_progress_[command] = InProgress(metrics_file, pending_);
+
+ // Reset the filename and clear the data, so we're ready to
+ // start afresh.
+ pending_.clear();
+ filename_base_ = unique_filename();
+
+ // Initiate the conversion from LaTeX to bitmap images files.
+ Forkedcall::SignalTypePtr convert_ptr;
+ convert_ptr.reset(new Forkedcall::SignalType);
+
+ convert_ptr->connect(
+ boost::bind(&Impl::finishedGenerating, this, _1, _2, _3));
+
+ Forkedcall call;
+ int ret = call.startscript(command, convert_ptr);
+
+ if (ret != 0) {
+ InProgressMap::iterator it = in_progress_.find(command);
+ if (it != in_progress_.end())
+ in_progress_.erase(it);
+
+ lyxerr[Debug::GRAPHICS] << "PreviewLoader::startLoading()\n"
+ << "Unable to start process \n"
+ << command << endl;
+ }
+}
+
+
+void PreviewLoader::Impl::finishedGenerating(string const & command,
+ pid_t /* pid */, int retval)
+{
+ string const status = retval > 0 ? "failed" : "succeeded";
+ lyxerr[Debug::GRAPHICS] << "PreviewLoader::finishedInProgress("
+ << retval << "): processing " << status
+ << " for " << command << endl;
+ if (retval > 0)
+ return;
+
+ InProgressMap::iterator git = in_progress_.find(command);
+ if (git == in_progress_.end()) {
+ lyxerr << "PreviewLoader::finishedGenerating(): unable to find "
+ "data for\n"
+ << command << "!" << endl;
+ return;
+ }
+
+ // Read the metrics file, if it exists
+ PreviewMetrics metrics_file(git->second.metrics_file);
+
+ // Add these newly generated bitmap files to the cache and
+ // start loading them into LyX.
+ PendingMap::const_iterator it = git->second.snippets.begin();
+ PendingMap::const_iterator end = git->second.snippets.end();
+
+ int metrics_counter = 0;
+ for (; it != end; ++it) {
+ string const & snip = it->first;
+
+ // Paranoia check
+ Cache::const_iterator chk = cache_.find(snip);
+ if (chk != cache_.end())
+ continue;
+
+ // Mental note (Angus, 4 July 2002, having just found out the
+ // hard way :-().
+ // We /must/ first add to the cache and then start the
+ // image loading process.
+ // If not, then outside functions can be called before by the
+ // image loader before the PreviewImage is properly constucted.
+ // This can lead to all sorts of horribleness if such a
+ // function attempts to access its internals.
+ string const & file = it->second;
+ double af = metrics_file.ascent_fraction(metrics_counter++);
+ PreviewImagePtr ptr(new PreviewImage(parent_, snip, file, af));
+
+ cache_[snip] = ptr;
+
+ ptr->startLoading();
+ }
+
+ in_progress_.erase(git);
+}
+
+
+void PreviewLoader::Impl::dumpPreamble(ostream & os) const
+{
+ // Why on earth is Buffer::makeLaTeXFile a non-const method?
+ Buffer & tmp = const_cast<Buffer &>(buffer_);
+ // Dump the preamble only.
+ tmp.makeLaTeXFile(os, string(), true, false, true);
+
+ // Loop over the insets in the buffer and dump all the math-macros.
+ Buffer::inset_iterator it = buffer_.inset_const_iterator_begin();
+ Buffer::inset_iterator end = buffer_.inset_const_iterator_end();
+
+ for (; it != end; ++it) {
+ if ((*it)->lyxCode() == Inset::MATHMACRO_CODE) {
+ (*it)->latex(&buffer_, os, true, true);
+ }
+ }
+
+ // Use the preview style file to ensure that each snippet appears on a
+ // fresh page.
+ os << "\n"
+ << "\\usepackage[active,dvips,tightpage]{preview}\n"
+ << "\n";
+
+ // This piece of PostScript magic ensures that the foreground and
+ // background colors are the same as the LyX screen.
+ string fg = lyx_gui::hexname(LColor::preview);
+ if (fg.empty()) fg = "000000";
+
+ string bg = lyx_gui::hexname(LColor::background);
+ if (bg.empty()) bg = "ffffff";
+
+ os << "\\AtBeginDocument{\\AtBeginDvi{%\n"
+ << "\\special{!userdict begin/bop-hook{//bop-hook exec\n"
+ << "<" << fg << bg << ">{255 div}forall setrgbcolor\n"
+ << "clippath fill setrgbcolor}bind def end}}}\n";
+}
+
+
+namespace {
+
+typedef std::pair<string, string> StrPair;
+
+struct CompSecond {
+ bool operator()(StrPair const & lhs, StrPair const & rhs)
+ {
+ return lhs.second < rhs.second;
+ }
+};
+
+} // namespace anon
+
+
+void PreviewLoader::Impl::dumpData(ostream & os) const
+{
+ if (pending_.empty())
+ return;
+
+ // Sorting by image filename ensures that the snippets are put into
+ // the LaTeX file in the expected order.
+ std::vector<StrPair> vec(pending_.begin(), pending_.end());
+ std::sort(vec.begin(), vec.end(), CompSecond());
+
+ std::vector<StrPair>::const_iterator it = vec.begin();
+ std::vector<StrPair>::const_iterator end = vec.end();
+
+ for (; it != end; ++it) {
+ os << "\\begin{preview}\n"
+ << it->first
+ << "\n\\end{preview}\n\n";
+ }
+}
+
+} // namespace grfx
--- /dev/null
+// -*- C++ -*-
+/**
+ * \file PreviewLoader.h
+ * Copyright 2002 the LyX Team
+ * Read the file COPYING
+ *
+ * \author Angus Leeming <a.leeming@ic.ac.uk>
+ *
+ * grfx::PreviewLoader collects latex snippets together. Then, on a
+ * startLoading() call, these are dumped to file and processed, converting
+ * each snippet to a separate bitmap image file. Once a bitmap file is ready
+ * to be loaded back into LyX, the PreviewLoader emits a readyToDisplay signal
+ * to inform the initiating process.
+ */
+
+#ifndef PREVIEWLOADER_H
+#define PREVIEWLOADER_H
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "LString.h"
+#include <boost/utility.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/signals/signal1.hpp>
+
+class Buffer;
+
+namespace grfx {
+
+class PreviewImage;
+
+class PreviewLoader : boost::noncopyable {
+public:
+ /** We need buffer because we require the preamble to the
+ * LaTeX file.
+ */
+ PreviewLoader(Buffer const & buffer);
+ ///
+ ~PreviewLoader();
+
+ /** Is there an image already associated with this snippet of LaTeX?
+ * If so, returns a pointer to it, else returns 0.
+ */
+ PreviewImage const * preview(string const & latex_snippet) const;
+
+ ///
+ enum Status {
+ ///
+ NotFound,
+ ///
+ InQueue,
+ ///
+ Processing,
+ ///
+ Ready
+ };
+
+ /// How far have we got in loading the image?
+ Status status(string const & latex_snippet) const;
+
+ /// Add a snippet of LaTeX to the queue for processing.
+ void add(string const & latex_snippet);
+
+ /// Remove this snippet of LaTeX from the PreviewLoader.
+ void remove(string const & latex_snippet);
+
+ /** We have accumulated several latex snippets with status "InQueue".
+ * Initiate their transformation into bitmap images.
+ */
+ void startLoading();
+
+ /// Emit this signal when an image is ready for display.
+ boost::signal1<void, PreviewImage const &> imageReady;
+
+private:
+ /// 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 // PREVIEWLOADER_H
--- /dev/null
+/*
+ * \file PreviewMetrics.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 "PreviewMetrics.h"
+
+#include "debug.h"
+#include "lyxlex.h"
+#include "support/lyxlib.h"
+
+
+namespace grfx {
+
+namespace {
+
+keyword_item MetricsTags[] = {
+ { "%%Page", 1 }
+};
+
+} // namespace anon
+
+
+PreviewMetrics::PreviewMetrics(string const & file)
+{
+ LyXLex lex(MetricsTags, 1);
+ lex.setFile(file);
+
+ if (!lex.isOK()) {
+ lyxerr[Debug::GRAPHICS]
+ << "PreviewMetricsFile(" << file << ")\n"
+ << "Unable to open file." << std::endl;
+ return;
+ }
+
+ int line = 0;
+ while (lex.isOK()) {
+
+ int le = lex.lex();
+ switch (le) {
+ case LyXLex::LEX_UNDEF:
+ lex.printError("Unknown tag `$$Token'");
+ continue;
+ case LyXLex::LEX_FEOF:
+ continue;
+ default: break;
+ }
+
+ if (le != 1 || !lex.next())
+ continue;
+
+ int store[7];
+ for (int i = 0; i < 7; ++i) {
+ if (lex.next())
+ store[i] = lex.getInteger();
+ if (lex.isOK())
+ continue;
+
+ lyxerr[Debug::GRAPHICS]
+ << "PreviewMetricsFile(" << file << ")\n"
+ << "Error reading file." << std::endl;
+ break;
+ }
+
+ if (!lex.isOK())
+ break;
+
+ // These 7 numbers are
+ // bb_ll_x bb_ll_y bb_ur_x bb_ur_y ht dp wd
+ // We are interested only in the ratio ht:dp
+ double const a = double(store[4]);
+ double const d = double(store[5]);
+ double const af = a / (a + d);
+ store_.push_back(af);
+ }
+
+ lyx::unlink(file);
+}
+
+
+double PreviewMetrics::ascent_fraction(size_type counter)
+{
+ if (store_.empty() || counter >= store_.size())
+ return 0.5;
+
+ return store_[counter];
+}
+
+
+} // namespace grfx
--- /dev/null
+// -*- C++ -*-
+/**
+ * \file PreviewMetrics.h
+ * Copyright 2002 the LyX Team
+ * Read the file COPYING
+ *
+ * \author Angus Leeming <a.leeming@ic.ac.uk>
+ */
+
+#ifndef PREVIEWMETRICS_H
+#define PREVIEWMETRICS_H
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "LString.h"
+#include <boost/utility.hpp>
+#include <vector>
+
+namespace grfx {
+
+class PreviewMetrics : boost::noncopyable {
+public:
+ ///
+ typedef std::vector<PreviewMetrics>::size_type size_type;
+
+ /// Reads in file and then deletes it.
+ PreviewMetrics(string const & file);
+
+ /** Return the data from the metrics file if found,
+ * or 0.5
+ */
+ double ascent_fraction(size_type);
+
+private:
+ ///
+ std::vector<double> store_;
+};
+
+} // namespace grfx
+
+#endif // PREVIEWMETRICS_H
--- /dev/null
+/*
+ * \file Previews.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 "Previews.h"
+#include "PreviewLoader.h"
+
+#include "buffer.h"
+#include "lyxrc.h"
+
+#include "insets/inset.h"
+
+#include "support/LAssert.h"
+
+#include <map>
+
+
+namespace grfx {
+
+bool Previews::activated()
+{
+ return lyxrc.preview;
+}
+
+
+Previews & Previews::get()
+{
+ static Previews singleton;
+ return singleton;
+}
+
+
+struct Previews::Impl {
+ ///
+ typedef boost::shared_ptr<PreviewLoader> PreviewLoaderPtr;
+ ///
+ typedef std::map<Buffer *, PreviewLoaderPtr> CacheType;
+ ///
+ CacheType cache;
+};
+
+
+Previews::Previews()
+ : pimpl_(new Impl())
+{}
+
+
+Previews::~Previews()
+{}
+
+
+PreviewLoader & Previews::loader(Buffer * buffer)
+{
+ lyx::Assert(buffer);
+
+ Impl::CacheType::iterator it = pimpl_->cache.find(buffer);
+
+ if (it == pimpl_->cache.end()) {
+ Impl::PreviewLoaderPtr ptr(new PreviewLoader(*buffer));
+ pimpl_->cache[buffer] = ptr;
+ return *ptr.get();
+ }
+
+ return *it->second.get();
+}
+
+
+void Previews::removeLoader(Buffer * buffer)
+{
+ if (!buffer)
+ return;
+
+ Impl::CacheType::iterator it = pimpl_->cache.find(buffer);
+
+ if (it != pimpl_->cache.end())
+ pimpl_->cache.erase(it);
+}
+
+
+void Previews::generateBufferPreviews(Buffer * buffer)
+{
+ if (!buffer || !lyxrc.preview)
+ return;
+
+ PreviewLoader & ploader = loader(buffer);
+
+ Buffer::inset_iterator it = buffer->inset_const_iterator_begin();
+ Buffer::inset_iterator end = buffer->inset_const_iterator_end();
+
+ for (; it != end; ++it) {
+ if ((*it)->lyxCode() == Inset::MATH_CODE) {
+ (*it)->generatePreview(ploader);
+ }
+ }
+
+ ploader.startLoading();
+}
+
+} // namespace grfx
--- /dev/null
+// -*- C++ -*-
+/**
+ * \file Previews.h
+ * Copyright 2002 the LyX Team
+ * Read the file COPYING
+ *
+ * \author Angus Leeming <a.leeming@ic.ac.uk>
+ *
+ * grfx::Previews is a singleton class that stores the grfx::PreviewLoader
+ * for each buffer requiring one.
+ */
+
+#ifndef PREVIEWS_H
+#define PREVIEWS_H
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "LString.h"
+#include <boost/utility.hpp>
+#include <boost/scoped_ptr.hpp>
+
+class Buffer;
+
+namespace grfx {
+
+class PreviewLoader;
+
+class Previews : boost::noncopyable {
+public:
+ /// a wrapper for lyxrc.preview
+ static bool activated();
+
+ /// This is a singleton class. Get the instance.
+ static Previews & get();
+
+ /** Returns the PreviewLoader for this buffer.
+ * Used by individual insets to update their own preview.
+ * We assert that (buffer != 0) but do not pass a Buffer &
+ * so that insets do not need to #include buffer.h
+ */
+ PreviewLoader & loader(Buffer * buffer);
+
+ /** Called from the Buffer d-tor.
+ * If (buffer == 0), does nothing.
+ */
+ void removeLoader(Buffer * buffer);
+
+ /** For a particular buffer, initiate the generation of previews
+ * for each and every snippetof LaTeX that's of interest with
+ * a single forked process.
+ * If (buffer == 0), does nothing.
+ */
+ void generateBufferPreviews(Buffer * buffer);
+
+private:
+ /** Make the c-tor, d-tor private so we can control how many objects
+ * are instantiated.
+ */
+ Previews();
+ ///
+ ~Previews();
+
+ /// 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 // PREVIEWS_H
+2002-07-05 Angus Leeming <leeming@lyx.org>
+
+ * inset.h (generatePreview): new virtual method.
+
2002-07-04 Lars Gullik Bjønnes <larsbj@birdstep.com>
* insetcommandparams.[Ch] (operator=): move out of class
struct LaTeXFeatures;
+namespace grfx {
+ class PreviewLoader;
+}
/// Insets
class Inset {
minipage somewhere, it will be the width of this minipage */
virtual int latexTextWidth(BufferView *) const;
+ /** Adds a LaTeX snippet to the Preview Loader for transformation
+ * into a bitmap image. Also connects to PreviewLoader::imageReady
+ * so that the inset is informed when the image has been generated
+ * in order to initiate its loading into LyX.
+ *
+ * Most insets have no interest in this capability, so the method
+ * defaults to empty.
+ */
+ virtual void generatePreview(grfx::PreviewLoader &) const {}
+
protected:
///
mutable int top_x;
+2002-07-05 Angus Leeming <leeming@lyx.org>
+
+ * formula.[Ch] (generatePreview): instantiate new virtual method.
+ Strip out the preliminary preview code and replace with new that
+ makes full use of the graphics/Preview* files. Hide all the shenanigans
+ behind a PreviewImpl firewall.
+
+ * math_nestinset.C (notifyCursorLeaves): update the preview using the
+ new graphics/Preview* code.
+
2002-07-04 Lars Gullik Bjønnes <larsbj@birdstep.com>
* formulabase.C: ws changes
#include "math_charinset.h"
#include "math_arrayinset.h"
#include "math_deliminset.h"
+#include "math_hullinset.h"
+#include "math_support.h"
+#include "math_mathmlstream.h"
+#include "textpainter.h"
+
#include "lyx_main.h"
#include "BufferView.h"
#include "gettext.h"
#include "debug.h"
+#include "lyxrc.h"
+
#include "support/LOstream.h"
#include "support/LAssert.h"
#include "support/lyxlib.h"
#include "support/systemcall.h"
#include "support/filetools.h"
+
#include "frontends/Alert.h"
#include "frontends/LyXView.h"
#include "frontends/Painter.h"
+
#include "graphics/GraphicsImage.h"
-#include "lyxrc.h"
-#include "math_hullinset.h"
-#include "math_support.h"
-#include "math_mathmlstream.h"
-#include "textpainter.h"
+#include "graphics/PreviewLoader.h"
+#include "graphics/PreviewImage.h"
+#include "graphics/Previews.h"
#include <fstream>
#include <boost/bind.hpp>
+#include <boost/signals/trackable.hpp>
+#include <boost/signals/connection.hpp>
#include <boost/utility.hpp>
using std::ostream;
using std::getline;
+struct InsetFormula::PreviewImpl : public boost::signals::trackable {
+ ///
+ PreviewImpl(InsetFormula & p) : parent_(p), pimage_(0) {}
+
+ ///
+ void generatePreview(grfx::PreviewLoader & previewer);
+
+ /** This method is connected to the grfx::PreviewLoader::imageReady
+ * signal.
+ */
+ void previewReady(grfx::PreviewImage const &);
+
+ /// A helper method.
+ string const latexString() const;
+
+ ///
+ bool usePreview() const;
+
+ ///
+ InsetFormula & parent_;
+ ///
+ mutable grfx::PreviewImage const * pimage_;
+ ///
+ boost::signals::connection connection_;
+};
+
+
InsetFormula::InsetFormula()
- : par_(MathAtom(new MathHullInset)), loader_(0)
+ : par_(MathAtom(new MathHullInset)),
+ preview_(new PreviewImpl(*this))
+{}
+
+
+InsetFormula::InsetFormula(InsetFormula const & other)
+ : par_(other.par_),
+ preview_(new PreviewImpl(*this))
{}
InsetFormula::InsetFormula(BufferView * bv)
- : par_(MathAtom(new MathHullInset)), loader_(0)
+ : par_(MathAtom(new MathHullInset)),
+ preview_(new PreviewImpl(*this))
{
view_ = bv;
}
InsetFormula::InsetFormula(string const & data)
- : par_(MathAtom(new MathHullInset)), loader_(0)
+ : par_(MathAtom(new MathHullInset)),
+ preview_(new PreviewImpl(*this))
{
if (!data.size())
return;
+InsetFormula::~InsetFormula()
+{}
+
+
Inset * InsetFormula::clone(Buffer const &, bool) const
{
return new InsetFormula(*this);
MathPainterInfo pi(bv->painter());
- if (canPreview()) {
- pi.pain.image(x + 1, y - a + 1, w - 2, h - 2, *(loader_->image()));
+ if (preview_->usePreview()) {
+ pi.pain.image(x + 1, y - a + 1, w - 2, h - 2,
+ *(preview_->pimage_->image()));
} else {
//pi.base.style = display() ? LM_ST_DISPLAY : LM_ST_TEXT;
pi.base.style = LM_ST_TEXT;
int InsetFormula::ascent(BufferView *, LyXFont const &) const
{
- const int a = par_->ascent();
- if (!canPreview())
- return a + 1;
- return a + 1 - (par_->height() - loader_->image()->getHeight()) / 2;
+ return preview_->usePreview() ?
+ 1 + preview_->pimage_->ascent() : 1 + par_->ascent();
}
int InsetFormula::descent(BufferView *, LyXFont const &) const
{
- const int d = par_->descent();
- if (!canPreview())
- return d + 1;
- return d + 1 - (par_->height() - loader_->image()->getHeight()) / 2;
+ return preview_->usePreview() ?
+ 1 + preview_->pimage_->descent() : 1 + par_->descent();
}
int InsetFormula::width(BufferView * bv, LyXFont const & font) const
{
metrics(bv, font);
- return canPreview() ? loader_->image()->getWidth() : par_->width();
+ return preview_->usePreview() ?
+ preview_->pimage_->width() : par_->width();
}
// preview stuff
//
-bool InsetFormula::canPreview() const
+void InsetFormula::generatePreview(grfx::PreviewLoader & ploader) const
{
- return lyxrc.preview && loader_ && !par_->asNestInset()->editing()
- && loader_->status() == grfx::Ready;
+ // Do nothing if no preview is desired.
+ if (!grfx::Previews::activated())
+ return;
+
+ preview_->generatePreview(ploader);
}
-void InsetFormula::statusChanged()
+void InsetFormula::PreviewImpl::generatePreview(grfx::PreviewLoader & ploader)
{
- lyxerr << "### InsetFormula::statusChanged called!, status: "
- << loader_->status() << "\n";
- if (loader_->status() == grfx::Ready)
- view()->updateInset(this, false);
- else if (loader_->status() == grfx::WaitingToLoad)
- loader_->startLoading();
+ // Generate the LaTeX snippet.
+ string const snippet = latexString();
+
+ pimage_ = ploader.preview(snippet);
+ if (pimage_)
+ return;
+
+ // If this is the first time of calling, connect to the
+ // grfx::PreviewLoader signal that'll inform us when the preview image
+ // is ready for loading.
+ if (!connection_.connected()) {
+ connection_ = ploader.imageReady.connect(
+ boost::bind(&PreviewImpl::previewReady, this, _1));
+ }
+
+ ploader.add(snippet);
}
-void InsetFormula::updatePreview()
+bool InsetFormula::PreviewImpl::usePreview() const
{
- // nothing to be done if no preview requested
- lyxerr << "### updatePreview() called\n";
- if (!lyxrc.preview)
- return;
+ BufferView * view = parent_.view();
+
+ if (!grfx::Previews::activated() ||
+ parent_.par_->asNestInset()->editing() ||
+ !view || !view->buffer())
+ return false;
+
+ // If the cached grfx::PreviewImage is invalid, update it.
+ string const snippet = latexString();
+ if (!pimage_ || snippet != pimage_->snippet()) {
+ grfx::PreviewLoader & ploader =
+ grfx::Previews::get().loader(view->buffer());
+ pimage_ = ploader.preview(snippet);
+ }
- // get LaTeX
+ if (!pimage_)
+ return false;
+
+ return pimage_->image();
+}
+
+
+string const InsetFormula::PreviewImpl::latexString() const
+{
ostringstream ls;
WriteStream wi(ls, false, false);
- par_->write(wi);
- string const data = ls.str();
-
- // the preview cache, maps contents to image loaders
- typedef std::map<string, boost::shared_ptr<grfx::Loader> > cache_type;
- static cache_type theCache;
- static int theCounter = 0;
-
- // set our loader corresponding to our current data
- cache_type::const_iterator it = theCache.find(data);
-
- // is this old data?
- if (it != theCache.end()) {
- // we have already a loader, connect to it anyway
- //lyxerr << "### updatePreview(), old loader: " << loader_ << "\n";
- loader_ = it->second.get();
- loader_->statusChanged.connect
- (boost::bind(&InsetFormula::statusChanged, this));
+ parent_.par_->write(wi);
+ return ls.str().c_str();
+}
+
+
+void InsetFormula::PreviewImpl::previewReady(grfx::PreviewImage const & pimage)
+{
+ // Check snippet against the Inset's current contents
+ if (latexString() != pimage.snippet())
return;
- }
- // construct new file name
- static string const dir = OnlyPath(lyx::tempName());
- ostringstream os;
- os << dir << theCounter++ << ".lyxpreview";
- string file = os.str();
-
- // the real work starts
- //lyxerr << "### updatePreview(), new file " << file << "\n";
- std::ofstream of(file.c_str());
- of << "\\batchmode"
- << "\\documentclass{article}"
- << "\\usepackage{amssymb}"
- << "\\thispagestyle{empty}"
- << "\\pdfoutput=0"
- << "\\begin{document}"
- << data
- << "\\end{document}\n";
- of.close();
-
- // now we are done, start actual loading we will get called back via
- // InsetFormula::statusChanged() if this is finished
- theCache[data].reset(new grfx::Loader(file));
- //lyxerr << "### updatePreview(), new loader: " << loader_ << "\n";
- loader_ = theCache.find(data)->second.get();
- loader_->startLoading();
- loader_->statusChanged.connect(boost::bind(&InsetFormula::statusChanged, this));
+ pimage_ = &pimage;
+ BufferView * view = parent_.view();
+ if (view)
+ view->updateInset(&parent_, false);
}
#include "formulabase.h"
#include "math_atom.h"
-#include "graphics/GraphicsTypes.h"
-#include "graphics/GraphicsLoader.h"
+
+#include <boost/scoped_ptr.hpp>
class MathHullInset;
///
explicit InsetFormula(const string & data);
///
+ InsetFormula(InsetFormula const &);
+ ///
+ ~InsetFormula();
+ ///
int ascent(BufferView *, LyXFont const &) const;
///
int descent(BufferView *, LyXFont const &) const;
///
MathAtom & par() { return par_; }
///
+ void generatePreview(grfx::PreviewLoader &) const;
+ ///
void mutate(string const & type);
private:
MathHullInset const * hull() const;
///
void handleExtern(string const & arg);
- ///
- void statusChanged();
- ///
- void updatePreview();
- ///
- bool canPreview() const;
/// contents
MathAtom par_;
- /// non owning pointer
- mutable grfx::Loader * loader_;
+
+ /// Use the Pimpl idiom to hide the internals of the previewer.
+ class PreviewImpl;
+ friend class PreviewImpl;
+ /// The pointer never changes although *preview_'s contents may.
+ boost::scoped_ptr<PreviewImpl> const preview_;
};
#endif
#include "math_cursor.h"
#include "math_mathmlstream.h"
#include "formulabase.h"
+#include "BufferView.h"
#include "debug.h"
#include "frontends/Painter.h"
+#include "graphics/PreviewLoader.h"
+#include "graphics/Previews.h"
MathNestInset::MathNestInset(idx_type nargs)
void MathNestInset::notifyCursorLeaves()
{
//lyxerr << "leaving " << *this << "\n";
- if (mathcursor)
- mathcursor->formula()->updatePreview();
+ if (!mathcursor || !grfx::Previews::activated())
+ return;
+
+ InsetFormulaBase * inset = mathcursor->formula();
+ BufferView * bufferview = inset->view();
+ if (!bufferview || !bufferview->buffer())
+ return;
+
+ grfx::Previews & previews = grfx::Previews::get();
+ grfx::PreviewLoader & loader = previews.loader(bufferview->buffer());
+
+ inset->generatePreview(loader);
+ loader.startLoading();
}