RefChanger

RefChanger temporarily assigns a value to a non-const reference of any
kind. RefChanger provides a flexible and uniform generalisation of the various
scope guards previously derived from the old Changer class in MetricsInfo.h.

As before, a temporary assignment lasts as long as the Changer object lives. But
the new Changer is movable. In particular, contorsions are no longer needed to
change a private field. Special code can be moved into the appropriate classes,
and it is no longer necessary to create a new class for each specific use.

Syntax change:

   FontSetChanger dummy(mi.base, value);
-> Changer dummy = mi.base.changeFontSet(value);

New function for generating arbitrary Changers:

  Changer dummy = make_change(ref, val, condition);

Bugfix:

* Fix the display of \displaystyle{\substack{\frac{xyz}{}}} (missing style
  change).
This commit is contained in:
Guillaume Munch 2016-05-23 22:30:23 +01:00
parent 0be52d3710
commit e2bc7ffae3
34 changed files with 334 additions and 437 deletions

View File

@ -21,6 +21,7 @@
#include "support/debug.h" #include "support/debug.h"
#include "support/docstring.h" #include "support/docstring.h"
#include "support/lstrings.h" #include "support/lstrings.h"
#include "support/RefChanger.h"
#include <ostream> #include <ostream>
#include <sstream> #include <sstream>
@ -245,6 +246,26 @@ FontInfo & FontInfo::realize(FontInfo const & tmplt)
} }
Changer FontInfo::changeColor(ColorCode const color, bool cond)
{
return make_change(color_, color, cond);
}
Changer FontInfo::changeShape(FontShape const shape, bool cond)
{
return make_change(shape_, shape, cond);
}
Changer FontInfo::change(FontInfo font, bool realiz, bool cond)
{
if (realiz)
font.realize(*this);
return make_change(*this, font, cond);
}
/// Updates a misc setting according to request /// Updates a misc setting according to request
static FontState setMisc(FontState newfont, static FontState setMisc(FontState newfont,
FontState org) FontState org)

View File

@ -18,8 +18,11 @@
#include "Color.h" #include "Color.h"
#include "ColorCode.h" #include "ColorCode.h"
#include "FontEnums.h" #include "FontEnums.h"
#include "support/Changer.h"
#include "support/strfwd.h" #include "support/strfwd.h"
namespace lyx { namespace lyx {
class Lexer; class Lexer;
@ -136,6 +139,14 @@ public:
} }
} }
/// Temporarily replace the color with \param color.
Changer changeColor(ColorCode const color, bool cond = true);
/// Temporarily replace the shape with \param shape.
Changer changeShape(FontShape const shape, bool cond = true);
/// Temporarily replace the FontInfo with \param font, and optionally
/// \param realize the \param font against the current FontInfo.
Changer change(FontInfo font, bool realize = false, bool cond = true);
private: private:
friend bool operator==(FontInfo const & lhs, FontInfo const & rhs); friend bool operator==(FontInfo const & lhs, FontInfo const & rhs);

View File

@ -22,6 +22,7 @@
#include "support/docstring.h" #include "support/docstring.h"
#include "support/lassert.h" #include "support/lassert.h"
#include "support/RefChanger.h"
using namespace std; using namespace std;
@ -46,6 +47,33 @@ MetricsBase::MetricsBase(BufferView * b, FontInfo const & f, int w)
{} {}
Changer MetricsBase::changeFontSet(docstring const & name, bool cond)
{
RefChanger<MetricsBase> rc = make_save(*this);
if (!cond)
rc->keep();
else {
ColorCode oldcolor = font.color();
docstring const oldname = from_ascii(fontname);
fontname = to_utf8(name);
font = sane_font;
augmentFont(font, name);
font.setSize(rc->old.font.size());
if (name != "lyxtex"
&& ((isTextFont(oldname) && oldcolor != Color_foreground)
|| (isMathFont(oldname) && oldcolor != Color_math)))
font.setColor(oldcolor);
}
return move(rc);
}
Changer MetricsBase::changeFontSet(char const * name, bool cond)
{
return changeFontSet(from_ascii(name), cond);
}
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// MetricsInfo // MetricsInfo
@ -117,210 +145,58 @@ Color PainterInfo::textColor(Color const & color) const
} }
///////////////////////////////////////////////////////////////////////// Changer MetricsBase::changeScript(bool cond)
//
// ScriptChanger
//
/////////////////////////////////////////////////////////////////////////
Styles smallerScriptStyle(Styles st)
{ {
switch (st) { switch (style) {
case LM_ST_DISPLAY: case LM_ST_DISPLAY:
case LM_ST_TEXT: case LM_ST_TEXT:
return LM_ST_SCRIPT; return changeStyle(LM_ST_SCRIPT, cond);
case LM_ST_SCRIPT: case LM_ST_SCRIPT:
case LM_ST_SCRIPTSCRIPT: case LM_ST_SCRIPTSCRIPT:
default: // shut up compiler return changeStyle(LM_ST_SCRIPTSCRIPT, cond);
return LM_ST_SCRIPTSCRIPT;
} }
//remove Warning
LASSERT(false, return Changer());
} }
ScriptChanger::ScriptChanger(MetricsBase & mb) Changer MetricsBase::changeFrac(bool cond)
: StyleChanger(mb, smallerScriptStyle(mb.style))
{}
/////////////////////////////////////////////////////////////////////////
//
// FracChanger
//
/////////////////////////////////////////////////////////////////////////
Styles smallerFracStyle(Styles st)
{ {
switch (st) { switch (style) {
case LM_ST_DISPLAY: case LM_ST_DISPLAY:
return LM_ST_TEXT; return changeStyle(LM_ST_TEXT, cond);
case LM_ST_TEXT: case LM_ST_TEXT:
return LM_ST_SCRIPT; return changeStyle(LM_ST_SCRIPT, cond);
case LM_ST_SCRIPT: case LM_ST_SCRIPT:
case LM_ST_SCRIPTSCRIPT: case LM_ST_SCRIPTSCRIPT:
default: // shut up compiler return changeStyle(LM_ST_SCRIPTSCRIPT, cond);
return LM_ST_SCRIPTSCRIPT;
} }
//remove Warning
return Changer();
} }
FracChanger::FracChanger(MetricsBase & mb) Changer MetricsBase::changeStyle(Styles new_style, bool cond)
: StyleChanger(mb, smallerFracStyle(mb.style))
{}
/////////////////////////////////////////////////////////////////////////
//
// ArrayChanger
//
/////////////////////////////////////////////////////////////////////////
ArrayChanger::ArrayChanger(MetricsBase & mb)
: StyleChanger(mb, mb.style == LM_ST_DISPLAY ? LM_ST_TEXT : mb.style)
{}
/////////////////////////////////////////////////////////////////////////
//
// ShapeChanger
//
/////////////////////////////////////////////////////////////////////////
ShapeChanger::ShapeChanger(FontInfo & font, FontShape shape)
: Changer<FontInfo, FontShape>(font, font.shape())
{
orig_.setShape(shape);
}
ShapeChanger::~ShapeChanger()
{
orig_.setShape(save_);
}
/////////////////////////////////////////////////////////////////////////
//
// StyleChanger
//
/////////////////////////////////////////////////////////////////////////
StyleChanger::StyleChanger(MetricsBase & mb, Styles style)
: Changer<MetricsBase>(mb)
{ {
static const int diff[4][4] = static const int diff[4][4] =
{ { 0, 0, -3, -5 }, { { 0, 0, -3, -5 },
{ 0, 0, -3, -5 }, { 0, 0, -3, -5 },
{ 3, 3, 0, -2 }, { 3, 3, 0, -2 },
{ 5, 5, 2, 0 } }; { 5, 5, 2, 0 } };
int t = diff[mb.style][style]; int t = diff[style][new_style];
if (t > 0) RefChanger<MetricsBase> rc = make_save(*this);
while (t--) if (!cond)
mb.font.incSize(); rc->keep();
else else {
while (t++) if (t > 0)
mb.font.decSize(); while (t--)
mb.style = style; font.incSize();
} else
while (t++)
font.decSize();
StyleChanger::~StyleChanger() style = new_style;
{
orig_ = save_;
}
/////////////////////////////////////////////////////////////////////////
//
// FontSetChanger
//
/////////////////////////////////////////////////////////////////////////
FontSetChanger::FontSetChanger(MetricsBase & mb, char const * name,
bool really_change_font)
: Changer<MetricsBase>(mb), change_(really_change_font)
{
if (change_) {
FontSize oldsize = save_.font.size();
ColorCode oldcolor = save_.font.color();
docstring const oldname = from_ascii(save_.fontname);
mb.fontname = name;
mb.font = sane_font;
augmentFont(mb.font, from_ascii(name));
mb.font.setSize(oldsize);
if (string(name) != "lyxtex"
&& ((isTextFont(oldname) && oldcolor != Color_foreground)
|| (isMathFont(oldname) && oldcolor != Color_math)))
mb.font.setColor(oldcolor);
} }
} return move(rc);
FontSetChanger::FontSetChanger(MetricsBase & mb, docstring const & name,
bool really_change_font)
: Changer<MetricsBase>(mb), change_(really_change_font)
{
if (change_) {
FontSize oldsize = save_.font.size();
ColorCode oldcolor = save_.font.color();
docstring const oldname = from_ascii(save_.fontname);
mb.fontname = to_utf8(name);
mb.font = sane_font;
augmentFont(mb.font, name);
mb.font.setSize(oldsize);
if (name != "lyxtex"
&& ((isTextFont(oldname) && oldcolor != Color_foreground)
|| (isMathFont(oldname) && oldcolor != Color_math)))
mb.font.setColor(oldcolor);
}
}
FontSetChanger::~FontSetChanger()
{
if (change_)
orig_ = save_;
}
/////////////////////////////////////////////////////////////////////////
//
// WidthChanger
//
/////////////////////////////////////////////////////////////////////////
WidthChanger::WidthChanger(MetricsBase & mb, int w)
: Changer<MetricsBase>(mb)
{
mb.textwidth = w;
}
WidthChanger::~WidthChanger()
{
orig_ = save_;
}
/////////////////////////////////////////////////////////////////////////
//
// ColorChanger
//
/////////////////////////////////////////////////////////////////////////
ColorChanger::ColorChanger(FontInfo & font, ColorCode color,
bool really_change_color)
: Changer<FontInfo, ColorCode>(font, font.color()), change_(really_change_color)
{
if (change_) {
font.setColor(color);
}
}
ColorChanger::~ColorChanger()
{
if (change_)
orig_.setColor(save_);
} }

