mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-22 10:00:33 +00:00
Use real italic slope for slanted caret
This commit is contained in:
parent
0bda5e5b8d
commit
e47092044b
@ -77,6 +77,8 @@ public:
|
|||||||
virtual int strikeoutPos() const = 0;
|
virtual int strikeoutPos() const = 0;
|
||||||
/// return true if font is not upright (italic or oblique)
|
/// return true if font is not upright (italic or oblique)
|
||||||
virtual bool italic() const = 0;
|
virtual bool italic() const = 0;
|
||||||
|
/// return slope for italic font
|
||||||
|
virtual double italicSlope() const = 0;
|
||||||
|
|
||||||
/// return the width of the char in the font
|
/// return the width of the char in the font
|
||||||
virtual int width(char_type c) const = 0;
|
virtual int width(char_type c) const = 0;
|
||||||
|
@ -20,11 +20,15 @@
|
|||||||
#include "support/convert.h"
|
#include "support/convert.h"
|
||||||
#include "support/lassert.h"
|
#include "support/lassert.h"
|
||||||
#include "support/lyxlib.h"
|
#include "support/lyxlib.h"
|
||||||
|
#include "support/debug.h"
|
||||||
|
|
||||||
#define DISABLE_PMPROF
|
#define DISABLE_PMPROF
|
||||||
#include "support/pmprof.h"
|
#include "support/pmprof.h"
|
||||||
|
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
#include <QRawFont>
|
||||||
|
#include <QtEndian>
|
||||||
|
#include <QtMath>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace lyx::support;
|
using namespace lyx::support;
|
||||||
@ -113,6 +117,24 @@ GuiFontMetrics::GuiFontMetrics(QFont const & font)
|
|||||||
breakat_cache_(cache_metrics_breakat_size),
|
breakat_cache_(cache_metrics_breakat_size),
|
||||||
qtextlayout_cache_(cache_metrics_qtextlayout_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));
|
||||||
|
// Correct italic fonts with zero slope
|
||||||
|
if (slope_ == 0.0 && font.italic())
|
||||||
|
slope_ = defaultSlope;
|
||||||
|
LYXERR(Debug::FONT, "Italic slope: " << slope_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -167,6 +189,12 @@ bool GuiFontMetrics::italic() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double GuiFontMetrics::italicSlope() const
|
||||||
|
{
|
||||||
|
return slope_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
int const outOfLimitMetric = -10000;
|
int const outOfLimitMetric = -10000;
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ public:
|
|||||||
virtual int underlinePos() const;
|
virtual int underlinePos() const;
|
||||||
virtual int strikeoutPos() const;
|
virtual int strikeoutPos() const;
|
||||||
virtual bool italic() const;
|
virtual bool italic() const;
|
||||||
|
virtual double italicSlope() const;
|
||||||
virtual int width(char_type c) const;
|
virtual int width(char_type c) const;
|
||||||
virtual int ascent(char_type c) const;
|
virtual int ascent(char_type c) const;
|
||||||
virtual int descent(char_type c) const;
|
virtual int descent(char_type c) const;
|
||||||
@ -85,6 +86,9 @@ private:
|
|||||||
/// Metrics on the font
|
/// Metrics on the font
|
||||||
QFontMetrics metrics_;
|
QFontMetrics metrics_;
|
||||||
|
|
||||||
|
/// Slope of italic font
|
||||||
|
double slope_;
|
||||||
|
|
||||||
/// Cache of char widths
|
/// Cache of char widths
|
||||||
mutable QHash<char_type, int> width_cache_;
|
mutable QHash<char_type, int> width_cache_;
|
||||||
/// Cache of string widths
|
/// Cache of string widths
|
||||||
|
@ -130,7 +130,7 @@ namespace frontend {
|
|||||||
class CaretWidget {
|
class CaretWidget {
|
||||||
public:
|
public:
|
||||||
CaretWidget() : rtl_(false), l_shape_(false), completable_(false),
|
CaretWidget() : rtl_(false), l_shape_(false), completable_(false),
|
||||||
x_(0), caret_width_(0), slant_(false), ascent_(0)
|
x_(0), caret_width_(0), slant_(false), ascent_(0), slope_(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/* Draw the caret. Parameter \c horiz_offset is not 0 when there
|
/* Draw the caret. Parameter \c horiz_offset is not 0 when there
|
||||||
@ -146,18 +146,18 @@ public:
|
|||||||
int const lx = rtl_ ? x_ - rect_.left() : rect_.right() - x_;
|
int const lx = rtl_ ? x_ - rect_.left() : rect_.right() - x_;
|
||||||
int const bot = rect_.bottom();
|
int const bot = rect_.bottom();
|
||||||
int const dir = rtl_ ? -1 : 1;
|
int const dir = rtl_ ? -1 : 1;
|
||||||
// this is almost equal to tan(14 * PI / 180)
|
|
||||||
qreal const slope = 0.25;
|
|
||||||
|
|
||||||
// draw caret box
|
// draw caret box
|
||||||
if (slant_ && !rtl_) {
|
if (slant_ && !rtl_) {
|
||||||
// slanted (14 degree angle)
|
// slanted
|
||||||
|
|
||||||
QPainterPath path;
|
QPainterPath path;
|
||||||
path.moveTo(x + ascent_ * slope, y);
|
path.moveTo(x + ascent_ * slope_, y);
|
||||||
path.lineTo(x - (rect_.height() - ascent_) * slope, y + rect_.height());
|
path.lineTo(x - (rect_.height() - ascent_) * slope_,
|
||||||
path.lineTo(x + dir * caret_width_ - (rect_.height() - ascent_) * slope,
|
y + rect_.height());
|
||||||
|
path.lineTo(x + dir * caret_width_ - (rect_.height() - ascent_) * slope_,
|
||||||
y + rect_.height());
|
y + rect_.height());
|
||||||
path.lineTo(x + dir * caret_width_ + ascent_ * slope, y);
|
path.lineTo(x + dir * caret_width_ + ascent_ * slope_, y);
|
||||||
painter.setRenderHint(QPainter::Antialiasing, true);
|
painter.setRenderHint(QPainter::Antialiasing, true);
|
||||||
painter.fillPath(path, color_);
|
painter.fillPath(path, color_);
|
||||||
painter.setRenderHint(QPainter::Antialiasing, false);
|
painter.setRenderHint(QPainter::Antialiasing, false);
|
||||||
@ -176,7 +176,7 @@ public:
|
|||||||
int const m = y + rect_.height() / 2;
|
int const m = y + rect_.height() / 2;
|
||||||
int const d = TabIndicatorWidth - 1;
|
int const d = TabIndicatorWidth - 1;
|
||||||
// offset for slanted carret
|
// offset for slanted carret
|
||||||
int const sx = (slant_ && !rtl_) ? (ascent_ - (rect_.height() / 2 - d)) * slope : 0;
|
int const sx = (slant_ && !rtl_) ? (ascent_ - (rect_.height() / 2 - d)) * slope_ : 0;
|
||||||
painter.drawLine(x + dir * (caret_width_ + 1) + sx, m - d,
|
painter.drawLine(x + dir * (caret_width_ + 1) + sx, m - d,
|
||||||
x + dir * (caret_width_ + d + 1) + sx, m);
|
x + dir * (caret_width_ + d + 1) + sx, m);
|
||||||
painter.drawLine(x + dir * (caret_width_ + 1) + sx, m + d,
|
painter.drawLine(x + dir * (caret_width_ + 1) + sx, m + d,
|
||||||
@ -185,7 +185,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void update(int x, int y, int h, bool l_shape,
|
void update(int x, int y, int h, bool l_shape,
|
||||||
bool rtl, bool completable, bool slant, int ascent)
|
bool rtl, bool completable, bool slant, int ascent, double slope)
|
||||||
{
|
{
|
||||||
color_ = guiApp->colorCache().get(Color_cursor);
|
color_ = guiApp->colorCache().get(Color_cursor);
|
||||||
l_shape_ = l_shape;
|
l_shape_ = l_shape;
|
||||||
@ -194,6 +194,7 @@ public:
|
|||||||
x_ = x;
|
x_ = x;
|
||||||
slant_ = slant;
|
slant_ = slant;
|
||||||
ascent_ = ascent;
|
ascent_ = ascent;
|
||||||
|
slope_ = slope;
|
||||||
|
|
||||||
// extension to left and right
|
// extension to left and right
|
||||||
int l = 0;
|
int l = 0;
|
||||||
@ -245,6 +246,8 @@ private:
|
|||||||
bool slant_;
|
bool slant_;
|
||||||
/// the fontmetrics ascent for drawing slanted caret
|
/// the fontmetrics ascent for drawing slanted caret
|
||||||
int ascent_;
|
int ascent_;
|
||||||
|
/// the slope for drawing slanted caret
|
||||||
|
double slope_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -644,10 +647,11 @@ void GuiWorkArea::Private::updateCaretGeometry()
|
|||||||
Point point;
|
Point point;
|
||||||
int h = 0;
|
int h = 0;
|
||||||
buffer_view_->caretPosAndHeight(point, h);
|
buffer_view_->caretPosAndHeight(point, h);
|
||||||
|
Cursor & cur = buffer_view_->cursor();
|
||||||
|
|
||||||
// RTL or not RTL
|
// RTL or not RTL
|
||||||
bool l_shape = false;
|
bool l_shape = false;
|
||||||
Font const & realfont = buffer_view_->cursor().real_current_font;
|
Font const & realfont = cur.real_current_font;
|
||||||
FontMetrics const & fm = theFontMetrics(realfont.fontInfo());
|
FontMetrics const & fm = theFontMetrics(realfont.fontInfo());
|
||||||
BufferParams const & bp = buffer_view_->buffer().params();
|
BufferParams const & bp = buffer_view_->buffer().params();
|
||||||
bool const samelang = realfont.language() == bp.language;
|
bool const samelang = realfont.language() == bp.language;
|
||||||
@ -661,22 +665,23 @@ void GuiWorkArea::Private::updateCaretGeometry()
|
|||||||
l_shape = false;
|
l_shape = false;
|
||||||
|
|
||||||
// show caret on screen
|
// show caret on screen
|
||||||
Cursor & cur = buffer_view_->cursor();
|
|
||||||
bool completable = cur.inset().showCompletionCursor()
|
bool completable = cur.inset().showCompletionCursor()
|
||||||
&& completer_->completionAvailable()
|
&& completer_->completionAvailable()
|
||||||
&& !completer_->popupVisible()
|
&& !completer_->popupVisible()
|
||||||
&& !completer_->inlineVisible();
|
&& !completer_->inlineVisible();
|
||||||
|
|
||||||
caret_->update(point.x_, point.y_, h, l_shape, isrtl, completable,
|
// use slanted caret for italics in text edit mode
|
||||||
// use slanted caret for italics in text edit mode
|
// except for selections because the selection rect does not slant
|
||||||
fm.italic() && buffer_view_->cursor().inTexted()
|
int slant = fm.italic() && buffer_view_->cursor().inTexted()
|
||||||
// except for selections because the selection rect does not slant
|
&& !buffer_view_->cursor().selection();
|
||||||
&& !buffer_view_->cursor().selection(), fm.maxAscent());
|
double slope = fm.italicSlope();
|
||||||
|
|
||||||
|
caret_->update(point.x_, point.y_, h, l_shape, isrtl, completable, slant,
|
||||||
|
fm.maxAscent(), slope);
|
||||||
needs_caret_geometry_update_ = false;
|
needs_caret_geometry_update_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void GuiWorkArea::Private::showCaret()
|
void GuiWorkArea::Private::showCaret()
|
||||||
{
|
{
|
||||||
if (caret_visible_)
|
if (caret_visible_)
|
||||||
|
Loading…
Reference in New Issue
Block a user