[LyX/2.3.x] Backport fix for #11491. From Enrico.

Richard Kimberly Heck rikiheck at lyx.org
Wed Nov 23 01:09:56 UTC 2022


commit b4ff3fb2878da14c3ae702b506b91210f4481888
Author: Richard Kimberly Heck <rikiheck at lyx.org>
Date:   Tue Nov 22 21:04:29 2022 -0500

    Backport fix for #11491. From Enrico.
---
 src/BufferView.cpp                   |   16 +++++
 src/BufferView.h                     |    5 ++
 src/frontends/FontMetrics.h          |    2 +
 src/frontends/qt4/GuiFontMetrics.cpp |   25 +++++++
 src/frontends/qt4/GuiFontMetrics.h   |    4 +
 src/mathed/InsetMathDecoration.cpp   |   37 +++++++---
 src/mathed/MathSupport.cpp           |  121 +++++++++++++++++++++++++--------
 src/mathed/MathSupport.h             |    2 +
 8 files changed, 171 insertions(+), 41 deletions(-)

diff --git a/src/BufferView.cpp b/src/BufferView.cpp
index 182bfdf..d5c850b 100644
--- a/src/BufferView.cpp
+++ b/src/BufferView.cpp
@@ -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;
diff --git a/src/BufferView.h b/src/BufferView.h
index 886d3c8..8326e36 100644
--- a/src/BufferView.h
+++ b/src/BufferView.h
@@ -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;
 
diff --git a/src/frontends/FontMetrics.h b/src/frontends/FontMetrics.h
index c02606c..fbe18df 100644
--- a/src/frontends/FontMetrics.h
+++ b/src/frontends/FontMetrics.h
@@ -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;
diff --git a/src/frontends/qt4/GuiFontMetrics.cpp b/src/frontends/qt4/GuiFontMetrics.cpp
index 3df1bc9..2e20a08 100644
--- a/src/frontends/qt4/GuiFontMetrics.cpp
+++ b/src/frontends/qt4/GuiFontMetrics.cpp
@@ -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;
 }
diff --git a/src/frontends/qt4/GuiFontMetrics.h b/src/frontends/qt4/GuiFontMetrics.h
index 6cea40f..f4ba40b 100644
--- a/src/frontends/qt4/GuiFontMetrics.h
+++ b/src/frontends/qt4/GuiFontMetrics.h
@@ -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
diff --git a/src/mathed/InsetMathDecoration.cpp b/src/mathed/InsetMathDecoration.cpp
index 1262370..fd918ca 100644
--- a/src/mathed/InsetMathDecoration.cpp
+++ b/src/mathed/InsetMathDecoration.cpp
@@ -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);
 }
 
 
diff --git a/src/mathed/MathSupport.cpp b/src/mathed/MathSupport.cpp
index b98dc54..f76a5d7 100644
--- a/src/mathed/MathSupport.cpp
+++ b/src/mathed/MathSupport.cpp
@@ -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);
 		}
 	}
 }
diff --git a/src/mathed/MathSupport.h b/src/mathed/MathSupport.h
index 7c40baa..4675bcc 100644
--- a/src/mathed/MathSupport.h
+++ b/src/mathed/MathSupport.h
@@ -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);
 


More information about the lyx-cvs mailing list