#include "InsetMathFrac.h"
-#include "Cursor.h"
-#include "LaTeXFeatures.h"
#include "MathData.h"
+#include "MathParser.h"
#include "MathStream.h"
#include "MathSupport.h"
+
+#include "Cursor.h"
+#include "LaTeXFeatures.h"
#include "MetricsInfo.h"
#include "TextPainter.h"
namespace {
-// align frac to minus character
-int dy_for_frac(MetricsBase & mb)
-{
- Changer dummy = mb.changeFontSet("mathnormal");
- return theFontMetrics(mb.font).ascent('-') - 1;
-}
-
-
// align the top of M in the cell with the top of M in the surrounding font
int dy_for_nicefrac(MetricsBase & mb)
{
return big_m - small_m;
}
-} // anon namespace
+// symbol for nicefrac solidus
+latexkeys const * slash_symbol()
+{
+ return in_word_set(from_ascii("slash"));
+}
+
+} // namespace
void InsetMathFrac::metrics(MetricsInfo & mi, Dimension & dim) const
{
Dimension dim0, dim1, dim2;
+ Changer dummy3 = mi.base.changeEnsureMath();
switch (kind_) {
case UNIT: {
case NICEFRAC: {
// \unitfrac, \unitfracthree, \nicefrac
dim.wid = 0;
+ dim.asc = 0;
+ dim.des = 0;
int const dy = dy_for_nicefrac(mi.base);
// is there an extra cell holding the value being given a dimension?
// (this is \unitfracthree)
if (kind_ == UNITFRAC && nargs() == 3) {
cell(2).metrics(mi, dim2);
dim.wid += dim2.wid + 4;
+ dim.asc = dim2.asc;
+ dim.des = dim2.des;
}
Changer dummy = (kind_ == UNITFRAC) ? mi.base.font.changeShape(UP_SHAPE)
: Changer();
Changer dummy2 = mi.base.changeScript();
+ if (latexkeys const * slash = slash_symbol()) {
+ Dimension dimslash;
+ mathedSymbolDim(mi.base, dimslash, slash);
+ dim.wid += dimslash.wid - mathed_mu(mi.base.font, 3.0);
+ dim.asc = max(dim.asc, dimslash.asc);
+ dim.des = max(dim.des, dimslash.des);
+ }
cell(0).metrics(mi, dim0);
cell(1).metrics(mi, dim1);
- dim.wid += dim0.wid + dim1.wid + 5;
- dim.asc = max(max(dim2.asc, dim0.asc + dy), dim1.asc);
- dim.des = max(max(dim2.des, dim0.des - dy), dim1.des);
+ dim.wid += dim0.wid + dim1.wid + 2;
+ dim.asc = max(max(dim.asc, dim0.asc + dy), dim1.asc);
+ dim.des = max(max(dim.des, dim0.des - dy), dim1.des);
}
break;
case TFRAC:
case OVER:
case ATOP: {
- int const dy = dy_for_frac(mi.base);
+ int const dy = axis_height(mi.base);
Changer dummy =
// \tfrac is always in text size
(kind_ == TFRAC) ? mi.base.font.changeStyle(LM_ST_SCRIPT) :
|| kind_ == DFRAC) ? mi.base.font.changeStyle(LM_ST_DISPLAY) :
// all others
mi.base.changeFrac();
+ Changer dummy2 = mi.base.changeEnsureMath();
cell(0).metrics(mi, dim0);
cell(1).metrics(mi, dim1);
dim.wid = max(dim0.wid, dim1.wid) + 2;
- dim.asc = dim0.height() + 2 + dy;
- dim.des = max(0, dim1.height() + 2 - dy);
+ dim.asc = dim0.height() + dy/2 + dy;
+ int const t = mi.base.solidLineThickness();
+ dim.des = max(0, dim1.height() + dy/2 - dy + t);
}
} //switch (kind_)
- metricsMarkers(mi, dim);
}
void InsetMathFrac::draw(PainterInfo & pi, int x, int y) const
{
- setPosCache(pi, x, y);
+ Changer dummy3 = pi.base.changeEnsureMath();
Dimension const dim = dimension(*pi.base.bv);
Dimension const dim0 = cell(0).dimension(*pi.base.bv);
switch (kind_) {
// is there an extra cell holding the value being given a dimension?
// (this is \unittwo)
if (nargs() == 2) {
- cell(0).draw(pi, x + 1, y);
+ cell(0).draw(pi, x, y);
xx += dim0.wid + 4;
unit_cell = 1;
}
Changer dummy = pi.base.font.changeShape(UP_SHAPE);
- cell(unit_cell).draw(pi, xx + 1, y);
+ cell(unit_cell).draw(pi, xx, y);
}
break;
// is there an extra cell holding the value being given a dimension?
// (this is \unitfracthree)
if (kind_ == UNITFRAC && nargs() == 3) {
- cell(2).draw(pi, x + 1, y);
+ cell(2).draw(pi, x, y);
xx += cell(2).dimension(*pi.base.bv).wid + 4;
}
Changer dummy = (kind_ == UNITFRAC) ? pi.base.font.changeShape(UP_SHAPE)
: Changer();
// nice fraction
- // FIXME:
- // * the solidus should be \kern-2mu/\kern-1mu.
Changer dummy2 = pi.base.changeScript();
- cell(0).draw(pi, xx + 2, y - dy);
- cell(1).draw(pi, xx + dim0.wid + 5, y);
- // Diag line:
- pi.pain.line(xx + dim0.wid + 1, y + dim.des - 2,
- xx + dim0.wid + 6, y - dim.asc + 2,
- pi.base.font.color());
+ cell(0).draw(pi, xx + 1, y - dy);
+ // reference LaTeX code from nicefrac.sty:
+ // \mkern-2mu/\mkern-1mu
+ if (latexkeys const * slash = slash_symbol()) {
+ int mkern = mathed_mu(pi.base.font, 2.0);
+ mathedSymbolDraw(pi, xx + 1 + dim0.wid - mkern, y, slash);
+ Dimension dimslash;
+ mathedSymbolDim(pi.base, dimslash, slash);
+ xx += dimslash.wid - mathed_mu(pi.base.font, 3.0);
+ }
+ cell(1).draw(pi, xx + 1 + dim0.wid, y);
}
break;
case TFRAC:
case OVER:
case ATOP: {
- int const dy = dy_for_frac(pi.base);
+ int const dy = axis_height(pi.base);
Changer dummy =
// \tfrac is always in text size
(kind_ == TFRAC) ? pi.base.font.changeStyle(LM_ST_SCRIPT) :
// all others
pi.base.changeFrac();
Dimension const dim1 = cell(1).dimension(*pi.base.bv);
- int m = x + dim.wid / 2;
- int xx =
+ int const m = x + dim.wid / 2;
+ int const xx =
// align left
- (kind_ == CFRACLEFT) ? x + 2 :
+ (kind_ == CFRACLEFT) ? x + 1 :
// align right
(kind_ == CFRACRIGHT) ? x + dim.wid - dim0.wid - 2 :
// center
m - dim0.wid / 2;
- cell(0).draw(pi, xx, y - dim0.des - 2 - dy);
+ int const t = pi.base.solidLineThickness();
+ // take dy/2 for the spacing around the horizontal line. This is
+ // arbitrary. In LaTeX it is more complicated to ensure that displayed
+ // fractions line up next to each other.
+ // For more accurate implementation refer to the TeXbook, Appendix G,
+ // rules 15a-e.
+ cell(0).draw(pi, xx, y - dim0.des - dy/2 - dy);
// center
- cell(1).draw(pi, m - dim1.wid / 2, y + dim1.asc + 2 - dy);
+ cell(1).draw(pi, m - dim1.wid / 2, y + dim1.asc + dy/2 - dy + t);
// horizontal line
if (kind_ != ATOP)
- pi.pain.line(x + 1, y - dy,
- x + dim.wid - 2, y - dy, pi.base.font.color());
+ pi.pain.line(x, y - dy, x + dim.wid, y - dy,
+ pi.base.font.color(), pi.pain.line_solid, t);
}
} //switch (kind_)
- drawMarkers(pi, x, y);
}
// FIXME This is not right, because we still output mi, etc,
// when we output the cell. So we need to prevent that somehow.
if (nargs() == 2)
- os << cell(0)
- << MTag("mstyle mathvariant='normal'")
- << cell(1)
+ os << cell(0)
+ << MTag("mstyle mathvariant='normal'")
+ << cell(1)
<< ETag("mstyle");
else
- os << MTag("mstyle mathvariant='normal'")
+ os << MTag("mstyle mathvariant='normal'")
<< cell(0)
<< ETag("mstyle");
}
// FIXME This is not right, because we still output i, etc,
// when we output the cell. So we need to prevent that somehow.
if (nargs() == 2)
- os << cell(0)
- << MTag("span")
- << cell(1)
+ os << cell(0)
+ << MTag("span")
+ << cell(1)
<< ETag("span");
else
- os << MTag("span")
+ os << MTag("span")
<< cell(0)
<< ETag("span");
}
void InsetMathBinom::metrics(MetricsInfo & mi, Dimension & dim) const
{
+ Changer dummy2 = mi.base.changeEnsureMath();
Dimension dim0, dim1;
- int const dy = dy_for_frac(mi.base);
+ int const dy = axis_height(mi.base);
Changer dummy =
(kind_ == DBINOM) ? mi.base.font.changeStyle(LM_ST_DISPLAY) :
(kind_ == TBINOM) ? mi.base.font.changeStyle(LM_ST_SCRIPT) :
mi.base.changeFrac();
cell(0).metrics(mi, dim0);
cell(1).metrics(mi, dim1);
- dim.asc = dim0.height() + 4 + dy;
- dim.des = max(0, dim1.height() + 4 - dy);
+ dim.asc = dim0.height() + 1 + dy/2 + dy;
+ dim.des = max(0, dim1.height() + 1 + dy/2 - dy);
dim.wid = max(dim0.wid, dim1.wid) + 2 * dw(dim.height()) + 4;
- metricsMarkers2(mi, dim);
}
void InsetMathBinom::draw(PainterInfo & pi, int x, int y) const
{
+ Changer dummy2 = pi.base.changeEnsureMath();
Dimension const dim = dimension(*pi.base.bv);
Dimension const & dim0 = cell(0).dimension(*pi.base.bv);
Dimension const & dim1 = cell(1).dimension(*pi.base.bv);
- int const dy = dy_for_frac(pi.base);
+ int const dy = axis_height(pi.base);
// define the binom brackets
docstring const bra = kind_ == BRACE ? from_ascii("{") :
kind_ == BRACK ? from_ascii("[") : from_ascii("(");
(kind_ == DBINOM) ? pi.base.font.changeStyle(LM_ST_DISPLAY) :
(kind_ == TBINOM) ? pi.base.font.changeStyle(LM_ST_SCRIPT) :
pi.base.changeFrac();
- cell(0).draw(pi, m - dim0.wid / 2, y - dim0.des - 3 - dy);
- cell(1).draw(pi, m - dim1.wid / 2, y + dim1.asc + 3 - dy);
+ // take dy both for the vertical alignment and for the spacing between
+ // cells
+ cell(0).draw(pi, m - dim0.wid / 2, y - dim0.des - dy/2 - dy);
+ cell(1).draw(pi, m - dim1.wid / 2, y + dim1.asc + dy/2 - dy);
}
// draw the brackets and the marker
mathed_draw_deco(pi, x, y - dim.ascent(), dw(dim.height()),
dim.height(), bra);
mathed_draw_deco(pi, x + dim.width() - dw(dim.height()),
y - dim.ascent(), dw(dim.height()), dim.height(), ket);
- drawMarkers2(pi, x, y);
}