Backport fix for #11491. From Enrico.

This commit is contained in:
Richard Kimberly Heck 2022-11-22 21:04:29 -05:00
parent 5290f96e1e
commit b4ff3fb287
8 changed files with 171 additions and 41 deletions

View File

@ -82,6 +82,7 @@
#include "support/gettext.h"
#include "support/lassert.h"
#include "support/lstrings.h"
#include "support/lyxlib.h"
#include "support/Package.h"
#include "support/types.h"
@ -389,6 +390,21 @@ int BufferView::inPixels(Length const & len) const
}
int BufferView::zoomedPixels(int pix) const
{
// FIXME: the dpi setting should really depend on the BufferView
// (think different monitors).
// Zoom factor specified by user in percent
double const zoom = lyxrc.currentZoom / 100.0; // [percent]
// DPI setting for monitor: pixels/inch
double const dpizoom = lyxrc.dpi / 100.0; // [per 100dpi]
return support::iround(pix * zoom * dpizoom);
}
bool BufferView::isTopScreen() const
{
return 0 == d->scrollbarParameters_.min;

View File

@ -114,6 +114,11 @@ public:
*/
int inPixels(Length const & len) const;
/** Return the number of pixels equivalent to \c pix pixels at
* 100dpi and 100% zoom.
*/
int zoomedPixels(int pix) const;
/// \return true if the BufferView is at the top of the document.
bool isTopScreen() const;

View File

@ -73,6 +73,8 @@ public:
/// return the distance from the base line to where the strike out line
/// should be drawn.
virtual int strikeoutPos() const = 0;
/// return slope for italic font
virtual double italicSlope() const = 0;
/// return the width of the char in the font
virtual int width(char_type c) const = 0;

View File

@ -20,11 +20,15 @@
#include "support/convert.h"
#include "support/lassert.h"
#include "support/lyxlib.h"
#include "support/debug.h"
#define DISABLE_PMPROF
#include "support/pmprof.h"
#include <QByteArray>
#include <QRawFont>
#include <QtEndian>
#include <QtMath>
using namespace std;
using namespace lyx::support;
@ -113,6 +117,21 @@ GuiFontMetrics::GuiFontMetrics(QFont const & font)
breakat_cache_(cache_metrics_breakat_size),
qtextlayout_cache_(cache_metrics_qtextlayout_size)
{
// Determine italic slope
double const defaultSlope = tan(qDegreesToRadians(19.0));
QRawFont raw = QRawFont::fromFont(font);
QByteArray post(raw.fontTable("post"));
if (post.length() == 0) {
slope_ = defaultSlope;
LYXERR(Debug::FONT, "Screen font doesn't have 'post' table.");
} else {
// post table description:
// https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6post.html
int32_t italicAngle = qFromBigEndian(*reinterpret_cast<int32_t *>(post.data() + 4));
double angle = italicAngle / 65536.0; // Fixed-point 16.16 to floating-point
slope_ = -tan(qDegreesToRadians(angle));
LYXERR(Debug::FONT, "Italic slope: " << slope_);
}
}
@ -154,6 +173,12 @@ int GuiFontMetrics::strikeoutPos() const
}
double GuiFontMetrics::italicSlope() const
{
return slope_;
}
namespace {
int const outOfLimitMetric = -10000;
}

View File

@ -41,6 +41,7 @@ public:
virtual int lineWidth() const;
virtual int underlinePos() const;
virtual int strikeoutPos() const;
virtual double italicSlope() const;
virtual int width(char_type c) const;
virtual int ascent(char_type c) const;
virtual int descent(char_type c) const;
@ -83,6 +84,9 @@ private:
/// Metrics on the font
QFontMetrics metrics_;
/// Slope of italic font
double slope_;
/// Cache of char widths
mutable QHash<char_type, int> width_cache_;
/// Cache of string widths

View File

