Remove a conversion to_utf8() inside FontSetChanger

This requires to change many docstrings into std::strings. The logic behind that
is that they represent a fixed set of math fonts, and therefore “string” means
here “poor man's enum” rather than text (this is consistent with MetricsBase).

Profiling of scrolling inside a document over macro-instensive areas:

Before the patch:
  44,1% BufferView::updateMetrics()
   -> 34,8% InsetMathHull::metrics()
     -> 9,8% FontSetChanger::FontSetChanger()
  28,4% BufferView::draw()

After the patch:
  35,3% BufferView::updateMetrics()
   -> 27,2% InsetMathHull::metrics
     -> 0,4% FontSetChanger::FontSetChanger()
  47,5% BufferView::draw()

FontSetChanger::FontSetChanger() is made 41x less expensive (with reference
BV::draw()) just by removing this conversion. The remaining 0,4% could be
squished by replacing the strings with a proper enum, but this is premature. Of
course, this only treats the symptoms: there is no good reason that this
function is called 45500 times over the time of 40 repaints.
This commit is contained in:
Guillaume Munch 2016-06-07 22:58:55 +01:00
parent 325c476bcb
commit b2b8733096
18 changed files with 88 additions and 75 deletions

View File

@ -66,15 +66,15 @@ MetricsBase::MetricsBase(BufferView * b, FontInfo f, int w)
}
Changer MetricsBase::changeFontSet(docstring const & name, bool cond)
Changer MetricsBase::changeFontSet(string 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);
string const oldname = fontname;
fontname = name;
font = sane_font;
augmentFont(font, name);
font.setSize(rc->old.font.size());
@ -87,12 +87,6 @@ Changer MetricsBase::changeFontSet(docstring const & name, bool cond)
}
Changer MetricsBase::changeFontSet(char const * name, bool cond)
{
return changeFontSet(from_ascii(name), cond);
}
/////////////////////////////////////////////////////////////////////////
//
// MetricsInfo

View File

