Centralize code to markup deleted complex objects (with tikz) in output

This fixes #9293
This commit is contained in:
Juergen Spitzmueller 2019-12-28 13:43:17 +01:00
parent f686a97fd8
commit 89b5607e0a
14 changed files with 201 additions and 50 deletions

View File

@ -435,6 +435,7 @@
\TestPackage{tcolorbox} \TestPackage{tcolorbox}
\TestPackage{textcomp} \TestPackage{textcomp}
\TestPackage{thswitch} \TestPackage{thswitch}
\TestPackage{tikz}
\TestPackage[turkmen.ldf]{turkmen} \TestPackage[turkmen.ldf]{turkmen}
\TestPackage{ulem} \TestPackage{ulem}
\TestPackage{undertilde} \TestPackage{undertilde}

View File

@ -434,9 +434,11 @@ int Changes::latexMarkChange(otexstream & os, BufferParams const & bparams,
|| runparams.flavor == OutputParams::DVILUATEX); || runparams.flavor == OutputParams::DVILUATEX);
if (oldChange.type != Change::UNCHANGED) { if (oldChange.type != Change::UNCHANGED) {
if (oldChange.type != Change::DELETED || runparams.ctObject != OutputParams::CT_OMITOBJECT) {
// close \lyxadded or \lyxdeleted // close \lyxadded or \lyxdeleted
os << '}'; os << '}';
column++; column++;
}
if (oldChange.type == Change::DELETED if (oldChange.type == Change::DELETED
&& !runparams.wasDisplayMath && !dvipost) && !runparams.wasDisplayMath && !dvipost)
--runparams.inulemcmd; --runparams.inulemcmd;
@ -449,10 +451,20 @@ int Changes::latexMarkChange(otexstream & os, BufferParams const & bparams,
docstring macro_beg; docstring macro_beg;
if (change.type == Change::DELETED) { if (change.type == Change::DELETED) {
if (runparams.ctObject == OutputParams::CT_OMITOBJECT)
return 0;
else if (runparams.ctObject == OutputParams::CT_OBJECT)
macro_beg = from_ascii("\\lyxobjdeleted");
else if (runparams.ctObject == OutputParams::CT_DISPLAYOBJECT)
macro_beg = from_ascii("\\lyxdisplayobjdeleted");
else if (runparams.ctObject == OutputParams::CT_UDISPLAYOBJECT)
macro_beg = from_ascii("\\lyxudisplayobjdeleted");
else {
macro_beg = from_ascii("\\lyxdeleted"); macro_beg = from_ascii("\\lyxdeleted");
if (!runparams.inDisplayMath && !dvipost) if (!runparams.inDisplayMath && !dvipost)
++runparams.inulemcmd; ++runparams.inulemcmd;
} }
}
else if (change.type == Change::INSERTED) else if (change.type == Change::INSERTED)
macro_beg = from_ascii("\\lyxadded"); macro_beg = from_ascii("\\lyxadded");
@ -460,15 +472,6 @@ int Changes::latexMarkChange(otexstream & os, BufferParams const & bparams,
bparams.authors().get(change.author), bparams.authors().get(change.author),
chgTime, runparams); chgTime, runparams);
// signature needed by \lyxsout to correctly strike out display math
if (change.type == Change::DELETED && runparams.inDisplayMath
&& !dvipost) {
if (os.blankLine())
str += from_ascii("\\\\\\noindent\n");
else
str += from_ascii("\\\\\\\\\n");
}
os << str; os << str;
column += str.size(); column += str.size();

View File

@ -298,21 +298,83 @@ static docstring const changetracking_xcolor_ulem_hyperref_cb_def = from_ascii(
static docstring const changetracking_tikz_object_sout_def = from_ascii( static docstring const changetracking_tikz_object_sout_def = from_ascii(
"%% Strike out display math and text objects with tikz\n" "%% Strike out display math and text objects with tikz\n"
"\\usepackage{tikz}\n"
"\\usetikzlibrary{calc}\n" "\\usetikzlibrary{calc}\n"
"\\newcommand{\\lyxobjectsout}[1]{%\n" "\\newcommand{\\lyxobjectsout}[1]{%\n"
" \\bgroup%\n" " \\bgroup%\n"
" \\color{lyxdeleted}%\n" " \\color{lyxdeleted}%\n"
" \\tikz[baseline=(obj.base)]{\n" " \\tikz{\n"
" \\node[inner sep=0pt,outer sep=0pt](obj){#1};\n" " \\node[inner sep=0pt,outer sep=0pt](lyxdelobj){#1};\n"
" \\draw($(obj.south west)+(2em,.5em)$)--($(obj.north east)-(2em,.5em)$);\n" " \\draw($(lyxdelobj.south west)+(2em,.5em)$)--($(lyxdelobj.north east)-(2em,.5em)$);\n"
" }\n" " }\n"
" \\egroup%\n" " \\egroup%\n"
"}\n"); "}\n");
static docstring const changetracking_xcolor_ulem_object_def = from_ascii(
"%% Change tracking with ulem and xcolor: ct markup for complex objects\n"
"\\DeclareRobustCommand{\\lyxobjdeleted}[4][]{\\lyxobjectsout{#4}}\n"
"\\DeclareRobustCommand{\\lyxdisplayobjdeleted}[4][]{\\lyxobjectsout{\\parbox{\\linewidth}{#4}}}\n"
"\\DeclareRobustCommand{\\lyxudisplayobjdeleted}[4][]{%\n"
" \\raisebox{-\\belowdisplayshortskip}{%\n"
" \\lyxobjectsout{\\parbox[b]{\\linewidth}{#4}}}%\n"
"}\n");
static docstring const changetracking_xcolor_ulem_cb_object_def = from_ascii(
"%% Change tracking with ulem, xcolor and changebars:ct markup for complex objects\n"
"\\DeclareRobustCommand{\\lyxobjdeleted}[4][]{%\n"
" \\protect\\cbstart\\lyxobjectsout{#4}%\n"
" \\protect\\cbend%\n"
"}\n"
"\\DeclareRobustCommand{\\lyxdisplayobjdeleted}[4][]{%\n"
" \\protect\\cbstart%\n"
" \\lyxobjectsout{\\parbox{\\linewidth}{#4}}%\n"
" \\protect\\cbend%\n"
"}\n"
"\\DeclareRobustCommand{\\lyxudisplayobjdeleted}[4][]{%\n"
" \\raisebox{-\\belowdisplayshortskip}{%\n"
" \\protect\\cbstart%\n"
" \\lyxobjectsout{\\parbox[b]{\\linewidth}{#4}}}%\n"
" \\protect\\cbend%\n"
"}\n");
static docstring const changetracking_xcolor_ulem_hyperref_object_def = from_ascii(
"%% Change tracking with ulem, xcolor, and hyperref: ct markup for complex objects\n"
"\\DeclareRobustCommand{\\lyxobjdeleted}[4][]{\\texorpdfstring{\\lyxobjectsout{#4}}{}}\n"
"\\DeclareRobustCommand{\\lyxdisplayobjdeleted}[4][]{%\n"
" \\texorpdfstring{\\lyxobjectsout{\\parbox{\\linewidth}{#4}}}{}%\n"
"}\n"
"\\DeclareRobustCommand{\\lyxudisplayobjdeleted}[4][]{%\n"
" \\texorpdfstring{\\raisebox{-\\belowdisplayshortskip}{%\n"
" \\lyxobjectsout{\\parbox[b]{\\linewidth}{#4}}}}{}%\n"
"}\n");
static docstring const changetracking_xcolor_ulem_hyperref_cb_object_def = from_ascii(
"%% Change tracking with ulem, xcolor, hyperref and changebars:\n"
"%% ct markup for complex objects\n"
"\\DeclareRobustCommand{\\lyxobjdeleted}[4][]{%\n"
" \\texorpdfstring{\\protect\\cbstart\\lyxobjectsout{#4}%\n"
" \\protect\\cbend}{}%\n"
"}\n"
"\\DeclareRobustCommand{\\lyxdisplayobjdeleted}[4][]{%\n"
" \\texorpdfstring{\\protect\\cbstart%\n"
" \\lyxobjectsout{\\parbox{\\linewidth}{#4}}%\n"
" \\protect\\cbend%\n"
" }{}%\n"
"}\n"
"\\DeclareRobustCommand{\\lyxudisplayobjdeleted}[4][]{%\n"
" \\texorpdfstring{\\protect\\cbstart%\n"
" \\raisebox{-\\belowdisplayshortskip}{%\n"
" \\lyxobjectsout{\\parbox[b]{\\linewidth}{#4}}%\n"
" }%\n"
" }{}%\n"
"}\n");
static docstring const changetracking_none_def = from_ascii( static docstring const changetracking_none_def = from_ascii(
"%% Change tracking: Disable markup in output\n"
"\\newcommand{\\lyxadded}[3]{#3}\n" "\\newcommand{\\lyxadded}[3]{#3}\n"
"\\newcommand{\\lyxdeleted}[3]{}\n"); "\\newcommand{\\lyxdeleted}[3]{}\n"
"\\newcommand{\\lyxobjdeleted}[3]{}\n"
"\\newcommand{\\lyxdisplayobjdeleted}[3]{}\n"
"\\newcommand{\\lyxudisplayobjdeleted}[3]{}\n");
static docstring const textgreek_LGR_def = from_ascii( static docstring const textgreek_LGR_def = from_ascii(
"\\DeclareFontEncoding{LGR}{}{}\n"); "\\DeclareFontEncoding{LGR}{}{}\n");
@ -1089,6 +1151,7 @@ char const * simplefeatures[] = {
"tablefootnote", "tablefootnote",
"afterpage", "afterpage",
"tabularx", "tabularx",
"tikz",
"xltabular", "xltabular",
"chessboard", "chessboard",
"xskak", "xskak",
@ -1695,9 +1758,36 @@ TexString LaTeXFeatures::getMacros() const
} }
} }
if (mustProvide("ct-tikz-object-sout")) if (mustProvide("ct-tikz-object-sout")) {
if (!mustProvide("ct-xcolor-ulem")) {
streamsize const prec = macros.os().precision(2);
RGBColor cadd = rgbFromHexName(lcolor.getX11Name(Color_addedtext));
macros << "\\providecolor{lyxadded}{rgb}{"
<< cadd.r / 255.0 << ',' << cadd.g / 255.0 << ',' << cadd.b / 255.0 << "}\n";
RGBColor cdel = rgbFromHexName(lcolor.getX11Name(Color_deletedtext));
macros << "\\providecolor{lyxdeleted}{rgb}{"
<< cdel.r / 255.0 << ',' << cdel.g / 255.0 << ',' << cdel.b / 255.0 << "}\n";
macros.os().precision(prec);
}
macros << changetracking_tikz_object_sout_def; macros << changetracking_tikz_object_sout_def;
if (isRequired("changebar")) {
if (isRequired("hyperref"))
macros << changetracking_xcolor_ulem_hyperref_cb_object_def;
else
macros << changetracking_xcolor_ulem_cb_object_def;
} else {
if (isRequired("hyperref"))
macros << changetracking_xcolor_ulem_hyperref_object_def;
else
macros << changetracking_xcolor_ulem_object_def;
}
}
if (mustProvide("ct-none")) if (mustProvide("ct-none"))
macros << changetracking_none_def; macros << changetracking_none_def;