@ -13,12 +13,14 @@
#include "InsetMathDecoration.h"
#include "InsetMathChar.h"
#include "MathData.h"
#include "MathParser.h"
#include "MathSupport.h"
#include "MathStream.h"
#include "MetricsInfo.h"
#include "BufferView.h"
#include "LaTeXFeatures.h"
#include "support/debug.h"
@ -115,15 +117,19 @@ void InsetMathDecoration::metrics(MetricsInfo & mi, Dimension & dim) const
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');
int const l1 = mi.base.bv->zoomedPixels(1);
int const l2 = 6 * l1;
int const l3 = 6 * l1;
dh_ = l2; //mathed_char_height(LM_TC_VAR, mi, 'I', ascent_, descent_);
dw_ = l3; //mathed_char_width(LM_TC_VAR, mi, 'x');
if (upper()) {
dy_ = -dim.asc - dh_;
dim.asc += dh_ + 1;
dy_ = -dim.asc - dh_ - l1;
dim.asc += dh_ + l1;
} else {
dy_ = dim.des + 1;
dim.des += dh_ + 2;
dy_ = dim.des + l1;
dim.des += dh_ + l2;
}
}
@ -134,11 +140,20 @@ void InsetMathDecoration::draw(PainterInfo & pi, int x, int y) const
cell(0).draw(pi, x, 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);
if (wide()) {
mathed_draw_deco(pi, x, y + dy_, dim0.wid, dh_, key_->name);
return;
}
// Lacking the necessary font parameters, in order to properly align
// the decoration we have to resort to heuristics for choosing a
// suitable value for shift
char_type c = (cell(0).empty() || !cell(0)[0]->asCharInset())
? 0 : cell(0)[0]->asCharInset()->getChar();
double slope = (c == 0) ? 0.0 : mathed_char_slope(pi.base, c);
int kerning = (c == 0) ? 0 : mathed_char_kerning(pi.base.font, c);
int shift = (kerning == 0) ? int(dim0.asc * slope) : kerning;
mathed_draw_deco(pi, x + (dim0.wid - dw_) / 2 + shift,
y + dy_, dw_, dh_, key_->name);
}

View File

