Fix bug #9354 (Preview inset does not work with math macros)

The patch also makes sure that only the macros actually used in a
math inset are included in the preview snippet. In this way, the
size of the tex file used for generating the previews does not
explode in the presence of lots of macros.
This commit is contained in:
Enrico Forestieri 2015-06-09 20:07:48 +02:00
parent 558100ad58
commit 4c92d969eb
6 changed files with 107 additions and 14 deletions

View File

@ -25,6 +25,9 @@
#include "graphics/PreviewImage.h"
#include "mathed/InsetMathHull.h"
#include "mathed/MacroTable.h"
#include <sstream>
using namespace std;
@ -74,7 +77,32 @@ void InsetPreview::preparePreview(DocIterator const & pos) const
otexstream os(str, texrow);
OutputParams runparams(&pos.buffer()->params().encoding());
latex(os, runparams);
docstring const snippet = str.str();
// collect macros at this position
MacroNameSet macros;
pos.buffer()->listMacroNames(macros);
// look for math insets and collect definitions for the used macros
MacroNameSet defs;
DocIterator dit = doc_iterator_begin(pos.buffer(), this);
DocIterator const dend = doc_iterator_end(pos.buffer(), this);
if (!dit.nextInset())
dit.forwardInset();
for (; dit != dend; dit.forwardInset()) {
InsetMath * im = dit.nextInset()->asInsetMath();
InsetMathHull * hull = im ? im->asHullInset() : 0;
if (!hull)
continue;
for (idx_type idx = 0; idx < hull->nargs(); ++idx)
hull->usedMacros(hull->cell(idx), pos, macros, defs);
}
MacroNameSet::iterator it = defs.begin();
MacroNameSet::iterator end = defs.end();
docstring macro_preamble;
for (; it != end; ++it)
macro_preamble.append(*it);
docstring const snippet = macro_preamble + str.str();
preview_->addPreview(snippet, *pos.buffer());
}

View File

@ -58,6 +58,7 @@ class InsetMathAMSArray;
class InsetMathBrace;
class InsetMathChar;
class InsetMathDelim;
class InsetMathFracBase;
class InsetMathFrac;
class InsetMathFont;
class InsetMathGrid;
@ -129,6 +130,8 @@ public:
virtual InsetMathChar const * asCharInset() const { return 0; }
virtual InsetMathDelim * asDelimInset() { return 0; }
virtual InsetMathDelim const * asDelimInset() const { return 0; }
virtual InsetMathFracBase * asFracBaseInset() { return 0; }
virtual InsetMathFracBase const * asFracBaseInset() const { return 0; }
virtual InsetMathFrac * asFracInset() { return 0; }
virtual InsetMathFrac const * asFracInset() const { return 0; }
virtual InsetMathFont * asFontInset() { return 0; }

View File

@ -30,6 +30,10 @@ public:
bool idxBackward(Cursor &) const { return false; }
///
bool idxForward(Cursor &) const { return false; }
///
InsetMathFracBase * asFracBaseInset() { return this; }
///
InsetMathFracBase const * asFracBaseInset() const { return this; }
};

View File