View File

@ -28,7 +28,7 @@ OutputParams::OutputParams(Encoding const * enc)
wasDisplayMath(false), inComment(false), openbtUnit(false), only_childbibs(false), wasDisplayMath(false), inComment(false), openbtUnit(false), only_childbibs(false),
inTableCell(NO), inFloat(NONFLOAT), inTableCell(NO), inFloat(NONFLOAT),
inIndexEntry(false), inIPA(false), inDeletedInset(0), inIndexEntry(false), inIPA(false), inDeletedInset(0),
changeOfDeletedInset(Change::UNCHANGED), changeOfDeletedInset(Change::UNCHANGED), ctObject(CT_NORMAL),
par_begin(0), par_end(0), lastid(-1), lastpos(0), isLastPar(false), par_begin(0), par_end(0), lastid(-1), lastpos(0), isLastPar(false),
dryrun(false), silent(false), pass_thru(false), dryrun(false), silent(false), pass_thru(false),
html_disable_captions(false), html_in_par(false), html_disable_captions(false), html_in_par(false),

View File

@ -60,6 +60,14 @@ public:
SUBFLOAT SUBFLOAT
}; };
enum CtObject {
CT_NORMAL,
CT_OBJECT,
CT_DISPLAYOBJECT,
CT_UDISPLAYOBJECT,
CT_OMITOBJECT
};
OutputParams(Encoding const *); OutputParams(Encoding const *);
~OutputParams(); ~OutputParams();
@ -280,6 +288,11 @@ public:
*/ */
Change changeOfDeletedInset; Change changeOfDeletedInset;
/** What kind of change tracking object is this?
* Relevant for strikeout method in output
*/
mutable CtObject ctObject;
/** allow output of only part of the top-level paragraphs /** allow output of only part of the top-level paragraphs
* par_begin: beginning paragraph * par_begin: beginning paragraph
*/ */

