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

View file

@ -269,6 +269,9 @@ SpeedButtonLayout::SpeedButtonLayout(
, _text(SpeedText(speed))
, _textWidth(_metrics.horizontalAdvance(_text))
, _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) {
@ -292,7 +295,7 @@ void SpeedButtonLayout::paint(QPainter &p, bool over, bool active) {
p.drawText(
QPointF(inner.topLeft()) + QPointF(
(inner.width() - _textWidth) / 2.,
(inner.height() - _metrics.height()) / 2. + _metrics.ascent()),
(inner.height() - _adjustedHeight) / 2. + _adjustedAscent),
_text);
}

View file

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

View file

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

View file

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

View file

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

View file

@ -29,18 +29,6 @@ CountryInput::CountryInput(
, _st(st)
, _text(tr::lng_country_code(tr::now)) {
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) {
@ -70,42 +58,6 @@ void CountryInput::paintEvent(QPaintEvent *e) {
p.setFont(_st.font);
p.setPen(_st.textFg);
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) {

View file

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

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

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