@ -21,6 +21,7 @@
#include "MathParser.h"
#include "MathStream.h"
#include "Encoding.h"
#include "LaTeXFeatures.h"
#include "MetricsInfo.h"
@ -32,6 +33,7 @@
#include "support/docstream.h"
#include "support/lassert.h"
#include "support/lyxlib.h"
#include "support/textutils.h"
#include <map>
#include <algorithm>
@ -99,8 +101,8 @@ double const parenthHigh[] = {
double const parenth[] = {
2, 13,
0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
0.9930, 0.0081, 0.7254, 0.0588, 0.5070, 0.1136,
0.3310, 0.1724, 0.2113, 0.2353, 0.0563, 0.3631,
0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
0.9930, 0.9919,
@ -108,6 +110,13 @@ double const parenth[] = {
};
double const breve[] = {
2, 5,
0.1, 0.4, 0.2, 0.7, 0.5, 0.8, 0.8, 0.7, 0.9, 0.4,
0
};
double const brace[] = {
2, 21,
0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
@ -277,13 +286,13 @@ double const corner[] = {
double const angle[] = {
2, 3,
1, 0, 0.05, 0.5, 1, 1,
0.9, 0.05, 0.05, 0.5, 0.9, 0.95,
0
};
double const slash[] = {
1, 0.95, 0.05, 0.05, 0.95,
1, 0.8, 0.1, 0.1, 0.8,
0
};
@ -298,31 +307,31 @@ double const dot[] = {
// 1, 0.5, 0.2, 0.5, 0.2,
// 1, 0.4, 0.4, 0.6, 0.4,
// 1, 0.5, 0.5, 0.5, 0.5,
5, 0.4, 0.4, 0.6, 0.4,
5, 0.4, 0.5, 0.6, 0.5,
0
};
double const ddot[] = {
5, 0.0, 0.4, 0.3, 0.4,
5, 0.6, 0.4, 1.0, 0.4,
5, 0.1, 0.5, 0.3, 0.5,
5, 0.6, 0.5, 0.8, 0.5,
0
};
double const dddot[] = {
1, 0.1, 0.5, 0.2, 0.5,
1, 0.45, 0.5, 0.55, 0.5,
1, 0.8, 0.5, 0.9, 0.5,
5, -0.2, 0.5, 0.0, 0.5,
5, 0.3, 0.5, 0.5, 0.5,
5, 0.8, 0.5, 1.0, 0.5,
0
};
double const ddddot[] = {
1, 0.1, 0.5, 0.2, 0.5,
1, 0.45, 0.5, 0.55, 0.5,
1, 0.8, 0.5, 0.9, 0.5,
1, 1.15, 0.5, 1.25, 0.5,
5, -0.4, 0.5, -0.2, 0.5,
5, 0.1, 0.5, 0.3, 0.5,
5, 0.6, 0.5, 0.8, 0.5,
5, 1.1, 0.5, 1.3, 0.5,
0
};
@ -344,8 +353,10 @@ double const dline3[] = {
double const ring[] = {
2, 5,
0.5, 0.8, 0.8, 0.5, 0.5, 0.2, 0.2, 0.5, 0.5, 0.8,
2, 9,
0.5, 0.8, 0.7, 0.7, 0.8, 0.5,
0.7, 0.3, 0.5, 0.2, 0.3, 0.3,
0.2, 0.5, 0.3, 0.7, 0.5, 0.8,
0
};
@ -364,8 +375,12 @@ double const Vert[] = {
double const tilde[] = {
2, 4,
0.00, 0.8, 0.25, 0.2, 0.75, 0.8, 1.00, 0.2,
2, 13,
-0.05,0.70, 0.00, 0.55, 0.05, 0.40,
0.15, 0.30, 0.30, 0.30, 0.40, 0.40,
0.45, 0.55, 0.50, 0.70, 0.60, 0.80,
0.75, 0.80, 0.85, 0.70, 0.90, 0.55,
0.95, 0.40,
0
};
@ -463,7 +478,7 @@ named_deco_struct deco_table[] = {
{"bar", hline, 0 },
{"dot", dot, 0 },
{"check", angle, 1 },
{"breve", parenth, 1 },
{"breve", breve, 0 },
{"vec", arrow, 3 },
{"mathring", ring, 0 },
@ -570,6 +585,15 @@ int mathed_char_kerning(FontInfo const & font, char_type c)
}
double mathed_char_slope(MetricsBase const & mb, char_type c)
{
bool slanted = isAlphaASCII(c) || Encodings::isMathAlpha(c);
if (slanted && mb.fontname == "mathnormal")
return theFontMetrics(mb.font).italicSlope();
return 0.0;
}
void mathed_string_dim(FontInfo const & font,
docstring const & s,
Dimension & dim)
@ -596,9 +620,11 @@ int mathed_string_width(FontInfo const & font, docstring const & s)
void mathed_draw_deco(PainterInfo & pi, int x, int y, int w, int h,
docstring const & name)
{
int const lw = pi.base.solidLineThickness();
if (name == ".") {
pi.pain.line(x + w/2, y, x + w/2, y + h,
Color_cursor, Painter::line_onoffdash);
Color_cursor, Painter::line_onoffdash, lw);
return;
}
@ -640,16 +666,50 @@ void mathed_draw_deco(PainterInfo & pi, int x, int y, int w, int h,
pi.pain.line(
int(x + xx + 0.5), int(y + yy + 0.5),
int(x + x2 + 0.5), int(y + y2 + 0.5),
pi.base.font.color());
pi.base.font.color(), Painter::line_solid, lw);
if (code == 5) { // thicker, but rounded
pi.pain.line(
int(x + xx + 0.5+1), int(y + yy + 0.5-1),
int(x + x2 + 0.5-1), int(y + y2 + 0.5-1),
pi.base.font.color());
pi.pain.line(
int(x + xx + 0.5+1), int(y + yy + 0.5+1),
int(x + x2 + 0.5-1), int(y + y2 + 0.5+1),
pi.base.font.color());
double const xa = x + xx + 0.5;
double const xb = x + x2 + 0.5;
double const ya = y + yy + 0.5;
double const yb = y + y2 + 0.5;
pi.pain.line(int(xa + 1), int(ya - 1),
int(xb - 1), int(yb - 1),
pi.base.font.color(),
Painter::line_solid, lw);
pi.pain.line(int(xa + 1), int(ya + 1),
int(xb - 1), int(yb + 1),
pi.base.font.color(),
Painter::line_solid, lw);
if (xa + 2 <= xb - 2) {
pi.pain.line(int(xa + 2), int(ya - 2),
int(xb - 2), int(yb - 2),
pi.base.font.color(),
Painter::line_solid, lw);
pi.pain.line(int(xa + 2), int(ya + 2),
int(xb - 2), int(yb + 2),
pi.base.font.color(),
Painter::line_solid, lw);
}
if (xa + 3 <= xb - 3) {
pi.pain.line(int(xa + 3), int(ya - 3),
int(xb - 3), int(yb - 3),
pi.base.font.color(),
Painter::line_solid, lw);
pi.pain.line(int(xa + 3), int(ya + 3),
int(xb - 3), int(yb + 3),
pi.base.font.color(),
Painter::line_solid, lw);
}
if (xa + 4 <= xb - 4) {
pi.pain.line(int(xa + 4), int(ya - 4),
int(xb - 4), int(yb - 4),
pi.base.font.color(),
Painter::line_solid, lw);
pi.pain.line(int(xa + 4), int(ya + 4),
int(xb - 4), int(yb + 4),
pi.base.font.color(),
Painter::line_solid, lw);
}
}
} else {
int xp[32];
@ -667,7 +727,8 @@ void mathed_draw_deco(PainterInfo & pi, int x, int y, int w, int h,
yp[j] = int(y + yy + 0.5);
// lyxerr << "P[" << j ' ' << xx << ' ' << yy << ' ' << x << ' ' << y << ']';
}
pi.pain.lines(xp, yp, n, pi.base.font.color());
pi.pain.lines(xp, yp, n, pi.base.font.color(),
Painter::fill_none, Painter::line_solid, lw);
}
}
}

View File

@ -46,6 +46,8 @@ int mathed_char_width(FontInfo const &, char_type c);
int mathed_char_kerning(FontInfo const &, char_type c);
double mathed_char_slope(MetricsBase const & mb, char_type c);
void mathed_draw_deco(PainterInfo & pi, int x, int y, int w, int h,
docstring const & name);