@ -68,8 +68,7 @@ public:
int textwidth;
/// Temporarily change a full font.
Changer changeFontSet(docstring const & font, bool cond = true);
Changer changeFontSet(char const * font, bool cond = true);
Changer changeFontSet(std::string 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

View File

@ -50,7 +50,7 @@ void InsetMathBrace::metrics(MetricsInfo & mi, Dimension & dim) const
Dimension dim0;
cell(0).metrics(mi, dim0);
FontInfo font = mi.base.font;
augmentFont(font, from_ascii("mathnormal"));
augmentFont(font, "mathnormal");
Dimension t = theFontMetrics(font).dimension('{');
dim.asc = max(dim0.asc, t.asc);
dim.des = max(dim0.des, t.des);
@ -62,7 +62,7 @@ void InsetMathBrace::metrics(MetricsInfo & mi, Dimension & dim) const
void InsetMathBrace::draw(PainterInfo & pi, int x, int y) const
{
FontInfo font = pi.base.font;
augmentFont(font, from_ascii("mathnormal"));
augmentFont(font, "mathnormal");
font.setShape(UP_SHAPE);
font.setColor(Color_latex);
Dimension t = theFontMetrics(font).dimension('{');

View File

@ -106,7 +106,7 @@ InsetMath::mode_type InsetMathDecoration::currentMode() const
void InsetMathDecoration::metrics(MetricsInfo & mi, Dimension & dim) const
{
bool really_change_font = currentMode() == TEXT_MODE
&& isMathFont(from_ascii(mi.base.fontname));
&& isMathFont(mi.base.fontname);
Changer dummy = mi.base.changeFontSet("textnormal", really_change_font);
cell(0).metrics(mi, dim);
@ -129,7 +129,7 @@ void InsetMathDecoration::metrics(MetricsInfo & mi, Dimension & dim) const
void InsetMathDecoration::draw(PainterInfo & pi, int x, int y) const
{
bool really_change_font = currentMode() == TEXT_MODE
&& isMathFont(from_ascii(pi.base.fontname));
&& isMathFont(pi.base.fontname);
Changer dummy = pi.base.changeFontSet("textnormal", really_change_font);
cell(0).draw(pi, x + 1, y);

View File

@ -38,7 +38,7 @@ Inset * InsetMathEnsureMath::clone() const
void InsetMathEnsureMath::metrics(MetricsInfo & mi, Dimension & dim) const
{
bool really_change_font = isTextFont(from_ascii(mi.base.fontname));
bool really_change_font = isTextFont(mi.base.fontname);
Changer dummy = mi.base.changeFontSet("mathnormal", really_change_font);
cell(0).metrics(mi, dim);
metricsMarkers(dim);
@ -47,7 +47,7 @@ void InsetMathEnsureMath::metrics(MetricsInfo & mi, Dimension & dim) 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(pi.base.fontname);
Changer dummy = pi.base.changeFontSet("mathnormal", really_change_font);
cell(0).draw(pi, x, y);
drawMarkers(pi, x, y);

View File

@ -19,6 +19,7 @@
#include "MetricsInfo.h"
#include "support/gettext.h"
#include "support/lassert.h"
#include "support/lstrings.h"
#include <ostream>
@ -38,6 +39,13 @@ Inset * InsetMathFont::clone() const
}
std::string InsetMathFont::font() const
{
LASSERT(isAscii(key_->name), return "mathnormal");
return to_ascii(key_->name);
}
InsetMath::mode_type InsetMathFont::currentMode() const
{
if (key_->extra == "mathmode")
@ -58,7 +66,7 @@ bool InsetMathFont::lockedMode() const
void InsetMathFont::metrics(MetricsInfo & mi, Dimension & dim) const
{
Changer dummy = mi.base.changeFontSet(key_->name);
Changer dummy = mi.base.changeFontSet(font());
cell(0).metrics(mi, dim);
metricsMarkers(dim);
}
@ -66,7 +74,7 @@ void InsetMathFont::metrics(MetricsInfo & mi, Dimension & dim) const
void InsetMathFont::draw(PainterInfo & pi, int x, int y) const
{
Changer dummy = pi.base.changeFontSet(key_->name);
Changer dummy = pi.base.changeFontSet(font());
cell(0).draw(pi, x + 1, y);
drawMarkers(pi, x, y);
setPosCache(pi, x, y);
@ -96,19 +104,20 @@ docstring InsetMathFont::name() const
void InsetMathFont::validate(LaTeXFeatures & features) const
{
InsetMathNest::validate(features);
std::string fontname = font();
if (features.runparams().isLaTeX()) {
// Make sure amssymb is put in preamble if Blackboard Bold or
// Fraktur used:
if (key_->name == "mathfrak" || key_->name == "mathbb")
if (fontname == "mathfrak" || fontname == "mathbb")
features.require("amssymb");
if (key_->name == "text" || key_->name == "textnormal"
|| (key_->name.length() == 6 && key_->name.substr(0, 4) == "text"))
if (fontname == "text" || fontname == "textnormal"
|| (fontname.length() == 6 && fontname.substr(0, 4) == "text"))
features.require("amstext");
if (key_->name == "mathscr")
if (fontname == "mathscr")
features.require("mathrsfs");
if (key_->name == "textipa")
if (fontname == "textipa")
features.require("tipa");
if (key_->name == "ce" || key_->name == "cf")
if (fontname == "ce" || fontname == "cf")
features.require("mhchem");
} else if (features.runparams().math_flavor == OutputParams::MathAsHTML) {
features.addCSSSnippet(

View File

@ -57,6 +57,8 @@ public:
InsetCode lyxCode() const { return MATH_FONT_CODE; }
private:
std::string font() const;
///
virtual Inset * clone() const;
/// the font to be used on screen
latexkeys const * key_;

View File

@ -19,6 +19,7 @@
#include "MetricsInfo.h"
#include "support/gettext.h"
#include "support/lassert.h"
#include "support/lstrings.h"
#include <ostream>
@ -34,6 +35,13 @@ InsetMathFontOld::InsetMathFontOld(Buffer * buf, latexkeys const * key)
}
std::string InsetMathFontOld::font() const
{
LASSERT(isAscii(key_->name), return "mathnormal");
return to_ascii(key_->name);
}
Inset * InsetMathFontOld::clone() const
{
return new InsetMathFontOld(*this);
@ -42,16 +50,16 @@ Inset * InsetMathFontOld::clone() const
void InsetMathFontOld::metrics(MetricsInfo & mi, Dimension & dim) const
{
current_mode_ = isTextFont(from_ascii(mi.base.fontname))
current_mode_ = isTextFont(mi.base.fontname)
? TEXT_MODE : MATH_MODE;
docstring const font = current_mode_ == MATH_MODE
? "math" + key_->name : "text" + key_->name;
std::string const fontname = current_mode_ == MATH_MODE
? "math" + font() : "text" + font();// I doubt that this still works
// When \cal is used in text mode, the font is not changed
bool really_change_font = font != "textcal";
bool really_change_font = fontname != "textcal";
Changer dummy = mi.base.changeFontSet(font, really_change_font);
Changer dummy = mi.base.changeFontSet(fontname, really_change_font);
cell(0).metrics(mi, dim);
metricsMarkers(dim);
}
@ -59,16 +67,16 @@ void InsetMathFontOld::metrics(MetricsInfo & mi, Dimension & dim) const
void InsetMathFontOld::draw(PainterInfo & pi, int x, int y) const
{
current_mode_ = isTextFont(from_ascii(pi.base.fontname))
current_mode_ = isTextFont(pi.base.fontname)
? TEXT_MODE : MATH_MODE;
docstring const font = current_mode_ == MATH_MODE
? "math" + key_->name : "text" + key_->name;
std::string const fontname = current_mode_ == MATH_MODE
? "math" + font() : "text" + font();// I doubt that this still works
// When \cal is used in text mode, the font is not changed
bool really_change_font = font != "textcal";
bool really_change_font = fontname != "textcal";
Changer dummy = pi.base.changeFontSet(font, really_change_font);
Changer dummy = pi.base.changeFontSet(fontname, really_change_font);
cell(0).draw(pi, x + 1, y);
drawMarkers(pi, x, y);
}

View File

@ -49,6 +49,8 @@ public:
InsetCode lyxCode() const { return MATH_FONTOLD_CODE; }
private:
std::string font() const;
///
virtual Inset * clone() const;
/// the font to be used on screen
latexkeys const * key_;

View File

@ -426,15 +426,15 @@ int InsetMathHull::defaultColSpace(col_type col)
}
docstring InsetMathHull::standardFont() const
string InsetMathHull::standardFont() const
{
switch (type_) {
case hullRegexp:
return from_ascii("texttt");
return "texttt";
case hullNone:
return from_ascii("lyxnochange");
return "lyxnochange";
default:
return from_ascii("mathnormal");
return "mathnormal";
}
}
@ -501,7 +501,7 @@ void InsetMathHull::metrics(MetricsInfo & mi, Dimension & dim) const
}
if (numberedType()) {
Changer dummy = mi.base.changeFontSet(from_ascii("mathbf"));
Changer dummy = mi.base.changeFontSet("mathbf");
int l = 0;
for (row_type row = 0; row < nrows(); ++row)
l = max(l, mathed_string_width(mi.base.font, nicelabel(row)));
@ -592,7 +592,7 @@ void InsetMathHull::draw(PainterInfo & pi, int x, int y) const
int const xx = x + colinfo_.back().offset_ + colinfo_.back().width_ + 20;
for (row_type row = 0; row < nrows(); ++row) {
int const yy = y + rowinfo_[row].offset_;
Changer dummy = pi.base.changeFontSet(from_ascii("mathrm"));
Changer dummy = pi.base.changeFontSet("mathrm");
docstring const nl = nicelabel(row);
pi.draw(xx, yy, nl);
}

View File

@ -235,7 +235,7 @@ private:
/// change number of columns, split or combine columns if necessary.
void changeCols(col_type);
///
docstring standardFont() const;
std::string standardFont() const;
///
ColorCode standardColor() const;
/// consistency check

View File

@ -69,7 +69,7 @@ void InsetMathSymbol::metrics(MetricsInfo & mi, Dimension & dim) const
sym_->extra == "mathalpha" &&
mi.base.fontname == "mathit";
std::string const font = italic_upcase_greek ? "cmm" : sym_->inset;
Changer dummy = mi.base.changeFontSet(from_ascii(font));
Changer dummy = mi.base.changeFontSet(font);
mathed_string_dim(mi.base.font, sym_->draw, dim);
docstring::const_reverse_iterator rit = sym_->draw.rbegin();
kerning_ = mathed_char_kerning(mi.base.font, *rit);
@ -118,7 +118,7 @@ void InsetMathSymbol::draw(PainterInfo & pi, int x, int y) const
//else
// x += support::iround(0.0833 * em);
Changer dummy = pi.base.changeFontSet(from_ascii(font));
Changer dummy = pi.base.changeFontSet(font);
pi.draw(x, y - h_, sym_->draw);
}

View File

@ -285,7 +285,7 @@ void MathData::metrics(MetricsInfo & mi, Dimension & dim) const
continue;
FontInfo font = mi.base.font;
augmentFont(font, from_ascii("mathnormal"));
augmentFont(font, "mathnormal");
dim.wid += mathed_string_width(font, completion);
}
// Cache the dimension.
@ -334,7 +334,7 @@ void MathData::draw(PainterInfo & pi, int x, int y) const
if (completion.length() == 0)
continue;
FontInfo f = pi.base.font;
augmentFont(f, from_ascii("mathnormal"));
augmentFont(f, "mathnormal");
// draw the unique and the non-unique completion part
// Note: this is not time-critical as it is

View File

@ -92,7 +92,7 @@ bool isMathFontAvailable(string & name)
return false;
FontInfo f;
augmentFont(f, from_ascii(name));
augmentFont(f, name);
// Do we have the font proper?
if (theFontLoader().available(f))
@ -233,7 +233,7 @@ void initSymbols()
docstring help;
is >> tmp.name >> help;
tmp.inset = to_ascii(help);
if (isFontName(help))
if (isFontName(tmp.inset))
is >> charid >> fallbackid >> tmp.extra >> tmp.xmlname;
else
is >> tmp.extra;
@ -253,7 +253,7 @@ void initSymbols()
continue;
}
if (isFontName(from_ascii(tmp.inset))) {
if (isFontName(tmp.inset)) {
// tmp.inset _is_ the fontname here.
// create fallbacks if necessary

View File

@ -433,7 +433,7 @@ void MathMacro::metrics(MetricsInfo & mi, Dimension & dim) const
if (lyxrc.macro_edit_style == LyXRC::MACRO_EDIT_INLINE_BOX
&& d->editing_[mi.base.bv]) {
FontInfo font = mi.base.font;
augmentFont(font, from_ascii("lyxtex"));
augmentFont(font, "lyxtex");
Dimension namedim;
mathed_string_dim(font, name(), namedim);
#if 0
@ -622,7 +622,7 @@ void MathMacro::draw(PainterInfo & pi, int x, int y) const
if (drawBox && d->editing_[pi.base.bv]) {
// draw header and rectangle around
FontInfo font = pi.base.font;
augmentFont(font, from_ascii("lyxtex"));
augmentFont(font, "lyxtex");
font.setSize(FONT_SIZE_TINY);
font.setColor(Color_mathmacrolabel);
Dimension namedim;

View File

@ -543,7 +543,7 @@ void MathMacroTemplate::createLook(int args) const
void MathMacroTemplate::metrics(MetricsInfo & mi, Dimension & dim) const
{
Changer dummy1 = mi.base.changeFontSet(from_ascii("mathnormal"));
Changer dummy1 = mi.base.changeFontSet("mathnormal");
Changer dummy2 = mi.base.changeStyle(LM_ST_TEXT);
// valid macro?
@ -587,7 +587,7 @@ void MathMacroTemplate::draw(PainterInfo & pi, int x, int y) const
{
// FIXME: Calling Changer on the same object repeatedly is inefficient.
Changer dummy0 = pi.base.font.changeColor(Color_math);
Changer dummy1 = pi.base.changeFontSet(from_ascii("mathnormal"));
Changer dummy1 = pi.base.changeFontSet("mathnormal");
Changer dummy2 = pi.base.changeStyle(LM_ST_TEXT);
setPosCache(pi, x, y);

View File

@ -659,7 +659,7 @@ void mathed_draw_deco(PainterInfo & pi, int x, int y, int w, int h,
void metricsStrRedBlack(MetricsInfo & mi, Dimension & dim, docstring const & str)
{
FontInfo font = mi.base.font;
augmentFont(font, from_ascii("mathnormal"));
augmentFont(font, "mathnormal");
mathed_string_dim(font, str, dim);
}
@ -667,7 +667,7 @@ void metricsStrRedBlack(MetricsInfo & mi, Dimension & dim, docstring const & str
void drawStrRed(PainterInfo & pi, int x, int y, docstring const & str)
{
FontInfo f = pi.base.font;
augmentFont(f, from_ascii("mathnormal"));
augmentFont(f, "mathnormal");
f.setColor(Color_latex);
pi.pain.text(x, y, str, f);
}
@ -676,7 +676,7 @@ void drawStrRed(PainterInfo & pi, int x, int y, docstring const & str)
void drawStrBlack(PainterInfo & pi, int x, int y, docstring const & str)
{
FontInfo f = pi.base.font;
augmentFont(f, from_ascii("mathnormal"));
augmentFont(f, "mathnormal");
f.setColor(Color_foreground);
pi.pain.text(x, y, str, f);
}
@ -806,11 +806,10 @@ fontinfo fontinfos[] = {
};
fontinfo * lookupFont(docstring const & name0)
fontinfo * lookupFont(string const & name)
{
//lyxerr << "searching font '" << name << "'" << endl;
int const n = sizeof(fontinfos) / sizeof(fontinfo);
string name = to_utf8(name0);
for (int i = 0; i < n; ++i)
if (fontinfos[i].cmd_ == name) {
//lyxerr << "found '" << i << "'" << endl;
@ -820,7 +819,7 @@ fontinfo * lookupFont(docstring const & name0)
}
fontinfo * searchFont(docstring const & name)
fontinfo * searchFont(string const & name)
{
fontinfo * f = lookupFont(name);
return f ? f : fontinfos;
@ -829,27 +828,27 @@ fontinfo * searchFont(docstring const & name)
}
bool isFontName(docstring const & name)
bool isFontName(string const & name)
{
return lookupFont(name);
}
bool isMathFont(docstring const & name)
bool isMathFont(string const & name)
{
fontinfo * f = lookupFont(name);
return f && f->color_ == Color_math;
}
bool isTextFont(docstring const & name)
bool isTextFont(string const & name)
{
fontinfo * f = lookupFont(name);
return f && f->color_ == Color_foreground;
}
FontInfo getFont(docstring const & name)
FontInfo getFont(string const & name)
{
FontInfo font;
augmentFont(font, name);
@ -857,7 +856,7 @@ FontInfo getFont(docstring const & name)
}
void fakeFont(docstring const & orig, docstring const & fake)
void fakeFont(string const & orig, string const & fake)
{
fontinfo * forig = searchFont(orig);
fontinfo * ffake = searchFont(fake);
@ -867,22 +866,22 @@ void fakeFont(docstring const & orig, docstring const & fake)
forig->shape_ = ffake->shape_;
forig->color_ = ffake->color_;
} else {
lyxerr << "Can't fake font '" << to_utf8(orig) << "' with '"
<< to_utf8(fake) << "'" << endl;
lyxerr << "Can't fake font '" << orig << "' with '"
<< fake << "'" << endl;
}
}
void augmentFont(FontInfo & font, docstring const & name)
void augmentFont(FontInfo & font, string const & name)
{
static bool initialized = false;
if (!initialized) {
initialized = true;
// fake fonts if necessary
if (!theFontLoader().available(getFont(from_ascii("mathfrak"))))
fakeFont(from_ascii("mathfrak"), from_ascii("lyxfakefrak"));
if (!theFontLoader().available(getFont(from_ascii("mathcal"))))
fakeFont(from_ascii("mathcal"), from_ascii("lyxfakecal"));
if (!theFontLoader().available(getFont("mathfrak")))
fakeFont("mathfrak", "lyxfakefrak");
if (!theFontLoader().available(getFont("mathcal")))
fakeFont("mathcal", "lyxfakecal");
}
fontinfo * info = searchFont(name);
if (info->family_ != inh_family)

View File

@ -55,13 +55,13 @@ void drawStrBlack(PainterInfo & pi, int x, int y, docstring const & s);
void math_font_max_dim(FontInfo const &, int & asc, int & desc);
void augmentFont(FontInfo & f, docstring const & cmd);
void augmentFont(FontInfo & f, std::string const & cmd);
bool isFontName(docstring const & name);
bool isFontName(std::string const & name);
bool isMathFont(docstring const & name);
bool isMathFont(std::string const & name);
bool isTextFont(docstring const & name);
bool isTextFont(std::string const & name);
bool isAlphaSymbol(MathAtom const & at);