View File

@ -2477,9 +2477,14 @@ void Paragraph::latex(BufferParams const & bparams,
Change const & change = runparams.inDeletedInset Change const & change = runparams.inDeletedInset
? runparams.changeOfDeletedInset : lookupChange(i); ? runparams.changeOfDeletedInset : lookupChange(i);
char_type const c = d->text_[i];
// Check whether a display math inset follows // Check whether a display math inset follows
if (d->text_[i] == META_INSET if (c == META_INSET
&& i >= start_pos && (end_pos == -1 || i < end_pos)) { && i >= start_pos && (end_pos == -1 || i < end_pos)) {
if (isDeleted(i))
runparams.ctObject = getInset(i)->CtObject(runparams);
InsetMath const * im = getInset(i)->asInsetMath(); InsetMath const * im = getInset(i)->asInsetMath();
if (im && im->asHullInset() if (im && im->asHullInset()
&& im->asHullInset()->outerDisplay()) { && im->asHullInset()->outerDisplay()) {
@ -2593,8 +2598,6 @@ void Paragraph::latex(BufferParams const & bparams,
} }
} }
char_type const c = d->text_[i];
// A display math inset inside an ulem command will be output // A display math inset inside an ulem command will be output
// as a box of width \linewidth, so we have to either disable // as a box of width \linewidth, so we have to either disable
// indentation if the inset starts a paragraph, or start a new // indentation if the inset starts a paragraph, or start a new

View File

@ -20,6 +20,7 @@
#include "InsetLayout.h" #include "InsetLayout.h"
#include "LayoutEnums.h" #include "LayoutEnums.h"
#include "OutputEnums.h" #include "OutputEnums.h"
#include "OutputParams.h"
#include "support/strfwd.h" #include "support/strfwd.h"
#include "support/types.h" #include "support/types.h"
@ -471,6 +472,8 @@ public:
/// does this inset try to use all available space (like \\hfill does)? /// does this inset try to use all available space (like \\hfill does)?
virtual bool isHfill() const { return false; } virtual bool isHfill() const { return false; }
virtual OutputParams::CtObject CtObject(OutputParams const &) const { return OutputParams::CT_NORMAL; }
enum DisplayType { enum DisplayType {
Inline = 0, Inline = 0,
AlignLeft, AlignLeft,

View File

@ -322,8 +322,10 @@ void InsetFloat::validate(LaTeXFeatures & features) const
if (features.inFloat()) if (features.inFloat())
features.require("subfig"); features.require("subfig");
if (features.inDeletedInset()) if (features.inDeletedInset()) {
features.require("tikz");
features.require("ct-tikz-object-sout"); features.require("ct-tikz-object-sout");
}
features.useFloat(params_.type, features.inFloat()); features.useFloat(params_.type, features.inFloat());
features.inFloat(true); features.inFloat(true);
@ -439,8 +441,12 @@ void InsetFloat::latex(otexstream & os, OutputParams const & runparams_in) const
os << '\n'; os << '\n';
if (runparams.inDeletedInset) { if (runparams.inDeletedInset) {
os << "\\lyxobjectsout{%" << breakln; // This has to be done manually since we need it inside the float
os << "\\parbox{\\linewidth}{%" << breakln; OutputParams::CtObject ctobject = runparams.ctObject;
runparams.ctObject = OutputParams::CT_DISPLAYOBJECT;
Changes::latexMarkChange(os, buffer().params(), Change(Change::UNCHANGED),
Change(Change::DELETED), runparams);
runparams.ctObject = ctobject;
} }
string alignment = getAlignment(); string alignment = getAlignment();
@ -454,7 +460,7 @@ void InsetFloat::latex(otexstream & os, OutputParams const & runparams_in) const
InsetText::latex(os, runparams); InsetText::latex(os, runparams);
if (runparams.inDeletedInset) if (runparams.inDeletedInset)
os << "}}"; os << "}";
// Force \end{<floatname>} to appear in a new line. // Force \end{<floatname>} to appear in a new line.
os << breakln << "\\end{" << from_ascii(tmptype) << "}\n"; os << breakln << "\\end{" << from_ascii(tmptype) << "}\n";

View File

@ -122,6 +122,8 @@ private:
TexString getCaption(OutputParams const &) const; TexString getCaption(OutputParams const &) const;
/// ///
std::string getAlignment() const; std::string getAlignment() const;
///
OutputParams::CtObject CtObject(OutputParams const &) const { return OutputParams::CT_OMITOBJECT; }
InsetFloatParams params_; InsetFloatParams params_;
}; };

View File

@ -858,11 +858,6 @@ void InsetGraphics::latex(otexstream & os,
if (runparams.moving_arg) if (runparams.moving_arg)
before += "\\protect"; before += "\\protect";
if (runparams.inDeletedInset) {
before += "\\lyxobjectsout{";
after += "}";
}
// We never use the starred form, we use the "clip" option instead. // We never use the starred form, we use the "clip" option instead.
before += "\\includegraphics"; before += "\\includegraphics";
@ -1141,9 +1136,11 @@ void InsetGraphics::validate(LaTeXFeatures & features) const
if (contains(rel_file, ".")) if (contains(rel_file, "."))
features.require("lyxdot"); features.require("lyxdot");
} }
if (features.inDeletedInset()) if (features.inDeletedInset()) {
features.require("tikz");
features.require("ct-tikz-object-sout"); features.require("ct-tikz-object-sout");
} }
}
bool InsetGraphics::setParams(InsetGraphicsParams const & p) bool InsetGraphics::setParams(InsetGraphicsParams const & p)

