mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-16 16:18:22 +00:00
c88eaf877e
\mathbb{\underbar{a}} is not correctly rendered on screen. We really have to change the font set, but not always. This cannot be done using an "if" statement, as when the FontSetChanger scope ends, everything is restored, defeating our change. Thus, this has to be done in the FontSetChanger class itself. This is easily accomplished by introducing a boolean with a default value of true for really changing a font set. This will also be useful in other cases that I am discovering. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@34312 a592a061-630c-0410-9148-cb99ea01b6c8
298 lines
7.9 KiB
C++
298 lines
7.9 KiB
C++
/**
|
|
* \file InsetMathDecoration.cpp
|
|
* This file is part of LyX, the document processor.
|
|
* Licence details can be found in the file COPYING.
|
|
*
|
|
* \author Alejandro Aguilar Sierra
|
|
* \author André Pönitz
|
|
*
|
|
* Full author contact details are available in file CREDITS.
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include "InsetMathDecoration.h"
|
|
|
|
#include "MathData.h"
|
|
#include "MathParser.h"
|
|
#include "MathSupport.h"
|
|
#include "MathStream.h"
|
|
#include "MetricsInfo.h"
|
|
|
|
#include "LaTeXFeatures.h"
|
|
|
|
#include "support/debug.h"
|
|
#include "support/docstring.h"
|
|
#include "support/lassert.h"
|
|
|
|
#include <ostream>
|
|
|
|
using namespace std;
|
|
|
|
namespace lyx {
|
|
|
|
|
|
InsetMathDecoration::InsetMathDecoration(Buffer * buf, latexkeys const * key)
|
|
: InsetMathNest(buf, 1), key_(key)
|
|
{
|
|
// lyxerr << " creating deco " << key->name << endl;
|
|
}
|
|
|
|
|
|
Inset * InsetMathDecoration::clone() const
|
|
{
|
|
return new InsetMathDecoration(*this);
|
|
}
|
|
|
|
|
|
bool InsetMathDecoration::upper() const
|
|
{
|
|
return key_->name.substr(0, 5) != "under";
|
|
}
|
|
|
|
|
|
bool InsetMathDecoration::isScriptable() const
|
|
{
|
|
return
|
|
key_->name == "overbrace" ||
|
|
key_->name == "underbrace" ||
|
|
key_->name == "overleftarrow" ||
|
|
key_->name == "overrightarrow" ||
|
|
key_->name == "overleftrightarrow" ||
|
|
key_->name == "underleftarrow" ||
|
|
key_->name == "underrightarrow" ||
|
|
key_->name == "underleftrightarrow";
|
|
}
|
|
|
|
|
|
bool InsetMathDecoration::protect() const
|
|
{
|
|
return
|
|
key_->name == "overbrace" ||
|
|
key_->name == "underbrace" ||
|
|
key_->name == "overleftarrow" ||
|
|
key_->name == "overrightarrow" ||
|
|
key_->name == "overleftrightarrow" ||
|
|
key_->name == "underleftarrow" ||
|
|
key_->name == "underrightarrow" ||
|
|
key_->name == "underleftrightarrow";
|
|
}
|
|
|
|
|
|
bool InsetMathDecoration::wide() const
|
|
{
|
|
return
|
|
key_->name == "overline" ||
|
|
key_->name == "underline" ||
|
|
key_->name == "overbrace" ||
|
|
key_->name == "underbrace" ||
|
|
key_->name == "overleftarrow" ||
|
|
key_->name == "overrightarrow" ||
|
|
key_->name == "overleftrightarrow" ||
|
|
key_->name == "widehat" ||
|
|
key_->name == "widetilde" ||
|
|
key_->name == "underleftarrow" ||
|
|
key_->name == "underrightarrow" ||
|
|
key_->name == "underleftrightarrow";
|
|
}
|
|
|
|
|
|
InsetMath::mode_type InsetMathDecoration::currentMode() const
|
|
{
|
|
return key_->name == "underbar" ? TEXT_MODE : MATH_MODE;
|
|
}
|
|
|
|
|
|
void InsetMathDecoration::metrics(MetricsInfo & mi, Dimension & dim) const
|
|
{
|
|
bool really_change_font = currentMode() == TEXT_MODE
|
|
&& isMathFont(from_ascii(mi.base.fontname));
|
|
FontSetChanger dummy(mi.base, "textnormal", really_change_font);
|
|
|
|
cell(0).metrics(mi, dim);
|
|
|
|
dh_ = 6; //mathed_char_height(LM_TC_VAR, mi, 'I', ascent_, descent_);
|
|
dw_ = 6; //mathed_char_width(LM_TC_VAR, mi, 'x');
|
|
|
|
if (upper()) {
|
|
dy_ = -dim.asc - dh_;
|
|
dim.asc += dh_ + 1;
|
|
} else {
|
|
dy_ = dim.des + 1;
|
|
dim.des += dh_ + 2;
|
|
}
|
|
|
|
metricsMarkers(dim);
|
|
}
|
|
|
|
|
|
void InsetMathDecoration::draw(PainterInfo & pi, int x, int y) const
|
|
{
|
|
bool really_change_font = currentMode() == TEXT_MODE
|
|
&& isMathFont(from_ascii(pi.base.fontname));
|
|
FontSetChanger dummy(pi.base, "textnormal", really_change_font);
|
|
|
|
cell(0).draw(pi, x + 1, y);
|
|
Dimension const & dim0 = cell(0).dimension(*pi.base.bv);
|
|
if (wide())
|
|
mathed_draw_deco(pi, x + 1, y + dy_, dim0.wid, dh_, key_->name);
|
|
else
|
|
mathed_draw_deco(pi, x + 1 + (dim0.wid - dw_) / 2,
|
|
y + dy_, dw_, dh_, key_->name);
|
|
drawMarkers(pi, x, y);
|
|
setPosCache(pi, x, y);
|
|
}
|
|
|
|
|
|
void InsetMathDecoration::write(WriteStream & os) const
|
|
{
|
|
MathEnsurer ensurer(os);
|
|
if (os.fragile() && protect())
|
|
os << "\\protect";
|
|
os << '\\' << key_->name << '{';
|
|
ModeSpecifier specifier(os, currentMode());
|
|
os << cell(0) << '}';
|
|
}
|
|
|
|
|
|
void InsetMathDecoration::normalize(NormalStream & os) const
|
|
{
|
|
os << "[deco " << key_->name << ' ' << cell(0) << ']';
|
|
}
|
|
|
|
|
|
void InsetMathDecoration::infoize(odocstream & os) const
|
|
{
|
|
os << "Deco: " << key_->name;
|
|
}
|
|
|
|
|
|
namespace {
|
|
struct Attributes {
|
|
Attributes() {}
|
|
Attributes(bool o, string t)
|
|
: over(o), tag(t) {}
|
|
bool over;
|
|
string tag;
|
|
};
|
|
|
|
typedef map<string, Attributes> TranslationMap;
|
|
|
|
void buildTranslationMap(TranslationMap & t) {
|
|
// the decorations we need to support are listed in lib/symbols
|
|
t["acute"] = Attributes(true, "´");
|
|
t["bar"] = Attributes(true, "‾");
|
|
t["breve"] = Attributes(true, "˘");
|
|
t["check"] = Attributes(true, "ˇ");
|
|
t["ddddot"] = Attributes(true, "⃜");
|
|
t["dddot"] = Attributes(true, "⃛");
|
|
t["ddot"] = Attributes(true, "¨");
|
|
t["dot"] = Attributes(true, "˙");
|
|
t["grave"] = Attributes(true, "`");
|
|
t["hat"] = Attributes(true, "ˆ");
|
|
t["mathring"] = Attributes(true, "˚");
|
|
t["overbrace"] = Attributes(true, "⏞");
|
|
t["overleftarrow"] = Attributes(true, "⟵");
|
|
t["overleftrightarrow"] = Attributes(true, "⟷");
|
|
t["overline"] = Attributes(true, "¯");
|
|
t["overrightarrow"] = Attributes(true, "⟶");
|
|
t["tilde"] = Attributes(true, "˜");
|
|
t["underbar"] = Attributes(false, "_");
|
|
t["underbrace"] = Attributes(false, "⏟");
|
|
t["underleftarrow"] = Attributes(false, "⟵");
|
|
t["underleftrightarrow"] = Attributes(false, "⟷");
|
|
// this is the macron, again, but it works
|
|
t["underline"] = Attributes(false, "¯");
|
|
t["underrightarrow"] = Attributes(false, "⟶");
|
|
t["vec"] = Attributes(true, "→");
|
|
t["widehat"] = Attributes(true, "^");
|
|
t["widetilde"] = Attributes(true, "∼");
|
|
}
|
|
|
|
TranslationMap const & translationMap() {
|
|
static TranslationMap t;
|
|
if (t.empty())
|
|
buildTranslationMap(t);
|
|
return t;
|
|
}
|
|
}
|
|
|
|
void InsetMathDecoration::mathmlize(MathStream & os) const
|
|
{
|
|
TranslationMap const & t = translationMap();
|
|
TranslationMap::const_iterator cur = t.find(to_utf8(key_->name));
|
|
LASSERT(cur != t.end(), return);
|
|
char const * const outag = cur->second.over ? "mover" : "munder";
|
|
os << MTag(outag)
|
|
<< MTag("mrow") << cell(0) << ETag("mrow")
|
|
<< from_ascii("<mo stretchy=\"true\">" + cur->second.tag + "</mo>")
|
|
<< ETag(outag);
|
|
}
|
|
|
|
|
|
void InsetMathDecoration::htmlize(HtmlStream & os) const
|
|
{
|
|
string const name = to_utf8(key_->name);
|
|
if (name == "bar") {
|
|
os << MTag("span", "class='overbar'") << cell(0) << ETag("span");
|
|
return;
|
|
}
|
|
|
|
if (name == "underbar" || name == "underline") {
|
|
os << MTag("span", "class='underbar'") << cell(0) << ETag("span");
|
|
return;
|
|
}
|
|
|
|
TranslationMap const & t = translationMap();
|
|
TranslationMap::const_iterator cur = t.find(name);
|
|
LASSERT(cur != t.end(), return);
|
|
|
|
bool symontop = cur->second.over;
|
|
string const symclass = symontop ? "symontop" : "symonbot";
|
|
os << MTag("span", "class='symbolpair " + symclass + "'")
|
|
<< '\n';
|
|
|
|
if (symontop)
|
|
os << MTag("span", "class='symbol'") << from_ascii(cur->second.tag);
|
|
else
|
|
os << MTag("span", "class='base'") << cell(0);
|
|
os << ETag("span") << '\n';
|
|
if (symontop)
|
|
os << MTag("span", "class='base'") << cell(0);
|
|
else
|
|
os << MTag("span", "class='symbol'") << from_ascii(cur->second.tag);
|
|
os << ETag("span") << '\n' << ETag("span") << '\n';
|
|
}
|
|
|
|
|
|
// ideas borrowed from the eLyXer code
|
|
void InsetMathDecoration::validate(LaTeXFeatures & features) const
|
|
{
|
|
if (features.runparams().math_flavor == OutputParams::MathAsHTML) {
|
|
string const name = to_utf8(key_->name);
|
|
if (name == "bar") {
|
|
features.addPreambleSnippet("<style type=\"text/css\">\n"
|
|
"span.overbar{border-top: thin black solid;}\n"
|
|
"</style>");
|
|
} else if (name == "underbar" || name == "underline") {
|
|
features.addPreambleSnippet("<style type=\"text/css\">\n"
|
|
"span.underbar{border-bottom: thin black solid;}\n"
|
|
"</style>");
|
|
} else {
|
|
features.addPreambleSnippet("<style type=\"text/css\">\n"
|
|
"span.symbolpair{display: inline-block; text-align:center;}\n"
|
|
"span.symontop{vertical-align: top;}\n"
|
|
"span.symonbot{vertical-align: bottom;}\n"
|
|
"span.symbolpair span{display: block;}\n"
|
|
"span.symbol{height: 0.5ex;}\n"
|
|
"</style>");
|
|
}
|
|
} else {
|
|
if (!key_->requires.empty())
|
|
features.require(to_utf8(key_->requires));
|
|
}
|
|
InsetMathNest::validate(features);
|
|
}
|
|
|
|
} // namespace lyx
|