From b4ff3fb2878da14c3ae702b506b91210f4481888 Mon Sep 17 00:00:00 2001 From: Richard Kimberly Heck Date: Tue, 22 Nov 2022 21:04:29 -0500 Subject: [PATCH] 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 182bfdf765..d5c850bd87 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 886d3c8fe7..8326e36781 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 c02606c438..fbe18df2a5 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 3df1bc951a..2e20a0857c 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 +#include +#include +#include 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(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 6cea40f3ec..f4ba40b060 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 width_cache_; /// Cache of string widths diff --git a/src/mathed/InsetMathDecoration.cpp b/src/mathed/InsetMathDecoration.cpp index 1262370953..fd918caf10 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 b98dc54db1..f76a5d7a08 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 #include @@ -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 7c40baa0b4..4675bccef7 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);