Use custom-adjusted font metrics for custom fonts.

Fixes #27814.
This commit is contained in:
John Preston 2024-05-02 11:33:47 +04:00
parent 14e8b8fb91
commit 95ec0633ed
10 changed files with 77 additions and 149 deletions

View file

@ -241,7 +241,7 @@ Application::~Application() {
_mediaControlsManager = nullptr; _mediaControlsManager = nullptr;
Media::Player::finish(_audio.get()); Media::Player::finish(_audio.get());
style::stopManager(); style::StopManager();
Instance = nullptr; Instance = nullptr;
} }
@ -278,7 +278,7 @@ void Application::run() {
_translator = std::make_unique<Lang::Translator>(); _translator = std::make_unique<Lang::Translator>();
QCoreApplication::instance()->installTranslator(_translator.get()); QCoreApplication::instance()->installTranslator(_translator.get());
style::startManager(cScale()); style::StartManager(cScale());
Ui::InitTextOptions(); Ui::InitTextOptions();
Ui::StartCachedCorners(); Ui::StartCachedCorners();
Ui::Emoji::Init(); Ui::Emoji::Init();

View file

@ -269,6 +269,9 @@ SpeedButtonLayout::SpeedButtonLayout(
, _text(SpeedText(speed)) , _text(SpeedText(speed))
, _textWidth(_metrics.horizontalAdvance(_text)) , _textWidth(_metrics.horizontalAdvance(_text))
, _callback(std::move(callback)) { , _callback(std::move(callback)) {
const auto result = style::FindAdjustResult(_st.font->f);
_adjustedAscent = result ? result->ascent : _metrics.ascent();
_adjustedHeight = result ? result->height : _metrics.height();
} }
void SpeedButtonLayout::setSpeed(float64 speed) { void SpeedButtonLayout::setSpeed(float64 speed) {
@ -292,7 +295,7 @@ void SpeedButtonLayout::paint(QPainter &p, bool over, bool active) {
p.drawText( p.drawText(
QPointF(inner.topLeft()) + QPointF( QPointF(inner.topLeft()) + QPointF(
(inner.width() - _textWidth) / 2., (inner.width() - _textWidth) / 2.,
(inner.height() - _metrics.height()) / 2. + _metrics.ascent()), (inner.height() - _adjustedHeight) / 2. + _adjustedAscent),
_text); _text);
} }

View file

@ -69,6 +69,8 @@ private:
float64 _speed = 1.; float64 _speed = 1.;
QFontMetricsF _metrics; QFontMetricsF _metrics;
float64 _adjustedAscent = 0.;
float64 _adjustedHeight = 0.;
QString _text; QString _text;
float64 _textWidth = 0; float64 _textWidth = 0;

View file

@ -349,7 +349,7 @@ QImage Sibling::nameImage(const SiblingLayout &layout) {
const auto family = 0; // Default font family. const auto family = 0; // Default font family.
const auto font = style::font( const auto font = style::font(
_nameFontSize, _nameFontSize,
style::internal::FontSemibold, style::FontFlag::Semibold,
family); family);
_name.reset(); _name.reset();
_nameStyle = std::make_unique<style::TextStyle>(style::TextStyle{ _nameStyle = std::make_unique<style::TextStyle>(style::TextStyle{

View file

@ -53,10 +53,10 @@ public:
private: private:
void layout(); void layout();
void paintBubble(QPainter &p); void paintBubble(Painter &p);
void paintContent(QPainter &p); void paintContent(Painter &p);
void paintReply(QPainter &p); void paintReply(Painter &p);
void paintMessage(QPainter &p); void paintMessage(Painter &p);
void validateBubbleCache(); void validateBubbleCache();
@ -64,18 +64,16 @@ private:
const style::owned_color _msgBg; const style::owned_color _msgBg;
const style::owned_color _msgShadow; const style::owned_color _msgShadow;
QFont _nameFont; style::owned_font _nameFontOwned;
QFontMetricsF _nameMetrics; style::font _nameFont;
int _nameFontHeight = 0; style::TextStyle _nameStyle;
QFont _textFont; style::owned_font _textFontOwned;
QFontMetricsF _textMetrics; style::font _textFont;
int _textFontHeight = 0; style::TextStyle _textStyle;
QString _nameText; Ui::Text::String _nameText;
QString _replyText; Ui::Text::String _replyText;
QString _messageText; Ui::Text::String _messageText;
int _boundingLimit = 0;
QRect _replyRect; QRect _replyRect;
QRect _name; QRect _name;
@ -316,18 +314,18 @@ void Selector::validateCache(Entry &row) {
} }
row.paletteVersion = version; row.paletteVersion = version;
row.cache.fill(Qt::transparent); row.cache.fill(Qt::transparent);
auto font = style::ResolveFont(row.id, 0, st::boxFontSize); auto owned = style::owned_font(row.id, 0, st::boxFontSize);
const auto font = owned.font();
auto p = QPainter(&row.cache); auto p = QPainter(&row.cache);
p.setFont(font); p.setFont(font);
p.setPen(st::windowFg); p.setPen(st::windowFg);
const auto textw = width() - _st.padding.left() - _st.padding.right(); const auto textw = width() - _st.padding.left() - _st.padding.right();
const auto metrics = QFontMetrics(font); const auto textt = (_rowHeight - font->height) / 2.;
const auto textt = (_rowHeight - metrics.height()) / 2.;
p.drawText( p.drawText(
_st.padding.left(), _st.padding.left(),
int(base::SafeRound(textt)) + metrics.ascent(), textt + font->ascent,
metrics.elidedText(row.text, Qt::ElideRight, textw)); font->elided(row.text, textw));
} }
bool Selector::searching() const { bool Selector::searching() const {
@ -576,15 +574,15 @@ PreviewPainter::PreviewPainter(const QImage &bg, PreviewRequest request)
: _request(request) : _request(request)
, _msgBg(_request.msgBg) , _msgBg(_request.msgBg)
, _msgShadow(_request.msgShadow) , _msgShadow(_request.msgShadow)
, _nameFont(style::ResolveFont( , _nameFontOwned(_request.family, style::FontFlag::Semibold, st::fsize)
_request.family, , _nameFont(_nameFontOwned.font())
style::internal::FontSemibold, , _nameStyle(st::semiboldTextStyle)
st::fsize)) , _textFontOwned(_request.family, 0, st::fsize)
, _nameMetrics(_nameFont) , _textFont(_textFontOwned.font())
, _nameFontHeight(base::SafeRound(_nameMetrics.height())) , _textStyle(st::defaultTextStyle) {
, _textFont(style::ResolveFont(_request.family, 0, st::fsize)) _nameStyle.font = _nameFont;
, _textMetrics(_textFont) _textStyle.font = _textFont;
, _textFontHeight(base::SafeRound(_textMetrics.height())) {
layout(); layout();
const auto ratio = style::DevicePixelRatio(); const auto ratio = style::DevicePixelRatio();
@ -593,14 +591,14 @@ PreviewPainter::PreviewPainter(const QImage &bg, PreviewRequest request)
QImage::Format_ARGB32_Premultiplied); QImage::Format_ARGB32_Premultiplied);
_result.setDevicePixelRatio(ratio); _result.setDevicePixelRatio(ratio);
auto p = QPainter(&_result); auto p = Painter(&_result);
p.drawImage(0, 0, bg); p.drawImage(0, 0, bg);
p.translate(_bubble.topLeft()); p.translate(_bubble.topLeft());
paintBubble(p); paintBubble(p);
} }
void PreviewPainter::paintBubble(QPainter &p) { void PreviewPainter::paintBubble(Painter &p) {
validateBubbleCache(); validateBubbleCache();
const auto bubble = QRect(QPoint(), _bubble.size()); const auto bubble = QRect(QPoint(), _bubble.size());
const auto cornerShadow = _bubbleShadowBottomRight.size() const auto cornerShadow = _bubbleShadowBottomRight.size()
@ -636,7 +634,7 @@ void PreviewPainter::validateBubbleCache() {
= Ui::PrepareCornerPixmaps(radius, _msgShadow.color()).p[3]; = Ui::PrepareCornerPixmaps(radius, _msgShadow.color()).p[3];
} }
void PreviewPainter::paintContent(QPainter &p) { void PreviewPainter::paintContent(Painter &p) {
paintReply(p); paintReply(p);
p.translate(_message.topLeft()); p.translate(_message.topLeft());
@ -645,7 +643,7 @@ void PreviewPainter::paintContent(QPainter &p) {
paintMessage(p); paintMessage(p);
} }
void PreviewPainter::paintReply(QPainter &p) { void PreviewPainter::paintReply(Painter &p) {
{ {
auto hq = PainterHighQualityEnabler(p); auto hq = PainterHighQualityEnabler(p);
p.setPen(Qt::NoPen); p.setPen(Qt::NoPen);
@ -672,26 +670,25 @@ void PreviewPainter::paintReply(QPainter &p) {
p.setClipping(false); p.setClipping(false);
p.setPen(_request.replyNameFg); p.setPen(_request.replyNameFg);
p.setFont(_nameFont); _nameText.drawLeftElided(
const auto name = _nameMetrics.elidedText( p,
_nameText, _name.x(),
Qt::ElideRight, _name.y(),
_name.width()); _name.width(),
p.drawText(_name.x(), _name.y() + _nameMetrics.ascent(), name); _outer.width());
p.setPen(_request.textFg); p.setPen(_request.textFg);
p.setFont(_textFont); _replyText.drawLeftElided(
const auto reply = _textMetrics.elidedText( p,
_replyText, _reply.x(),
Qt::ElideRight, _reply.y(),
_reply.width()); _reply.width(),
p.drawText(_reply.x(), _reply.y() + _textMetrics.ascent(), reply); _outer.width());
} }
void PreviewPainter::paintMessage(QPainter &p) { void PreviewPainter::paintMessage(Painter &p) {
p.setPen(_request.textFg); p.setPen(_request.textFg);
p.setFont(_textFont); _messageText.drawLeft(p, 0, 0, _message.width(), _message.width());
p.drawText(QRect(0, 0, _message.width(), _boundingLimit), _messageText);
} }
QImage PreviewPainter::takeResult() { QImage PreviewPainter::takeResult() {
@ -705,79 +702,54 @@ void PreviewPainter::layout() {
- 2 * skip - 2 * skip
- st::msgPadding.left() - st::msgPadding.left()
- st::msgPadding.right(); - st::msgPadding.right();
_boundingLimit = 100 * maxTextWidth;
const auto textSize = [&]( _nameText = Ui::Text::String(
const QFontMetricsF &metrics, _nameStyle,
const QString &text, tr::lng_settings_chat_message_reply_from(tr::now));
int availableWidth, _replyText = Ui::Text::String(
bool oneline = false) { _textStyle,
const auto result = metrics.boundingRect( tr::lng_background_text2(tr::now));
QRect(0, 0, availableWidth, _boundingLimit), _messageText = Ui::Text::String(
(Qt::AlignLeft _textStyle,
| Qt::AlignTop tr::lng_background_text1(tr::now),
| (oneline ? Qt::TextSingleLine : Qt::TextWordWrap)), kDefaultTextOptions,
text); st::msgMinWidth / 2);
return QSize(
int(std::ceil(result.x() + result.width())),
int(std::ceil(result.y() + result.height())));
};
const auto naturalSize = [&](
const QFontMetricsF &metrics,
const QString &text,
bool oneline = false) {
return textSize(metrics, text, _boundingLimit, oneline);
};
_nameText = tr::lng_settings_chat_message_reply_from(tr::now);
_replyText = tr::lng_background_text2(tr::now);
_messageText = tr::lng_background_text1(tr::now);
const auto nameSize = naturalSize(_nameMetrics, _nameText, true);
const auto nameMaxWidth = nameSize.width();
const auto replySize = naturalSize(_textMetrics, _replyText, true);
const auto replyMaxWidth = replySize.width();
const auto messageSize = naturalSize(_textMetrics, _messageText);
const auto messageMaxWidth = messageSize.width();
const auto namePosition = QPoint( const auto namePosition = QPoint(
st::historyReplyPadding.left(), st::historyReplyPadding.left(),
st::historyReplyPadding.top()); st::historyReplyPadding.top());
const auto replyPosition = QPoint( const auto replyPosition = QPoint(
st::historyReplyPadding.left(), st::historyReplyPadding.left(),
(st::historyReplyPadding.top() + _nameFontHeight)); (st::historyReplyPadding.top() + _nameFont->height));
const auto paddingRight = st::historyReplyPadding.right(); const auto paddingRight = st::historyReplyPadding.right();
const auto wantedWidth = std::max({ const auto wantedWidth = std::max({
namePosition.x() + nameMaxWidth + paddingRight, namePosition.x() + _nameText.maxWidth() + paddingRight,
replyPosition.x() + replyMaxWidth + paddingRight, replyPosition.x() + _replyText.maxWidth() + paddingRight,
messageMaxWidth _messageText.maxWidth()
}); });
const auto messageWidth = std::clamp( const auto messageWidth = std::clamp(
wantedWidth, wantedWidth,
minTextWidth, minTextWidth,
maxTextWidth); maxTextWidth);
const auto messageHeight = textSize( const auto messageHeight = _messageText.countHeight(messageWidth);
_textMetrics,
_messageText,
maxTextWidth).height();
_replyRect = QRect( _replyRect = QRect(
st::msgReplyBarPos.x(), st::msgReplyBarPos.x(),
st::historyReplyTop, st::historyReplyTop,
messageWidth, messageWidth,
(st::historyReplyPadding.top() (st::historyReplyPadding.top()
+ _nameFontHeight + _nameFont->height
+ _textFontHeight + _textFont->height
+ st::historyReplyPadding.bottom())); + st::historyReplyPadding.bottom()));
_name = QRect( _name = QRect(
_replyRect.topLeft() + namePosition, _replyRect.topLeft() + namePosition,
QSize(messageWidth - namePosition.x(), _nameFontHeight)); QSize(messageWidth - namePosition.x(), _nameFont->height));
_reply = QRect( _reply = QRect(
_replyRect.topLeft() + replyPosition, _replyRect.topLeft() + replyPosition,
QSize(messageWidth - replyPosition.x(), _textFontHeight)); QSize(messageWidth - replyPosition.x(), _textFont->height));
_message = QRect(0, 0, messageWidth, messageHeight); _message = QRect(0, 0, messageWidth, messageHeight);
const auto replySkip = _replyRect.y() const auto replySkip = _replyRect.y()

View file

@ -649,7 +649,7 @@ void ChatStyle::clearColorIndexCaches() {
void ChatStyle::assignPalette(not_null<const style::palette*> palette) { void ChatStyle::assignPalette(not_null<const style::palette*> palette) {
*static_cast<style::palette*>(this) = *palette; *static_cast<style::palette*>(this) = *palette;
style::internal::resetIcons(); style::internal::ResetIcons();
clearColorIndexCaches(); clearColorIndexCaches();
for (auto &style : _messageStyles) { for (auto &style : _messageStyles) {

View file

@ -29,18 +29,6 @@ CountryInput::CountryInput(
, _st(st) , _st(st)
, _text(tr::lng_country_code(tr::now)) { , _text(tr::lng_country_code(tr::now)) {
resize(_st.width, _st.heightMin); resize(_st.width, _st.heightMin);
auto placeholderFont = _st.placeholderFont->f;
placeholderFont.setStyleStrategy(QFont::PreferMatch);
//auto metrics = QFontMetrics(placeholderFont);
auto placeholder = QString();// metrics.elidedText(tr::lng_country_fake_ph(tr::now), Qt::ElideRight, availableWidth);
if (!placeholder.isNull()) {
_placeholderPath.addText(
0,
QFontMetrics(placeholderFont).ascent(),
placeholderFont,
placeholder);
}
} }
void CountryInput::paintEvent(QPaintEvent *e) { void CountryInput::paintEvent(QPaintEvent *e) {
@ -70,42 +58,6 @@ void CountryInput::paintEvent(QPaintEvent *e) {
p.setFont(_st.font); p.setFont(_st.font);
p.setPen(_st.textFg); p.setPen(_st.textFg);
p.drawText(rect().marginsRemoved(_st.textMargins), _text, _st.textAlign); p.drawText(rect().marginsRemoved(_st.textMargins), _text, _st.textAlign);
if (!_placeholderPath.isEmpty()) {
auto placeholderShiftDegree = 1.;
p.save();
p.setClipRect(r);
const auto placeholderTop = anim::interpolate(
0,
_st.placeholderShift,
placeholderShiftDegree);
auto r = QRect(rect() - (_st.textMargins + _st.placeholderMargins));
r.moveTop(r.top() + placeholderTop);
if (rtl()) {
r.moveLeft(width() - r.left() - r.width());
}
const auto placeholderScale = 1.
- (1. - _st.placeholderScale) * placeholderShiftDegree;
auto placeholderFg = anim::color(
_st.placeholderFg,
_st.placeholderFgActive,
0.);
placeholderFg = anim::color(
placeholderFg,
_st.placeholderFgError,
0.);
PainterHighQualityEnabler hq(p);
p.setPen(Qt::NoPen);
p.setBrush(placeholderFg);
p.translate(r.topLeft());
p.scale(placeholderScale, placeholderScale);
p.drawPath(_placeholderPath);
p.restore();
}
} }
void CountryInput::mouseMoveEvent(QMouseEvent *e) { void CountryInput::mouseMoveEvent(QMouseEvent *e) {

View file

@ -53,7 +53,6 @@ private:
bool _active = false; bool _active = false;
QString _text; QString _text;
QString _chosenIso; QString _chosenIso;
QPainterPath _placeholderPath;
rpl::event_stream<QString> _codeChanged; rpl::event_stream<QString> _codeChanged;

@ -1 +1 @@
Subproject commit afed06a4c04d1a1cf7cfce4faca273e1f574462e Subproject commit 6462cda46ec5d48a9ae452ba1b6f7dfe1b6d882d

@ -1 +1 @@
Subproject commit 4ddff63a9b6cd2e2787995611f1ee4b145bdb504 Subproject commit 86dc01e9bc61db48d33ff253d29bfedd74309278