[LyX/master] Show slanted caret (cursor) when text style emphasis/italics/slanted.

Jean-Marc Lasgouttes lasgouttes at lyx.org
Fri Sep 18 12:53:04 UTC 2020


commit 9a1f732664baa840fe3d8b98d9df29a13116798b
Author: Daniel Ramoeller <d.lyx at web.de>
Date:   Fri Sep 18 10:14:46 2020 +0200

    Show slanted caret (cursor) when text style emphasis/italics/slanted.
    
    Fixes for bug #11428. Emphasis is used regularly and it is helpful to
    see whether the next text will be written emphasized directly from the
    cursor.
    
    This is also implemented in MS Word and Google docs but not in
    LibreWriter.
    
    Also fixes the caret for RTL languages whose width was previously
    extended into the wrong direction.
---
 src/frontends/qt/GuiWorkArea.cpp |   64 +++++++++++++++++++++++++------------
 1 files changed, 43 insertions(+), 21 deletions(-)

diff --git a/src/frontends/qt/GuiWorkArea.cpp b/src/frontends/qt/GuiWorkArea.cpp
index f323fbc..064d4cb 100644
--- a/src/frontends/qt/GuiWorkArea.cpp
+++ b/src/frontends/qt/GuiWorkArea.cpp
@@ -130,7 +130,7 @@ namespace frontend {
 class CaretWidget {
 public:
 	CaretWidget() : rtl_(false), l_shape_(false), completable_(false),
-		x_(0), caret_width_(0)
+		x_(0), caret_width_(0), slant_(false), ascent_(0)
 	{}
 
 	/* Draw the caret. Parameter \c horiz_offset is not 0 when there
@@ -143,44 +143,57 @@ public:
 
 		int const x = x_ - horiz_offset;
 		int const y = rect_.top();
-		int const l = x_ - rect_.left();
-		int const r = rect_.right() - x_;
+		int const lx = rtl_ ? x_ - rect_.left() : rect_.right() - x_;
 		int const bot = rect_.bottom();
-
-		// draw vertical line
-		painter.fillRect(x, y, caret_width_, rect_.height(), color_);
+		int const dir = rtl_ ? -1 : 1;
+		// this is almost equal to tan(14 * PI / 180)
+		qreal const slope = 0.25;
+
+		// draw caret box
+		if (slant_ && !rtl_) {
+			// slanted (14 degree angle)
+			QPainterPath path;
+			path.moveTo(x + ascent_ * slope, y);
+			path.lineTo(x - (rect_.height() - ascent_) * slope, y + rect_.height());
+			path.lineTo(x + dir * caret_width_ - (rect_.height() - ascent_) * slope,
+			            y + rect_.height());
+			path.lineTo(x + dir * caret_width_ + ascent_ * slope, y);
+			painter.setRenderHint(QPainter::Antialiasing, true);
+			painter.fillPath(path, color_);
+			painter.setRenderHint(QPainter::Antialiasing, false);
+		} else
+			// regular
+			painter.fillRect(x, y, dir * caret_width_, rect_.height(), color_);
 
 		// draw RTL/LTR indication
 		painter.setPen(color_);
 		if (l_shape_) {
-			if (rtl_)
-				painter.drawLine(x, bot, x - l + 1, bot);
-			else
-				painter.drawLine(x, bot, x + caret_width_ + r - 1, bot);
+			painter.drawLine(x, bot, x + dir * (caret_width_ + lx - 1), bot);
 		}
 
 		// draw completion triangle
 		if (completable_) {
-			int m = y + rect_.height() / 2;
-			int d = TabIndicatorWidth - 1;
-			if (rtl_) {
-				painter.drawLine(x - 1, m - d, x - 1 - d, m);
-				painter.drawLine(x - 1, m + d, x - 1 - d, m);
-			} else {
-				painter.drawLine(x + caret_width_, m - d, x + caret_width_ + d, m);
-				painter.drawLine(x + caret_width_, m + d, x + caret_width_ + d, m);
-			}
+			int const m = y + rect_.height() / 2;
+			int const d = TabIndicatorWidth - 1;
+			// offset for slanted carret
+			int const sx = (slant_ && !rtl_) ? (ascent_ - (rect_.height() / 2 - d)) * slope : 0;
+			painter.drawLine(x + dir * (caret_width_ + 1) + sx, m - d,
+			                 x + dir * (caret_width_ + d + 1) + sx, m);
+			painter.drawLine(x + dir * (caret_width_ + 1) + sx, m + d,
+			                 x + dir * (caret_width_ + d + 1) + sx, m);
 		}
 	}
 
 	void update(int x, int y, int h, bool l_shape,
-		bool rtl, bool completable)
+		bool rtl, bool completable, bool slant, int ascent)
 	{
 		color_ = guiApp->colorCache().get(Color_cursor);
 		l_shape_ = l_shape;
 		rtl_ = rtl;
 		completable_ = completable;
 		x_ = x;
+		slant_ = slant;
+		ascent_ = ascent;
 
 		// extension to left and right
 		int l = 0;
@@ -228,6 +241,10 @@ private:
 	int x_;
 	/// the width of the vertical blinking bar
 	int caret_width_;
+	/// caret is in slanted text
+	bool slant_;
+	/// the fontmetrics ascent for drawing slanted caret
+	int ascent_;
 };
 
 
@@ -631,6 +648,7 @@ void GuiWorkArea::Private::updateCaretGeometry()
 	// RTL or not RTL
 	bool l_shape = false;
 	Font const & realfont = buffer_view_->cursor().real_current_font;
+	FontMetrics const & fm = theFontMetrics(realfont.fontInfo());
 	BufferParams const & bp = buffer_view_->buffer().params();
 	bool const samelang = realfont.language() == bp.language;
 	bool const isrtl = realfont.isVisibleRightToLeft();
@@ -649,7 +667,11 @@ void GuiWorkArea::Private::updateCaretGeometry()
 		&& !completer_->popupVisible()
 		&& !completer_->inlineVisible();
 
-	caret_->update(point.x_, point.y_, h, l_shape, isrtl, completable);
+	caret_->update(point.x_, point.y_, h, l_shape, isrtl, completable,
+		// use slanted caret for italics in text edit mode
+		fm.italic() && buffer_view_->cursor().inTexted()
+		// except for selections because the selection rect does not slant
+		&& !buffer_view_->cursor().selection(), fm.maxAscent());
 	needs_caret_geometry_update_ = false;
 }
 


More information about the lyx-cvs mailing list