View File

@ -18,6 +18,8 @@
#include "FontInfo.h" #include "FontInfo.h"
#include "support/strfwd.h" #include "support/strfwd.h"
#include "support/Changer.h"
#include <string> #include <string>
@ -31,6 +33,7 @@ class MacroContext;
/// Standard Sizes (mode styles) /// Standard Sizes (mode styles)
/// note: These values are hard-coded in changeStyle
enum Styles { enum Styles {
/// ///
LM_ST_DISPLAY = 0, LM_ST_DISPLAY = 0,
@ -63,6 +66,16 @@ public:
std::string fontname; std::string fontname;
/// This is the width available in pixels /// This is the width available in pixels
int textwidth; int textwidth;
/// Temporarily change a full font.
Changer changeFontSet(docstring const & font, bool cond = true);
Changer changeFontSet(char const * font, bool cond = true);
/// Temporarily change the font size and the math style.
Changer changeStyle(Styles style, bool cond = true);
// Temporarily change to the style suitable for use in fractions
Changer changeFrac(bool cond = true);
// Temporarily change the style to (script)script style
Changer changeScript(bool cond = true);
}; };
@ -127,121 +140,6 @@ public:
class TextMetricsInfo {}; class TextMetricsInfo {};
/// Generic base for temporarily changing things. The derived class is
/// responsible for restoring the original state when the Changer is
/// destructed.
template <class Struct, class Temp = Struct>
class Changer {
protected:
///
Changer(Struct & orig, Temp const & save) : orig_(orig), save_(save) {}
///
Changer(Struct & orig) : orig_(orig), save_(orig) {}
///
Struct & orig_;
///
Temp save_;
};
// temporarily change some aspect of a font
class FontChanger : public Changer<FontInfo> {
public:
///
FontChanger(FontInfo & orig, docstring const & font);
FontChanger(MetricsBase & mb, char const * const font);
///
~FontChanger();
};
// temporarily change a full font
class FontSetChanger : public Changer<MetricsBase> {
public:
///
FontSetChanger(MetricsBase & mb, docstring const & font,
bool really_change_font = true);
FontSetChanger(MetricsBase & mb, char const * const font,
bool really_change_font = true);
///
~FontSetChanger();
private:
///
bool change_;
};
// temporarily change the style
class StyleChanger : public Changer<MetricsBase> {
public:
///
StyleChanger(MetricsBase & mb, Styles style);
///
~StyleChanger();
};
// temporarily change the style to script style
class ScriptChanger : public StyleChanger {
public:
///
ScriptChanger(MetricsBase & mb);
};
// temporarily change the style suitable for use in fractions
class FracChanger : public StyleChanger {
public:
///
FracChanger(MetricsBase & mb);
};
// temporarily change the style suitable for use in tabulars and arrays
class ArrayChanger : public StyleChanger {
public:
///
ArrayChanger(MetricsBase & mb);
};
// temporarily change the shape of a font
class ShapeChanger : public Changer<FontInfo, FontShape> {
public:
///
ShapeChanger(FontInfo & font, FontShape shape);
///
~ShapeChanger();
};
// temporarily change the available text width
class WidthChanger : public Changer<MetricsBase>
{
public:
///
WidthChanger(MetricsBase & mb, int width);
///
~WidthChanger();
};
// temporarily change the used color
class ColorChanger : public Changer<FontInfo, ColorCode> {
public:
///
ColorChanger(FontInfo & font, ColorCode color,
bool really_change_color = true);
///
~ColorChanger();
private:
///
bool change_;
};
} // namespace lyx } // namespace lyx
#endif #endif

View File

@ -160,7 +160,7 @@ Inset::DisplayType InsetScript::display() const
void InsetScript::metrics(MetricsInfo & mi, Dimension & dim) const void InsetScript::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
int const shift = params_.shift(mi.base.font); int const shift = params_.shift(mi.base.font);
ScriptChanger dummy(mi.base); Changer dummy = mi.base.changeScript();
InsetText::metrics(mi, dim); InsetText::metrics(mi, dim);
dim.asc -= shift; dim.asc -= shift;
dim.des += shift; dim.des += shift;
@ -170,7 +170,7 @@ void InsetScript::metrics(MetricsInfo & mi, Dimension & dim) const
void InsetScript::draw(PainterInfo & pi, int x, int y) const void InsetScript::draw(PainterInfo & pi, int x, int y) const
{ {
int const shift = params_.shift(pi.base.font); int const shift = params_.shift(pi.base.font);
ScriptChanger dummy(pi.base); Changer dummy = pi.base.changeScript();
InsetText::draw(pi, x, y + shift); InsetText::draw(pi, x, y + shift);
} }

View File

@ -20,8 +20,8 @@
#include "FuncRequest.h" #include "FuncRequest.h"
#include "FuncStatus.h" #include "FuncStatus.h"
#include "support/gettext.h"
#include "support/gettext.h"
#include "support/lstrings.h" #include "support/lstrings.h"
#include <sstream> #include <sstream>
@ -85,7 +85,8 @@ char const * InsetMathAMSArray::name_right() const
void InsetMathAMSArray::metrics(MetricsInfo & mi, Dimension & dim) const void InsetMathAMSArray::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
ArrayChanger dummy(mi.base); Changer dummy =
mi.base.changeStyle(LM_ST_TEXT, mi.base.style == LM_ST_DISPLAY);
InsetMathGrid::metrics(mi, dim); InsetMathGrid::metrics(mi, dim);
dim.wid += 14; dim.wid += 14;
} }
@ -95,10 +96,11 @@ void InsetMathAMSArray::draw(PainterInfo & pi, int x, int y) const
{ {
Dimension const dim = dimension(*pi.base.bv); Dimension const dim = dimension(*pi.base.bv);
int const yy = y - dim.ascent(); int const yy = y - dim.ascent();
// Drawing the deco after an ArrayChanger does not work // Drawing the deco after changeStyle does not work
mathed_draw_deco(pi, x + 1, yy, 5, dim.height(), from_ascii(name_left())); mathed_draw_deco(pi, x + 1, yy, 5, dim.height(), from_ascii(name_left()));
mathed_draw_deco(pi, x + dim.width() - 8, yy, 5, dim.height(), from_ascii(name_right())); mathed_draw_deco(pi, x + dim.width() - 8, yy, 5, dim.height(), from_ascii(name_right()));
ArrayChanger dummy(pi.base); Changer dummy =
pi.base.changeStyle(LM_ST_TEXT, pi.base.style == LM_ST_DISPLAY);
InsetMathGrid::drawWithMargin(pi, x, y, 6, 8); InsetMathGrid::drawWithMargin(pi, x, y, 6, 8);
} }

View File