View File

@ -133,6 +133,8 @@ private:
/// \return the new filename, relative to the location of the HTML file, /// \return the new filename, relative to the location of the HTML file,
/// or an empty string on error. /// or an empty string on error.
std::string prepareHTMLFile(OutputParams const & runparams) const; std::string prepareHTMLFile(OutputParams const & runparams) const;
///
OutputParams::CtObject CtObject(OutputParams const &) const { return OutputParams::CT_OBJECT; }
/// ///
InsetGraphicsParams params_; InsetGraphicsParams params_;

View File

@ -123,13 +123,10 @@ namespace {
// writes a preamble for underlined or struck out math display // writes a preamble for underlined or struck out math display
void writeMathdisplayPreamble(WriteStream & os) void writeMathdisplayPreamble(WriteStream & os)
{ {
if (os.strikeoutMath()) { if (os.strikeoutMath())
return;
if (os.ulemCmd() == WriteStream::UNDERLINE) if (os.ulemCmd() == WriteStream::UNDERLINE)
os << "\\raisebox{-\\belowdisplayshortskip}{"
"\\lyxobjectsout{\\parbox[b]{\\linewidth}{";
else
os << "\\lyxobjectsout{\\parbox{\\linewidth}{";
} else if (os.ulemCmd() == WriteStream::UNDERLINE)
os << "\\raisebox{-\\belowdisplayshortskip}{" os << "\\raisebox{-\\belowdisplayshortskip}{"
"\\parbox[b]{\\linewidth}{"; "\\parbox[b]{\\linewidth}{";
else if (os.ulemCmd() == WriteStream::STRIKEOUT) else if (os.ulemCmd() == WriteStream::STRIKEOUT)
@ -140,11 +137,10 @@ namespace {
// writes a postamble for underlined or struck out math display // writes a postamble for underlined or struck out math display
void writeMathdisplayPostamble(WriteStream & os) void writeMathdisplayPostamble(WriteStream & os)
{ {
if (os.strikeoutMath()) { if (os.strikeoutMath())
return;
if (os.ulemCmd() == WriteStream::UNDERLINE) if (os.ulemCmd() == WriteStream::UNDERLINE)
os << "}";
os << "}}\\\\\n";
} else if (os.ulemCmd() == WriteStream::UNDERLINE)
os << "}}\\\\\n"; os << "}}\\\\\n";
else if (os.ulemCmd() == WriteStream::STRIKEOUT) else if (os.ulemCmd() == WriteStream::STRIKEOUT)
os << "}\\\\\n"; os << "}\\\\\n";
@ -1104,6 +1100,7 @@ void InsetMathHull::validate(LaTeXFeatures & features) const
from_ascii("\\newcommand{\\endregexp}{}")); from_ascii("\\newcommand{\\endregexp}{}"));
} else if (outerDisplay() && features.inDeletedInset() } else if (outerDisplay() && features.inDeletedInset()
&& !features.mustProvide("ct-dvipost")) { && !features.mustProvide("ct-dvipost")) {
features.require("tikz");
features.require("ct-tikz-object-sout"); features.require("ct-tikz-object-sout");
} }
@ -1127,6 +1124,37 @@ void InsetMathHull::validate(LaTeXFeatures & features) const
} }
OutputParams::CtObject InsetMathHull::CtObject(OutputParams const & runparams) const
{
OutputParams::CtObject res = OutputParams::CT_NORMAL;
switch(type_) {
case hullNone:
case hullSimple:
case hullAlignAt:
case hullXAlignAt:
case hullXXAlignAt:
case hullRegexp:
case hullUnknown:
break;
case hullEquation:
case hullEqnArray:
case hullAlign:
case hullFlAlign:
case hullGather:
case hullMultline: {
if (runparams.inulemcmd
&& (!runparams.local_font || runparams.local_font->fontInfo().strikeout() != FONT_ON))
res = OutputParams::CT_UDISPLAYOBJECT;
else
res = OutputParams::CT_DISPLAYOBJECT;
break;
}
}
return res;
}
void InsetMathHull::header_write(WriteStream & os) const void InsetMathHull::header_write(WriteStream & os) const
{ {
bool n = numberedType(); bool n = numberedType();

View File

@ -88,6 +88,8 @@ public:
/// ///
bool outerDisplay() const; bool outerDisplay() const;
/// ///
OutputParams::CtObject CtObject(OutputParams const &) const;
///
void validate(LaTeXFeatures & features) const; void validate(LaTeXFeatures & features) const;
/// identifies HullInset /// identifies HullInset
InsetMathHull const * asHullInset() const { return this; } InsetMathHull const * asHullInset() const { return this; }

View File

@ -4051,7 +4051,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
continue; continue;
} }
if (t.cs() == "lyxadded" || t.cs() == "lyxdeleted") { if (t.cs() == "lyxadded" || t.cs() == "lyxdeleted" || t.cs() == "lyxobjdeleted"
|| t.cs() == "lyxdisplayobjdeleted" || t.cs() == "lyxudisplayobjdeleted") {
context.check_layout(os); context.check_layout(os);
string initials; string initials;
if (p.hasOpt()) { if (p.hasOpt()) {