@ -14,6 +14,10 @@
#include "InsetMathChar.h"
#include "InsetMathColor.h"
#include "InsetMathFrac.h"
#include "InsetMathGrid.h"
#include "InsetMathNest.h"
#include "InsetMathScript.h"
#include "MathExtern.h"
#include "MathFactory.h"
#include "MathStream.h"
@ -32,6 +36,7 @@
#include "LaTeXFeatures.h"
#include "LyXRC.h"
#include "MacroTable.h"
#include "MathMacro.h"
#include "output_xhtml.h"
#include "Paragraph.h"
#include "ParIterator.h"
@ -622,6 +627,55 @@ void InsetMathHull::addPreview(DocIterator const & inset_pos,
}
void InsetMathHull::usedMacros(MathData const & md, DocIterator const & pos,
MacroNameSet & macros, MacroNameSet & defs) const
{
MacroNameSet::iterator const end = macros.end();
for (size_t i = 0; i < md.size(); ++i) {
MathMacro const * mi = md[i].nucleus()->asMacro();
InsetMathScript const * si = md[i].nucleus()->asScriptInset();
InsetMathFracBase const * fi = md[i].nucleus()->asFracBaseInset();
InsetMathGrid const * gi = md[i].nucleus()->asGridInset();
InsetMathNest const * ni = md[i].nucleus()->asNestInset();
if (mi) {
// Make sure this is a macro defined in the document
// (as we also spot the macros in the symbols file)
// or that we have not already accounted for it.
docstring const name = mi->name();
if (macros.find(name) == end)
continue;
macros.erase(name);
MathData ar(pos.buffer());
MacroData const * data =
pos.buffer()->getMacro(name, pos, true);
if (data) {
odocstringstream macro_def;
data->write(macro_def, true);
macro_def << endl;
defs.insert(macro_def.str());
asArray(data->definition(), ar);
}
usedMacros(ar, pos, macros, defs);
} else if (si) {
if (!si->nuc().empty())
usedMacros(si->nuc(), pos, macros, defs);
if (si->hasDown())
usedMacros(si->down(), pos, macros, defs);
if (si->hasUp())
usedMacros(si->up(), pos, macros, defs);
} else if (fi || gi) {
idx_type nidx = fi ? fi->nargs() : gi->nargs();
for (idx_type idx = 0; idx < nidx; ++idx)
usedMacros(fi ? fi->cell(idx) : gi->cell(idx),
pos, macros, defs);
} else if (ni) {
usedMacros(ni->cell(0), pos, macros, defs);
}
}
}
void InsetMathHull::preparePreview(DocIterator const & pos,
bool forexport) const
{
@ -635,16 +689,17 @@ void InsetMathHull::preparePreview(DocIterator const & pos,
// collect macros at this position
MacroNameSet macros;
buffer->listMacroNames(macros);
MacroNameSet::iterator it = macros.begin();
MacroNameSet::iterator end = macros.end();
odocstringstream macro_preamble;
for (; it != end; ++it) {
MacroData const * data = buffer->getMacro(*it, pos, true);
if (data) {
data->write(macro_preamble, true);
macro_preamble << endl;
}
}
// collect definitions only for the macros used in this inset
MacroNameSet defs;
for (idx_type idx = 0; idx < nargs(); ++idx)
usedMacros(cell(idx), pos, macros, defs);
MacroNameSet::iterator it = defs.begin();
MacroNameSet::iterator end = defs.end();
docstring macro_preamble;
for (; it != end; ++it)
macro_preamble.append(*it);
docstring setcnt;
if (forexport && haveNumbers()) {
@ -667,8 +722,7 @@ void InsetMathHull::preparePreview(DocIterator const & pos,
'{' + convert<docstring>(num) + '}';
}
}
docstring const snippet = macro_preamble.str() +
setcnt + latexString(*this);
docstring const snippet = macro_preamble + setcnt + latexString(*this);
LYXERR(Debug::MACROS, "Preview snippet: " << snippet);
preview_->addPreview(snippet, *buffer, forexport);
}

View File

@ -23,6 +23,7 @@
namespace lyx {
class InsetLabel;
class MacroNameSet;
class ParConstIterator;
class RenderPreview;
@ -152,6 +153,9 @@ public:
/// Recreates the preview if preview is enabled.
void reloadPreview(DocIterator const & pos) const;
///
void usedMacros(MathData const & md, DocIterator const & pos,
MacroNameSet & macros, MacroNameSet & defs) const;
///
void initUnicodeMath() const;
///

View File

@ -135,7 +135,7 @@ What's new
- Fix test for urwclassico font (bug 9576).
- Fix issues with instant preview and math macros (bug 6369).
- Fix issues with instant preview and math macros (bugs 6369 and 9354).
- Fix instant preview for the Math manual (bug 9508).