@ -74,7 +74,8 @@ Inset * InsetMathArray::clone() const
void InsetMathArray::metrics(MetricsInfo & mi, Dimension & dim) const void InsetMathArray::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
ArrayChanger dummy(mi.base); Changer dummy =
mi.base.changeStyle(LM_ST_TEXT, mi.base.style == LM_ST_DISPLAY);
InsetMathGrid::metrics(mi, dim); InsetMathGrid::metrics(mi, dim);
dim.wid += 6; dim.wid += 6;
} }
@ -91,7 +92,8 @@ Dimension const InsetMathArray::dimension(BufferView const & bv) const
void InsetMathArray::draw(PainterInfo & pi, int x, int y) const void InsetMathArray::draw(PainterInfo & pi, int x, int y) const
{ {
setPosCache(pi, x, y); setPosCache(pi, x, y);
ArrayChanger dummy(pi.base); Changer dummy =
pi.base.changeStyle(LM_ST_TEXT, pi.base.style == LM_ST_DISPLAY);
InsetMathGrid::drawWithMargin(pi, x, y, 4, 2); InsetMathGrid::drawWithMargin(pi, x, y, 4, 2);
} }

View File

@ -49,7 +49,7 @@ docstring InsetMathBoldSymbol::name() const
void InsetMathBoldSymbol::metrics(MetricsInfo & mi, Dimension & dim) const void InsetMathBoldSymbol::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
//FontSetChanger dummy(mi.base, "mathbf"); //Changer dummy = mi.base.changeFontSet("mathbf");
cell(0).metrics(mi, dim); cell(0).metrics(mi, dim);
metricsMarkers(dim); metricsMarkers(dim);
++dim.wid; // for 'double stroke' ++dim.wid; // for 'double stroke'
@ -58,7 +58,7 @@ void InsetMathBoldSymbol::metrics(MetricsInfo & mi, Dimension & dim) const
void InsetMathBoldSymbol::draw(PainterInfo & pi, int x, int y) const void InsetMathBoldSymbol::draw(PainterInfo & pi, int x, int y) const
{ {
//FontSetChanger dummy(pi.base, "mathbf"); //Changer dummy = pi.base.changeFontSet("mathbf");
cell(0).draw(pi, x + 1, y); cell(0).draw(pi, x + 1, y);
cell(0).draw(pi, x + 2, y); cell(0).draw(pi, x + 2, y);
drawMarkers(pi, x, y); drawMarkers(pi, x, y);

View File

@ -81,7 +81,7 @@ void InsetMathBox::htmlize(HtmlStream & ms) const
void InsetMathBox::metrics(MetricsInfo & mi, Dimension & dim) const void InsetMathBox::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
FontSetChanger dummy(mi.base, "textnormal"); Changer dummy = mi.base.changeFontSet("textnormal");
cell(0).metrics(mi, dim); cell(0).metrics(mi, dim);
metricsMarkers(dim); metricsMarkers(dim);
} }
@ -89,7 +89,7 @@ void InsetMathBox::metrics(MetricsInfo & mi, Dimension & dim) const
void InsetMathBox::draw(PainterInfo & pi, int x, int y) const void InsetMathBox::draw(PainterInfo & pi, int x, int y) const
{ {
FontSetChanger dummy(pi.base, "textnormal"); Changer dummy = pi.base.changeFontSet("textnormal");
cell(0).draw(pi, x, y); cell(0).draw(pi, x, y);
drawMarkers(pi, x, y); drawMarkers(pi, x, y);
} }
@ -133,7 +133,7 @@ InsetMathFBox::InsetMathFBox(Buffer * buf)
void InsetMathFBox::metrics(MetricsInfo & mi, Dimension & dim) const void InsetMathFBox::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
FontSetChanger dummy(mi.base, "textnormal"); Changer dummy = mi.base.changeFontSet("textnormal");
cell(0).metrics(mi, dim); cell(0).metrics(mi, dim);
metricsMarkers2(dim, 3); // 1 pixel space, 1 frame, 1 space metricsMarkers2(dim, 3); // 1 pixel space, 1 frame, 1 space
} }
@ -144,7 +144,7 @@ void InsetMathFBox::draw(PainterInfo & pi, int x, int y) const
Dimension const dim = dimension(*pi.base.bv); Dimension const dim = dimension(*pi.base.bv);
pi.pain.rectangle(x + 1, y - dim.ascent() + 1, pi.pain.rectangle(x + 1, y - dim.ascent() + 1,
dim.width() - 2, dim.height() - 2, Color_foreground); dim.width() - 2, dim.height() - 2, Color_foreground);
FontSetChanger dummy(pi.base, "textnormal"); Changer dummy = pi.base.changeFontSet("textnormal");
cell(0).draw(pi, x + 3, y); cell(0).draw(pi, x + 3, y);
setPosCache(pi, x, y); setPosCache(pi, x, y);
} }
@ -219,7 +219,7 @@ InsetMathMakebox::InsetMathMakebox(Buffer * buf, bool framebox)
void InsetMathMakebox::metrics(MetricsInfo & mi, Dimension & dim) const void InsetMathMakebox::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
FontSetChanger dummy(mi.base, "textnormal"); Changer dummy = mi.base.changeFontSet("textnormal");
Dimension wdim; Dimension wdim;
static docstring bracket = from_ascii("["); static docstring bracket = from_ascii("[");
@ -254,7 +254,7 @@ void InsetMathMakebox::draw(PainterInfo & pi, int x, int y) const
{ {
drawMarkers(pi, x, y); drawMarkers(pi, x, y);
FontSetChanger dummy(pi.base, "textnormal"); Changer dummy = pi.base.changeFontSet("textnormal");
BufferView const & bv = *pi.base.bv; BufferView const & bv = *pi.base.bv;
int w = mathed_char_width(pi.base.font, '['); int w = mathed_char_width(pi.base.font, '[');

View File

@ -56,13 +56,13 @@ void InsetMathChar::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
#if 1 #if 1
if (char_ == '=' && has_math_fonts) { if (char_ == '=' && has_math_fonts) {
FontSetChanger dummy(mi.base, "cmr"); Changer dummy = mi.base.changeFontSet("cmr");
dim = theFontMetrics(mi.base.font).dimension(char_); dim = theFontMetrics(mi.base.font).dimension(char_);
} else if ((char_ == '>' || char_ == '<') && has_math_fonts) { } else if ((char_ == '>' || char_ == '<') && has_math_fonts) {
FontSetChanger dummy(mi.base, "cmm"); Changer dummy = mi.base.changeFontSet("cmm");
dim = theFontMetrics(mi.base.font).dimension(char_); dim = theFontMetrics(mi.base.font).dimension(char_);
} else if (!slanted(char_) && mi.base.fontname == "mathnormal") { } else if (!slanted(char_) && mi.base.fontname == "mathnormal") {
ShapeChanger dummy(mi.base.font, UP_SHAPE); Changer dummy = mi.base.font.changeShape(UP_SHAPE);
dim = theFontMetrics(mi.base.font).dimension(char_); dim = theFontMetrics(mi.base.font).dimension(char_);
} else { } else {
frontend::FontMetrics const & fm = theFontMetrics(mi.base.font); frontend::FontMetrics const & fm = theFontMetrics(mi.base.font);
@ -99,13 +99,13 @@ void InsetMathChar::draw(PainterInfo & pi, int x, int y) const
x += mathed_thinmuskip(pi.base.font) / 2; x += mathed_thinmuskip(pi.base.font) / 2;
#if 1 #if 1
if (char_ == '=' && has_math_fonts) { if (char_ == '=' && has_math_fonts) {
FontSetChanger dummy(pi.base, "cmr"); Changer dummy = pi.base.changeFontSet("cmr");
pi.draw(x, y, char_); pi.draw(x, y, char_);
} else if ((char_ == '>' || char_ == '<') && has_math_fonts) { } else if ((char_ == '>' || char_ == '<') && has_math_fonts) {
FontSetChanger dummy(pi.base, "cmm"); Changer dummy = pi.base.changeFontSet("cmm");
pi.draw(x, y, char_); pi.draw(x, y, char_);
} else if (!slanted(char_) && pi.base.fontname == "mathnormal") { } else if (!slanted(char_) && pi.base.fontname == "mathnormal") {
ShapeChanger dummy(pi.base.font, UP_SHAPE); Changer dummy = pi.base.font.changeShape(UP_SHAPE);
pi.draw(x, y, char_); pi.draw(x, y, char_);
} else { } else {
pi.draw(x, y, char_); pi.draw(x, y, char_);

View File

@ -107,7 +107,7 @@ void InsetMathDecoration::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
bool really_change_font = currentMode() == TEXT_MODE bool really_change_font = currentMode() == TEXT_MODE
&& isMathFont(from_ascii(mi.base.fontname)); && isMathFont(from_ascii(mi.base.fontname));
FontSetChanger dummy(mi.base, "textnormal", really_change_font); Changer dummy = mi.base.changeFontSet("textnormal", really_change_font);
cell(0).metrics(mi, dim); cell(0).metrics(mi, dim);
@ -130,7 +130,7 @@ void InsetMathDecoration::draw(PainterInfo & pi, int x, int y) const
{ {
bool really_change_font = currentMode() == TEXT_MODE bool really_change_font = currentMode() == TEXT_MODE
&& isMathFont(from_ascii(pi.base.fontname)); && isMathFont(from_ascii(pi.base.fontname));
FontSetChanger dummy(pi.base, "textnormal", really_change_font); Changer dummy = pi.base.changeFontSet("textnormal", really_change_font);
cell(0).draw(pi, x + 1, y); cell(0).draw(pi, x + 1, y);
Dimension const & dim0 = cell(0).dimension(*pi.base.bv); Dimension const & dim0 = cell(0).dimension(*pi.base.bv);

View File

@ -37,7 +37,7 @@ Inset * InsetMathEnsureMath::clone() const
void InsetMathEnsureMath::metrics(MetricsInfo & mi, Dimension & dim) const void InsetMathEnsureMath::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
bool really_change_font = isTextFont(from_ascii(mi.base.fontname)); bool really_change_font = isTextFont(from_ascii(mi.base.fontname));
FontSetChanger dummy(mi.base, "mathnormal", really_change_font); Changer dummy = mi.base.changeFontSet("mathnormal", really_change_font);
cell(0).metrics(mi, dim); cell(0).metrics(mi, dim);
metricsMarkers(dim); metricsMarkers(dim);
} }
@ -46,7 +46,7 @@ void InsetMathEnsureMath::metrics(MetricsInfo & mi, Dimension & dim) const
void InsetMathEnsureMath::draw(PainterInfo & pi, int x, int y) const void InsetMathEnsureMath::draw(PainterInfo & pi, int x, int y) const
{ {
bool really_change_font = isTextFont(from_ascii(pi.base.fontname)); bool really_change_font = isTextFont(from_ascii(pi.base.fontname));
FontSetChanger dummy(pi.base, "mathnormal", really_change_font); Changer dummy = pi.base.changeFontSet("mathnormal", really_change_font);
cell(0).draw(pi, x, y); cell(0).draw(pi, x, y);
drawMarkers(pi, x, y); drawMarkers(pi, x, y);
} }

View File

@ -58,7 +58,7 @@ bool InsetMathFont::lockedMode() const
void InsetMathFont::metrics(MetricsInfo & mi, Dimension & dim) const void InsetMathFont::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
FontSetChanger dummy(mi.base, key_->name); Changer dummy = mi.base.changeFontSet(key_->name);
cell(0).metrics(mi, dim); cell(0).metrics(mi, dim);
metricsMarkers(dim); metricsMarkers(dim);
} }
@ -66,7 +66,7 @@ void InsetMathFont::metrics(MetricsInfo & mi, Dimension & dim) const
void InsetMathFont::draw(PainterInfo & pi, int x, int y) const void InsetMathFont::draw(PainterInfo & pi, int x, int y) const
{ {
FontSetChanger dummy(pi.base, key_->name); Changer dummy = pi.base.changeFontSet(key_->name);
cell(0).draw(pi, x + 1, y); cell(0).draw(pi, x + 1, y);
drawMarkers(pi, x, y); drawMarkers(pi, x, y);
setPosCache(pi, x, y); setPosCache(pi, x, y);

View File

@ -51,7 +51,7 @@ void InsetMathFontOld::metrics(MetricsInfo & mi, Dimension & dim) const
// When \cal is used in text mode, the font is not changed // When \cal is used in text mode, the font is not changed
bool really_change_font = font != "textcal"; bool really_change_font = font != "textcal";
FontSetChanger dummy(mi.base, font, really_change_font); Changer dummy = mi.base.changeFontSet(font, really_change_font);
cell(0).metrics(mi, dim); cell(0).metrics(mi, dim);
metricsMarkers(dim); metricsMarkers(dim);
} }
@ -68,7 +68,7 @@ void InsetMathFontOld::draw(PainterInfo & pi, int x, int y) const
// When \cal is used in text mode, the font is not changed // When \cal is used in text mode, the font is not changed
bool really_change_font = font != "textcal"; bool really_change_font = font != "textcal";
FontSetChanger dummy(pi.base, font, really_change_font); Changer dummy = pi.base.changeFontSet(font, really_change_font);
cell(0).draw(pi, x + 1, y); cell(0).draw(pi, x + 1, y);
drawMarkers(pi, x, y); drawMarkers(pi, x, y);
} }

View File

@ -22,11 +22,13 @@
#include "MetricsInfo.h" #include "MetricsInfo.h"
#include "TextPainter.h" #include "TextPainter.h"
#include "support/lassert.h"
#include "frontends/Painter.h" #include "frontends/Painter.h"
#include "support/lassert.h"
using namespace std; using namespace std;
namespace lyx { namespace lyx {
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
@ -125,24 +127,26 @@ void InsetMathFrac::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
Dimension dim0, dim1, dim2; Dimension dim0, dim1, dim2;
// This could be simplified, including avoiding useless recalculation of
// cell metrics
if (kind_ == UNIT || (kind_ == UNITFRAC && nargs() == 3)) { if (kind_ == UNIT || (kind_ == UNITFRAC && nargs() == 3)) {
if (nargs() == 1) { if (nargs() == 1) {
ShapeChanger dummy2(mi.base.font, UP_SHAPE); Changer dummy = mi.base.font.changeShape(UP_SHAPE);
cell(0).metrics(mi, dim0); cell(0).metrics(mi, dim0);
dim.wid = dim0.width()+ 3; dim.wid = dim0.width()+ 3;
dim.asc = dim0.asc; dim.asc = dim0.asc;
dim.des = dim0.des; dim.des = dim0.des;
} else if (nargs() == 2) { } else if (nargs() == 2) {
cell(0).metrics(mi, dim0); cell(0).metrics(mi, dim0);
ShapeChanger dummy2(mi.base.font, UP_SHAPE); Changer dummy = mi.base.font.changeShape(UP_SHAPE);
cell(1).metrics(mi, dim1); cell(1).metrics(mi, dim1);
dim.wid = dim0.width() + dim1.wid + 5; dim.wid = dim0.width() + dim1.wid + 5;
dim.asc = max(dim0.asc, dim1.asc); dim.asc = max(dim0.asc, dim1.asc);
dim.des = max(dim0.des, dim1.des); dim.des = max(dim0.des, dim1.des);
} else { } else {
cell(2).metrics(mi, dim2); cell(2).metrics(mi, dim2);
ShapeChanger dummy2(mi.base.font, UP_SHAPE); Changer dummy = mi.base.font.changeShape(UP_SHAPE);
FracChanger dummy(mi.base); Changer dummy2 = mi.base.changeFrac();
cell(0).metrics(mi, dim0); cell(0).metrics(mi, dim0);
cell(1).metrics(mi, dim1); cell(1).metrics(mi, dim1);
dim.wid = dim0.width() + dim1.wid + dim2.wid + 10; dim.wid = dim0.width() + dim1.wid + dim2.wid + 10;
@ -151,31 +155,25 @@ void InsetMathFrac::metrics(MetricsInfo & mi, Dimension & dim) const
} }
} else { } else {
// general cell metrics used for \frac // general cell metrics used for \frac
FracChanger dummy(mi.base); Changer dummy = mi.base.changeFrac();
cell(0).metrics(mi, dim0); cell(0).metrics(mi, dim0);
cell(1).metrics(mi, dim1); cell(1).metrics(mi, dim1);
if (nargs() == 3) if (nargs() == 3)
cell(2).metrics(mi, dim2); cell(2).metrics(mi, dim2);
// metrics for special fraction types // metrics for special fraction types
if (kind_ == NICEFRAC) { if (kind_ == NICEFRAC || kind_ == UNITFRAC) {
dim.wid = dim0.width() + dim1.wid + 5; Changer dummy2 = mi.base.font.changeShape(UP_SHAPE, kind_ == UNITFRAC);
dim.asc = dim0.height() + 5;
dim.des = dim1.height() - 5;
} else if (kind_ == UNITFRAC) {
ShapeChanger dummy2(mi.base.font, UP_SHAPE);
dim.wid = dim0.width() + dim1.wid + 5; dim.wid = dim0.width() + dim1.wid + 5;
dim.asc = dim0.height() + 5; dim.asc = dim0.height() + 5;
dim.des = dim1.height() - 5; dim.des = dim1.height() - 5;
} else { } else {
if (kind_ == CFRAC || kind_ == CFRACLEFT if (kind_ == CFRAC || kind_ == CFRACLEFT || kind_ == CFRACRIGHT
|| kind_ == CFRACRIGHT || kind_ == DFRAC) { || kind_ == DFRAC || kind_ == TFRAC) {
// \cfrac and \dfrac are always in display size // \cfrac and \dfrac are always in display size
StyleChanger dummy2(mi.base, LM_ST_DISPLAY); // \tfrac is in always in text size
cell(0).metrics(mi, dim0); Changer dummy2 = mi.base.changeStyle((kind_ == TFRAC)
cell(1).metrics(mi, dim1); ? LM_ST_SCRIPT
} else if (kind_ == TFRAC) { : LM_ST_DISPLAY);
// tfrac is in always in text size
StyleChanger dummy2(mi.base, LM_ST_SCRIPT);
cell(0).metrics(mi, dim0); cell(0).metrics(mi, dim0);
cell(1).metrics(mi, dim1); cell(1).metrics(mi, dim1);
} }
@ -195,16 +193,16 @@ void InsetMathFrac::draw(PainterInfo & pi, int x, int y) const
Dimension const dim0 = cell(0).dimension(*pi.base.bv); Dimension const dim0 = cell(0).dimension(*pi.base.bv);
if (kind_ == UNIT || (kind_ == UNITFRAC && nargs() == 3)) { if (kind_ == UNIT || (kind_ == UNITFRAC && nargs() == 3)) {
if (nargs() == 1) { if (nargs() == 1) {
ShapeChanger dummy2(pi.base.font, UP_SHAPE); Changer dummy = pi.base.font.changeShape(UP_SHAPE);
cell(0).draw(pi, x + 1, y); cell(0).draw(pi, x + 1, y);
} else if (nargs() == 2) { } else if (nargs() == 2) {
cell(0).draw(pi, x + 1, y); cell(0).draw(pi, x + 1, y);
ShapeChanger dummy2(pi.base.font, UP_SHAPE); Changer dummy = pi.base.font.changeShape(UP_SHAPE);
cell(1).draw(pi, x + dim0.width() + 5, y); cell(1).draw(pi, x + dim0.width() + 5, y);
} else { } else {
cell(2).draw(pi, x + 1, y); cell(2).draw(pi, x + 1, y);
ShapeChanger dummy2(pi.base.font, UP_SHAPE); Changer dummy = pi.base.font.changeShape(UP_SHAPE);
FracChanger dummy(pi.base); Changer dummy2 = pi.base.changeFrac();
Dimension const dim1 = cell(1).dimension(*pi.base.bv); Dimension const dim1 = cell(1).dimension(*pi.base.bv);
Dimension const dim2 = cell(2).dimension(*pi.base.bv); Dimension const dim2 = cell(2).dimension(*pi.base.bv);
int xx = x + dim2.wid + 5; int xx = x + dim2.wid + 5;
@ -214,7 +212,7 @@ void InsetMathFrac::draw(PainterInfo & pi, int x, int y) const
y + dim1.asc / 2); y + dim1.asc / 2);
} }
} else { } else {
FracChanger dummy(pi.base); Changer dummy = pi.base.changeFrac();
Dimension const dim1 = cell(1).dimension(*pi.base.bv); Dimension const dim1 = cell(1).dimension(*pi.base.bv);
int m = x + dim.wid / 2; int m = x + dim.wid / 2;
if (kind_ == NICEFRAC) { if (kind_ == NICEFRAC) {
@ -223,20 +221,18 @@ void InsetMathFrac::draw(PainterInfo & pi, int x, int y) const
cell(1).draw(pi, x + dim0.width() + 5, cell(1).draw(pi, x + dim0.width() + 5,
y + dim1.asc / 2); y + dim1.asc / 2);
} else if (kind_ == UNITFRAC) { } else if (kind_ == UNITFRAC) {
ShapeChanger dummy2(pi.base.font, UP_SHAPE); Changer dummy2 = pi.base.font.changeShape(UP_SHAPE);
cell(0).draw(pi, x + 2, y - dim0.des - 5); cell(0).draw(pi, x + 2, y - dim0.des - 5);
cell(1).draw(pi, x + dim0.width() + 5, y + dim1.asc / 2); cell(1).draw(pi, x + dim0.width() + 5, y + dim1.asc / 2);
} else if (kind_ == FRAC || kind_ == ATOP || kind_ == OVER) { } else if (kind_ == FRAC || kind_ == ATOP || kind_ == OVER
cell(0).draw(pi, m - dim0.wid / 2, y - dim0.des - 2 - 5); || kind_ == TFRAC) {
cell(1).draw(pi, m - dim1.wid / 2, y + dim1.asc + 2 - 5);
} else if (kind_ == TFRAC) {
// tfrac is in always in text size // tfrac is in always in text size
StyleChanger dummy2(pi.base, LM_ST_SCRIPT); Changer dummy2 = pi.base.changeStyle(LM_ST_SCRIPT, kind_ == TFRAC);
cell(0).draw(pi, m - dim0.wid / 2, y - dim0.des - 2 - 5); cell(0).draw(pi, m - dim0.wid / 2, y - dim0.des - 2 - 5);
cell(1).draw(pi, m - dim1.wid / 2, y + dim1.asc + 2 - 5); cell(1).draw(pi, m - dim1.wid / 2, y + dim1.asc + 2 - 5);
} else { } else {
// \cfrac and \dfrac are always in display size // \cfrac and \dfrac are always in display size
StyleChanger dummy2(pi.base, LM_ST_DISPLAY); Changer dummy2 = pi.base.changeStyle(LM_ST_DISPLAY);
if (kind_ == CFRAC || kind_ == DFRAC) if (kind_ == CFRAC || kind_ == DFRAC)
cell(0).draw(pi, m - dim0.wid / 2, y - dim0.des - 2 - 5); cell(0).draw(pi, m - dim0.wid / 2, y - dim0.des - 2 - 5);
else if (kind_ == CFRACLEFT) else if (kind_ == CFRACLEFT)
@ -552,22 +548,12 @@ int InsetMathBinom::dw(int height) const
void InsetMathBinom::metrics(MetricsInfo & mi, Dimension & dim) const void InsetMathBinom::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
Dimension dim0, dim1; Dimension dim0, dim1;
Changer dummy =
// The cells must be set while the RAII objects (StyleChanger, (kind_ == DBINOM) ? mi.base.changeStyle(LM_ST_DISPLAY) :
// FracChanger) do still exist and cannot be set after the if case. (kind_ == TBINOM) ? mi.base.changeStyle(LM_ST_SCRIPT) :
if (kind_ == DBINOM) { mi.base.changeFrac();
StyleChanger dummy(mi.base, LM_ST_DISPLAY); cell(0).metrics(mi, dim0);
cell(0).metrics(mi, dim0); cell(1).metrics(mi, dim1);
cell(1).metrics(mi, dim1);
} else if (kind_ == TBINOM) {
StyleChanger dummy(mi.base, LM_ST_SCRIPT);
cell(0).metrics(mi, dim0);
cell(1).metrics(mi, dim1);
} else {
FracChanger dummy(mi.base);
cell(0).metrics(mi, dim0);
cell(1).metrics(mi, dim1);
}
dim.asc = dim0.height() + 4 + 5; dim.asc = dim0.height() + 4 + 5;
dim.des = dim1.height() + 4 - 5; dim.des = dim1.height() + 4 - 5;
dim.wid = max(dim0.wid, dim1.wid) + 2 * dw(dim.height()) + 4; dim.wid = max(dim0.wid, dim1.wid) + 2 * dw(dim.height()) + 4;
@ -587,18 +573,11 @@ void InsetMathBinom::draw(PainterInfo & pi, int x, int y) const
kind_ == BRACK ? from_ascii("]") : from_ascii(")"); kind_ == BRACK ? from_ascii("]") : from_ascii(")");
int m = x + dim.width() / 2; int m = x + dim.width() / 2;
// The cells must be drawn while the RAII objects (StyleChanger, {
// FracChanger) do still exist and cannot be drawn after the if case. Changer dummy =
if (kind_ == DBINOM) { (kind_ == DBINOM) ? pi.base.changeStyle(LM_ST_DISPLAY) :
StyleChanger dummy(pi.base, LM_ST_DISPLAY); (kind_ == TBINOM) ? pi.base.changeStyle(LM_ST_SCRIPT) :
cell(0).draw(pi, m - dim0.wid / 2, y - dim0.des - 3 - 5); pi.base.changeFrac();
cell(1).draw(pi, m - dim1.wid / 2, y + dim1.asc + 3 - 5);
} else if (kind_ == TBINOM) {
StyleChanger dummy(pi.base, LM_ST_SCRIPT);
cell(0).draw(pi, m - dim0.wid / 2, y - dim0.des - 3 - 5);
cell(1).draw(pi, m - dim1.wid / 2, y + dim1.asc + 3 - 5);
} else {
FracChanger dummy2(pi.base);
cell(0).draw(pi, m - dim0.wid / 2, y - dim0.des - 3 - 5); cell(0).draw(pi, m - dim0.wid / 2, y - dim0.des - 3 - 5);
cell(1).draw(pi, m - dim1.wid / 2, y + dim1.asc + 3 - 5); cell(1).draw(pi, m - dim1.wid / 2, y + dim1.asc + 3 - 5);
} }

View File

@ -487,8 +487,9 @@ void InsetMathHull::metrics(MetricsInfo & mi, Dimension & dim) const
return; return;
} }
FontSetChanger dummy1(mi.base, standardFont()); // FIXME: Changing the same object repeatedly is inefficient.
StyleChanger dummy2(mi.base, display() ? LM_ST_DISPLAY : LM_ST_TEXT); Changer dummy1 = mi.base.changeFontSet(standardFont());
Changer dummy2 = mi.base.changeStyle(display() ? LM_ST_DISPLAY : LM_ST_TEXT);
// let the cells adjust themselves // let the cells adjust themselves
InsetMathGrid::metrics(mi, dim); InsetMathGrid::metrics(mi, dim);
@ -499,7 +500,7 @@ void InsetMathHull::metrics(MetricsInfo & mi, Dimension & dim) const
} }
if (numberedType()) { if (numberedType()) {
FontSetChanger dummy(mi.base, from_ascii("mathbf")); Changer dummy = mi.base.changeFontSet(from_ascii("mathbf"));
int l = 0; int l = 0;
for (row_type row = 0; row < nrows(); ++row) for (row_type row = 0; row < nrows(); ++row)
l = max(l, mathed_string_width(mi.base.font, nicelabel(row))); l = max(l, mathed_string_width(mi.base.font, nicelabel(row)));
@ -580,9 +581,9 @@ void InsetMathHull::draw(PainterInfo & pi, int x, int y) const
ColorCode color = pi.selected && lyxrc.use_system_colors ColorCode color = pi.selected && lyxrc.use_system_colors
? Color_selectiontext : standardColor(); ? Color_selectiontext : standardColor();
bool const really_change_color = pi.base.font.color() == Color_none; bool const really_change_color = pi.base.font.color() == Color_none;
ColorChanger dummy0(pi.base.font, color, really_change_color); Changer dummy0 = pi.base.font.changeColor(color, really_change_color);
FontSetChanger dummy1(pi.base, standardFont()); Changer dummy1 = pi.base.changeFontSet(standardFont());
StyleChanger dummy2(pi.base, display() ? LM_ST_DISPLAY : LM_ST_TEXT); Changer dummy2 = pi.base.changeStyle(display() ? LM_ST_DISPLAY : LM_ST_TEXT);
InsetMathGrid::draw(pi, x + 1, y); InsetMathGrid::draw(pi, x + 1, y);
@ -590,7 +591,7 @@ void InsetMathHull::draw(PainterInfo & pi, int x, int y) const
int const xx = x + colinfo_.back().offset_ + colinfo_.back().width_ + 20; int const xx = x + colinfo_.back().offset_ + colinfo_.back().width_ + 20;
for (row_type row = 0; row < nrows(); ++row) { for (row_type row = 0; row < nrows(); ++row) {
int const yy = y + rowinfo_[row].offset_; int const yy = y + rowinfo_[row].offset_;
FontSetChanger dummy(pi.base, from_ascii("mathrm")); Changer dummy = pi.base.changeFontSet(from_ascii("mathrm"));
docstring const nl = nicelabel(row); docstring const nl = nicelabel(row);
pi.draw(xx, yy, nl); pi.draw(xx, yy, nl);
} }

View File

@ -31,7 +31,7 @@ void InsetMathOverset::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
Dimension dim1; Dimension dim1;
cell(1).metrics(mi, dim1); cell(1).metrics(mi, dim1);
FracChanger dummy(mi.base); Changer dummy = mi.base.changeFrac();
Dimension dim0; Dimension dim0;
cell(0).metrics(mi, dim0); cell(0).metrics(mi, dim0);
dim.wid = max(dim0.width(), dim1.wid) + 4; dim.wid = max(dim0.width(), dim1.wid) + 4;
@ -49,7 +49,7 @@ void InsetMathOverset::draw(PainterInfo & pi, int x, int y) const
int m = x + dim.wid / 2; int m = x + dim.wid / 2;
int yo = y - dim1.asc - dim0.des - 1; int yo = y - dim1.asc - dim0.des - 1;
cell(1).draw(pi, m - dim1.wid / 2, y); cell(1).draw(pi, m - dim1.wid / 2, y);
FracChanger dummy(pi.base); Changer dummy = pi.base.changeFrac();
cell(0).draw(pi, m - dim0.width() / 2, yo); cell(0).draw(pi, m - dim0.width() / 2, yo);
drawMarkers(pi, x, y); drawMarkers(pi, x, y);
} }

View File

@ -28,14 +28,14 @@ InsetMathPar::InsetMathPar(Buffer * buf, MathData const & ar)
void InsetMathPar::metrics(MetricsInfo & mi, Dimension & dim) const void InsetMathPar::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
FontSetChanger dummy1(mi.base, "textnormal"); Changer dummy = mi.base.changeFontSet("textnormal");
InsetMathGrid::metrics(mi, dim); InsetMathGrid::metrics(mi, dim);
} }
void InsetMathPar::draw(PainterInfo & pi, int x, int y) const void InsetMathPar::draw(PainterInfo & pi, int x, int y) const
{ {
FontSetChanger dummy1(pi.base, "textnormal"); Changer dummy = pi.base.changeFontSet("textnormal");
InsetMathGrid::draw(pi, x, y); InsetMathGrid::draw(pi, x, y);
} }

View File

@ -277,7 +277,7 @@ void InsetMathScript::metrics(MetricsInfo & mi, Dimension & dim) const
Dimension dim1; Dimension dim1;
Dimension dim2; Dimension dim2;
cell(0).metrics(mi, dim0); cell(0).metrics(mi, dim0);
ScriptChanger dummy(mi.base); Changer dummy = mi.base.changeScript();
if (nargs() > 1) if (nargs() > 1)
cell(1).metrics(mi, dim1); cell(1).metrics(mi, dim1);
if (nargs() > 2) if (nargs() > 2)
@ -332,7 +332,7 @@ void InsetMathScript::draw(PainterInfo & pi, int x, int y) const
if (editing(&bv)) if (editing(&bv))
pi.draw(x + dxx(bv), y, char_type('.')); pi.draw(x + dxx(bv), y, char_type('.'));
} }
ScriptChanger dummy(pi.base); Changer dummy = pi.base.changeScript();
if (hasUp()) if (hasUp())
up().draw(pi, x + dx1(bv), y - dy1(bv)); up().draw(pi, x + dx1(bv), y - dy1(bv));
if (hasDown()) if (hasDown())

View File

@ -197,7 +197,7 @@ void InsetMathSideset::metrics(MetricsInfo & mi, Dimension & dim) const
br().metrics(mi, dimbr); br().metrics(mi, dimbr);
dimtr = dimbr; dimtr = dimbr;
} }
ScriptChanger dummy(mi.base); Changer dummy = mi.base.changeScript();
if (scriptl_) { if (scriptl_) {
bl().metrics(mi, dimbl); bl().metrics(mi, dimbl);
tl().metrics(mi, dimtl); tl().metrics(mi, dimtl);
@ -231,7 +231,7 @@ void InsetMathSideset::draw(PainterInfo & pi, int x, int y) const
bl().draw(pi, x , y); bl().draw(pi, x , y);
if (!scriptr_) if (!scriptr_)
br().draw(pi, x + dxr(bv), y); br().draw(pi, x + dxr(bv), y);
ScriptChanger dummy(pi.base); Changer dummy = pi.base.changeScript();
if (scriptl_) { if (scriptl_) {
bl().draw(pi, x , y + dyb(bv)); bl().draw(pi, x , y + dyb(bv));
tl().draw(pi, x , y - dyt(bv)); tl().draw(pi, x , y - dyt(bv));

View File

@ -43,7 +43,7 @@ Inset * InsetMathSize::clone() const
void InsetMathSize::metrics(MetricsInfo & mi, Dimension & dim) const void InsetMathSize::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
StyleChanger dummy(mi.base, style_); Changer dummy = mi.base.changeStyle(style_);
cell(0).metrics(mi, dim); cell(0).metrics(mi, dim);
metricsMarkers(dim); metricsMarkers(dim);
} }
@ -51,7 +51,7 @@ void InsetMathSize::metrics(MetricsInfo & mi, Dimension & dim) const
void InsetMathSize::draw(PainterInfo & pi, int x, int y) const void InsetMathSize::draw(PainterInfo & pi, int x, int y) const
{ {
StyleChanger dummy(pi.base, style_); Changer dummy = pi.base.changeStyle(style_);
cell(0).draw(pi, x + 1, y); cell(0).draw(pi, x + 1, y);
drawMarkers(pi, x, y); drawMarkers(pi, x, y);
} }

View File

@ -56,7 +56,7 @@ Inset * InsetMathSpecialChar::clone() const
void InsetMathSpecialChar::metrics(MetricsInfo & mi, Dimension & dim) const void InsetMathSpecialChar::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
if (mi.base.fontname == "mathnormal") { if (mi.base.fontname == "mathnormal") {
ShapeChanger dummy(mi.base.font, UP_SHAPE); Changer dummy = mi.base.font.changeShape(UP_SHAPE);;
dim = theFontMetrics(mi.base.font).dimension(char_); dim = theFontMetrics(mi.base.font).dimension(char_);
} else { } else {
frontend::FontMetrics const & fm = theFontMetrics(mi.base.font); frontend::FontMetrics const & fm = theFontMetrics(mi.base.font);
@ -69,7 +69,7 @@ void InsetMathSpecialChar::metrics(MetricsInfo & mi, Dimension & dim) const
void InsetMathSpecialChar::draw(PainterInfo & pi, int x, int y) const void InsetMathSpecialChar::draw(PainterInfo & pi, int x, int y) const
{ {
if (pi.base.fontname == "mathnormal") { if (pi.base.fontname == "mathnormal") {
ShapeChanger dummy(pi.base.font, UP_SHAPE); Changer dummy = pi.base.font.changeShape(UP_SHAPE);
pi.draw(x, y, char_); pi.draw(x, y, char_);
} else { } else {
pi.draw(x, y, char_); pi.draw(x, y, char_);

View File

@ -54,7 +54,7 @@ void InsetMathStackrel::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
Dimension dim1; Dimension dim1;
cell(1).metrics(mi, dim1); cell(1).metrics(mi, dim1);
FracChanger dummy(mi.base); Changer dummy = mi.base.changeFrac();
Dimension dim0; Dimension dim0;
cell(0).metrics(mi, dim0); cell(0).metrics(mi, dim0);
if (nargs() > 2) { if (nargs() > 2) {
@ -80,7 +80,7 @@ void InsetMathStackrel::draw(PainterInfo & pi, int x, int y) const
int m = x + dim.width() / 2; int m = x + dim.width() / 2;
int yo = y - dim1.ascent() - dim0.descent() - 1; int yo = y - dim1.ascent() - dim0.descent() - 1;
cell(1).draw(pi, m - dim1.width() / 2, y); cell(1).draw(pi, m - dim1.width() / 2, y);
FracChanger dummy(pi.base); Changer dummy = pi.base.changeFrac();
cell(0).draw(pi, m - dim0.width() / 2, yo); cell(0).draw(pi, m - dim0.width() / 2, yo);
if (nargs() > 2) { if (nargs() > 2) {
Dimension const & dim2 = cell(2).dimension(*pi.base.bv); Dimension const & dim2 = cell(2).dimension(*pi.base.bv);

View File

@ -44,17 +44,14 @@ Inset * InsetMathSubstack::clone() const
void InsetMathSubstack::metrics(MetricsInfo & mi, Dimension & dim) const void InsetMathSubstack::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
if (mi.base.style == LM_ST_DISPLAY) { Changer dummy = mi.base.changeStyle(LM_ST_TEXT, mi.base.style == LM_ST_DISPLAY);
StyleChanger dummy(mi.base, LM_ST_TEXT); InsetMathGrid::metrics(mi, dim);
InsetMathGrid::metrics(mi, dim);
} else {
InsetMathGrid::metrics(mi, dim);
}
} }
void InsetMathSubstack::draw(PainterInfo & pi, int x, int y) const void InsetMathSubstack::draw(PainterInfo & pi, int x, int y) const
{ {
Changer dummy = pi.base.changeStyle(LM_ST_TEXT, pi.base.style == LM_ST_DISPLAY);
InsetMathGrid::draw(pi, x + 1, y); InsetMathGrid::draw(pi, x + 1, y);
} }

View File

@ -21,6 +21,7 @@
#include "support/debug.h" #include "support/debug.h"
#include "support/docstream.h" #include "support/docstream.h"
#include "support/lyxlib.h"
#include "support/textutils.h" #include "support/textutils.h"
#include "support/unique_ptr.h" #include "support/unique_ptr.h"
@ -66,7 +67,7 @@ void InsetMathSymbol::metrics(MetricsInfo & mi, Dimension & dim) const
sym_->extra == "mathalpha" && sym_->extra == "mathalpha" &&
mi.base.fontname == "mathit"; mi.base.fontname == "mathit";
std::string const font = italic_upcase_greek ? "cmm" : sym_->inset; std::string const font = italic_upcase_greek ? "cmm" : sym_->inset;
FontSetChanger dummy(mi.base, from_ascii(font)); Changer dummy = mi.base.changeFontSet(from_ascii(font));
mathed_string_dim(mi.base.font, sym_->draw, dim); mathed_string_dim(mi.base.font, sym_->draw, dim);
docstring::const_reverse_iterator rit = sym_->draw.rbegin(); docstring::const_reverse_iterator rit = sym_->draw.rbegin();
kerning_ = mathed_char_kerning(mi.base.font, *rit); kerning_ = mathed_char_kerning(mi.base.font, *rit);
@ -115,7 +116,7 @@ void InsetMathSymbol::draw(PainterInfo & pi, int x, int y) const
//else //else
// x += support::iround(0.0833 * em); // x += support::iround(0.0833 * em);
FontSetChanger dummy(pi.base, from_ascii(font)); Changer dummy = pi.base.changeFontSet(from_ascii(font));
pi.draw(x, y - h_, sym_->draw); pi.draw(x, y - h_, sym_->draw);
} }

View File

@ -43,7 +43,7 @@ Inset * InsetMathTabular::clone() const
void InsetMathTabular::metrics(MetricsInfo & mi, Dimension & dim) const void InsetMathTabular::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
FontSetChanger dummy(mi.base, "textnormal"); Changer dummy = mi.base.changeFontSet("textnormal");
InsetMathGrid::metrics(mi, dim); InsetMathGrid::metrics(mi, dim);
dim.wid += 6; dim.wid += 6;
} }
@ -59,7 +59,7 @@ Dimension const InsetMathTabular::dimension(BufferView const & bv) const
void InsetMathTabular::draw(PainterInfo & pi, int x, int y) const void InsetMathTabular::draw(PainterInfo & pi, int x, int y) const
{ {
FontSetChanger dummy(pi.base, "textnormal"); Changer dummy = pi.base.changeFontSet("textnormal");
InsetMathGrid::drawWithMargin(pi, x, y, 4, 2); InsetMathGrid::drawWithMargin(pi, x, y, 4, 2);
} }

View File

@ -31,7 +31,7 @@ void InsetMathUnderset::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
Dimension dim1; Dimension dim1;
cell(1).metrics(mi, dim1); cell(1).metrics(mi, dim1);
FracChanger dummy(mi.base); Changer dummy = mi.base.changeFrac();
Dimension dim0; Dimension dim0;
cell(0).metrics(mi, dim0); cell(0).metrics(mi, dim0);
dim.wid = max(dim0.width(), dim1.width()) + 4; dim.wid = max(dim0.width(), dim1.width()) + 4;
@ -49,7 +49,7 @@ void InsetMathUnderset::draw(PainterInfo & pi, int x, int y) const
int m = x + dim.wid / 2; int m = x + dim.wid / 2;
int yo = y + dim1.descent() + dim0.ascent() + 1; int yo = y + dim1.descent() + dim0.ascent() + 1;
cell(1).draw(pi, m - dim1.width() / 2, y); cell(1).draw(pi, m - dim1.width() / 2, y);
FracChanger dummy(pi.base); Changer dummy = pi.base.changeFrac();
cell(0).draw(pi, m - dim0.width() / 2, yo); cell(0).draw(pi, m - dim0.width() / 2, yo);
drawMarkers(pi, x, y); drawMarkers(pi, x, y);
} }

View File

@ -40,7 +40,7 @@ Inset * InsetMathXArrow::clone() const
void InsetMathXArrow::metrics(MetricsInfo & mi, Dimension & dim) const void InsetMathXArrow::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
ScriptChanger dummy(mi.base); Changer dummy = mi.base.changeScript();
Dimension dim0; Dimension dim0;
cell(0).metrics(mi, dim0); cell(0).metrics(mi, dim0);
Dimension dim1; Dimension dim1;
@ -54,7 +54,7 @@ void InsetMathXArrow::metrics(MetricsInfo & mi, Dimension & dim) const
void InsetMathXArrow::draw(PainterInfo & pi, int x, int y) const void InsetMathXArrow::draw(PainterInfo & pi, int x, int y) const
{ {
ScriptChanger dummy(pi.base); Changer dummy = pi.base.changeScript();
Dimension const dim = dimension(*pi.base.bv); Dimension const dim = dimension(*pi.base.bv);
Dimension const & dim0 = cell(0).dimension(*pi.base.bv); Dimension const & dim0 = cell(0).dimension(*pi.base.bv);
// center the cells with the decoration // center the cells with the decoration

View File

@ -82,8 +82,8 @@ MathData const & InsetMathXYArrow::sourceCell() const
bool InsetMathXYArrow::metrics(MetricsInfo & mi) const bool InsetMathXYArrow::metrics(MetricsInfo & mi) const
{ {
InsetMathNest::metrics(mi); InsetMathNest::metrics(mi);
mi_ = mi; mi_ = mi;
FontSetChanger dummy(mi.base, "textrm"); Changer dummy = mi.base.changeFontSet(mi.base, "textrm");
#if 0 #if 0
target_ = mi.inset ? mi.inset->asXYMatrixInset() : 0; target_ = mi.inset ? mi.inset->asXYMatrixInset() : 0;
@ -105,7 +105,7 @@ bool InsetMathXYArrow::metrics(MetricsInfo & mi) const
void InsetMathXYArrow::draw(PainterInfo & pi, int x, int y) const void InsetMathXYArrow::draw(PainterInfo & pi, int x, int y) const
{ {
metrics(mi_); metrics(mi_);
FontSetChanger dummy(pi.base, "textrm"); Changer dummy = pi.base.changeFontSet(pi.base, "textrm");
if (editing()) { if (editing()) {

View File

@ -551,10 +551,10 @@ void MathMacro::draw(PainterInfo & pi, int x, int y) const
int expy = y; int expy = y;
if (d->displayMode_ == DISPLAY_INIT || d->displayMode_ == DISPLAY_INTERACTIVE_INIT) { if (d->displayMode_ == DISPLAY_INIT || d->displayMode_ == DISPLAY_INTERACTIVE_INIT) {
FontSetChanger dummy(pi.base, "lyxtex"); Changer dummy = pi.base.changeFontSet("lyxtex");
pi.pain.text(x, y, from_ascii("\\") + name(), pi.base.font); pi.pain.text(x, y, from_ascii("\\") + name(), pi.base.font);
} else if (d->displayMode_ == DISPLAY_UNFOLDED) { } else if (d->displayMode_ == DISPLAY_UNFOLDED) {
FontSetChanger dummy(pi.base, "lyxtex"); Changer dummy = pi.base.changeFontSet("lyxtex");
pi.pain.text(x, y, from_ascii("\\"), pi.base.font); pi.pain.text(x, y, from_ascii("\\"), pi.base.font);
x += mathed_string_width(pi.base.font, from_ascii("\\")) + 1; x += mathed_string_width(pi.base.font, from_ascii("\\")) + 1;
cell(0).draw(pi, x, y); cell(0).draw(pi, x, y);

View File

@ -542,8 +542,8 @@ void MathMacroTemplate::createLook(int args) const
void MathMacroTemplate::metrics(MetricsInfo & mi, Dimension & dim) const void MathMacroTemplate::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
FontSetChanger dummy1(mi.base, from_ascii("mathnormal")); Changer dummy1 = mi.base.changeFontSet(from_ascii("mathnormal"));
StyleChanger dummy2(mi.base, LM_ST_TEXT); Changer dummy2 = mi.base.changeStyle(LM_ST_TEXT);
// valid macro? // valid macro?
MacroData const * macro = 0; MacroData const * macro = 0;
@ -584,9 +584,10 @@ void MathMacroTemplate::metrics(MetricsInfo & mi, Dimension & dim) const
void MathMacroTemplate::draw(PainterInfo & pi, int x, int y) const void MathMacroTemplate::draw(PainterInfo & pi, int x, int y) const
{ {
ColorChanger dummy0(pi.base.font, Color_math); // FIXME: Calling Changer on the same object repeatedly is inefficient.
FontSetChanger dummy1(pi.base, from_ascii("mathnormal")); Changer dummy0 = pi.base.font.changeColor(Color_math);
StyleChanger dummy2(pi.base, LM_ST_TEXT); Changer dummy1 = pi.base.changeFontSet(from_ascii("mathnormal"));
Changer dummy2 = pi.base.changeStyle(LM_ST_TEXT);
setPosCache(pi, x, y); setPosCache(pi, x, y);
Dimension const dim = dimension(*pi.base.bv); Dimension const dim = dimension(*pi.base.bv);

32
src/support/Changer.h Normal file
View File

@ -0,0 +1,32 @@
// -*- C++ -*-
/**
* \file Changer.h
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Guillaume Munch
*
* Full author contact details are available in file CREDITS.
*/
#ifndef LYX_CHANGER_H
#define LYX_CHANGER_H
#include "support/unique_ptr.h"
namespace lyx {
// Forward declaration for support/RefChanger.h
struct Revertible {
virtual ~Revertible() {}
virtual void revert() {}
virtual void keep() {}
};
using Changer = unique_ptr<Revertible>;
}
#endif //LYX_CHANGER_H

View File

@ -35,6 +35,7 @@ liblyxsupport_a_SOURCES = \
FileMonitor.cpp \ FileMonitor.cpp \
RandomAccessList.h \ RandomAccessList.h \
bind.h \ bind.h \
Change.h \
ConsoleApplication.cpp \ ConsoleApplication.cpp \
ConsoleApplication.h \ ConsoleApplication.h \
ConsoleApplicationPrivate.h \ ConsoleApplicationPrivate.h \
@ -90,6 +91,7 @@ liblyxsupport_a_SOURCES = \
qstring_helpers.cpp \ qstring_helpers.cpp \
qstring_helpers.h \ qstring_helpers.h \
regex.h \ regex.h \
RefChanger.h \
socktools.cpp \ socktools.cpp \
socktools.h \ socktools.h \
strfwd.h \ strfwd.h \

74
src/support/RefChanger.h Normal file
View File

@ -0,0 +1,74 @@
// -*- C++ -*-
/**
* \file RefChanger.h
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Guillaume Munch
*
* Full author contact details are available in file CREDITS.
*/
#ifndef LYX_REFCHANGER_H
#define LYX_REFCHANGER_H
#include "support/Changer.h"
namespace lyx {
/// A RefChanger records the current value of \param ref, allowing to
/// temporarily assign new values to it. The original value is restored
/// automatically when the object is destroyed, unless it is disabled.
///
/// RefChanger is movable, and doing so prolongs the duration of the temporary
/// assignment. This allows classes to supply their own changer methods.
///
/// Naturally, be careful not to extend the life of a RefChanger beyond that of
/// the reference it modifies. The RefChanger can be disabled by calling
/// ->keep() or ->revert(). Once disabled, the reference is never accessed
/// again.
template<typename X>
class RevertibleRef : public Revertible {
public:
RevertibleRef(X & ref) : ref(ref), old(ref), enabled(true) {}
//
~RevertibleRef() { revert(); }
//
void revert() { if (enabled) { enabled = false; ref = old; } }
//
void keep() { enabled = false; }
//
X & ref;
X const old;
private:
bool enabled;
};
template <typename X> using RefChanger = unique_ptr<RevertibleRef<X>>;
/// Saves the value of \param ref in a movable object
template <typename X> RefChanger<X> make_save(X & ref)
{
return make_unique<RevertibleRef<X>>(ref);
}
/// Temporarily assign value \param val to \param ref. If \param cond is false,
/// then the assignation does not happen and the RefChanger starts disabled.
template <typename X>
RefChanger<X> make_change(X & ref, X const val, bool cond = true)
{
auto rc = make_save(ref);
if (!cond)
rc->keep();
else
ref = val;
return rc;
}
}
#endif //LYX_REFCHANGER_H