diff --git a/src/textutil.cpp b/src/textutil.cpp
index 81209a1f1..d0f278008 100644
--- a/src/textutil.cpp
+++ b/src/textutil.cpp
@@ -294,7 +294,7 @@ static void emojiconifyPlainText(RTParse &p, const QString &in)
p.putRich(QLatin1String(R"html()html") + code + QLatin1String(""));
#else
// FIXME custom style here is a hack. This supposed to be handled via style resource in PsiTextView
- p.putRich(QString(R"()")
+ p.putRich(QString(R"()")
.arg(code));
#endif
};
diff --git a/src/widgets/psirichtext.cpp b/src/widgets/psirichtext.cpp
index ef9430138..cf5d32918 100644
--- a/src/widgets/psirichtext.cpp
+++ b/src/widgets/psirichtext.cpp
@@ -105,7 +105,8 @@ class TextIconFormat : public QTextCharFormat {
TextIconFormat(const QString &iconName, const QString &text, std::optional width = {},
std::optional height = {}, std::optional minWidth = {},
std::optional minHeight = {}, std::optional maxWidth = {},
- std::optional maxHeight = {}, std::optional valign = {});
+ std::optional maxHeight = {}, std::optional valign = {},
+ std::optional fontSize = {});
enum Property {
IconName = QTextFormat::UserProperty + 1,
@@ -115,7 +116,8 @@ class TextIconFormat : public QTextCharFormat {
IconMinWidth = QTextFormat::UserProperty + 5,
IconMinHeight = QTextFormat::UserProperty + 6,
IconMaxWidth = QTextFormat::UserProperty + 7,
- IconMaxHeight = QTextFormat::UserProperty + 8
+ IconMaxHeight = QTextFormat::UserProperty + 8,
+ IconFontSize = QTextFormat::UserProperty + 9
};
};
@@ -123,7 +125,8 @@ TextIconFormat::TextIconFormat(const QString &iconName, const QString &text, std
std::optional height, std::optional minWidth,
std::optional minHeight, std::optional maxWidth,
std::optional maxHeight,
- std::optional valign) : QTextCharFormat()
+ std::optional valign,
+ std::optional fontSize) : QTextCharFormat()
{
Q_UNUSED(text);
@@ -148,10 +151,12 @@ TextIconFormat::TextIconFormat(const QString &iconName, const QString &text, std
if (maxHeight) {
QTextFormat::setProperty(IconMaxHeight, QVariant::fromValue(*maxHeight));
}
-
if (valign) {
setVerticalAlignment(*valign);
}
+ if (fontSize) {
+ QTextFormat::setProperty(IconFontSize, QVariant::fromValue(*fontSize));
+ }
// TODO: handle animations
}
@@ -171,6 +176,59 @@ class TextIconHandler : public QObject, public QTextObjectInterface {
virtual QSizeF intrinsicSize(QTextDocument *doc, int posInDocument, const QTextFormat &format);
virtual void drawObject(QPainter *painter, const QRectF &rect, QTextDocument *doc, int posInDocument,
const QTextFormat &format);
+
+private:
+
+ QFont adjustFontSize(const QTextCharFormat charFormat) {
+ auto propHeight = charFormat.property(TextIconFormat::IconHeight);
+ auto propMinHeight = charFormat.property(TextIconFormat::IconMinHeight);
+ auto propMaxHeight = charFormat.property(TextIconFormat::IconMaxHeight);
+ auto propFontSize = charFormat.property(TextIconFormat::IconFontSize);
+
+ std::optional height;
+ std::optional minHeight;
+ std::optional maxHeight;
+
+ if (propMinHeight.isValid()) {
+ minHeight = htmlSizeToPixels(propMinHeight.value(), charFormat);
+ }
+ if (propMaxHeight.isValid()) {
+ maxHeight = htmlSizeToPixels(propMaxHeight.value(), charFormat);
+ }
+ if (propHeight.isValid()) { // we want to scale ignoring aspect ratio
+ int limitMin = minHeight ? *minHeight : 8;
+ int limitMax = maxHeight ? *maxHeight : 1080;
+ height = htmlSizeToPixels(propHeight.value(), charFormat);
+ height = qMax(qMin(limitMax, *height), limitMin);
+ }
+
+ auto font = charFormat.font();
+ int ps = font.pixelSize();
+ if (ps == -1) {
+ ps = pointToPixel(font.pointSizeF());
+ }
+ if (propFontSize.isValid()) {
+ auto fontSize = propFontSize.value();
+ if (fontSize.unit == HtmlSize::Em) {
+ ps *= fontSize.size;
+ } else if (fontSize.unit == HtmlSize::Px) {
+ ps = fontSize.size;
+ } else if (fontSize.unit == HtmlSize::Pt) {
+ ps = pointToPixel(fontSize.size);
+ }
+ }
+ if (height) {
+ ps = *height;
+ } else if (minHeight && maxHeight) {
+ ps = (*minHeight + *maxHeight) / 2;
+ } else if (minHeight && ps < *minHeight) {
+ ps = *minHeight;
+ } else if (maxHeight && ps > *maxHeight) {
+ ps = *maxHeight;
+ }
+ font.setPixelSize(ps);
+ return font;
+ }
};
TextIconHandler::TextIconHandler(QObject *parent) : QObject(parent) { }
@@ -194,9 +252,9 @@ QSizeF TextIconHandler::intrinsicSize(QTextDocument *doc, int posInDocument, con
}
ret = icon->size();
doScaling = icon->isScalable();
- } else {
- QFontMetrics fm(charFormat.font());
- ret = fm.boundingRect(iconText).size();
+ } else if (!iconText.isEmpty()) {
+ auto font = adjustFontSize(charFormat);
+ return QFontMetricsF(font).tightBoundingRect(iconText).size()*1.16; // 1.16 - magic for Windows
}
if (ret.isEmpty()) {
// something went wrong with this icon
@@ -297,6 +355,7 @@ QSizeF TextIconHandler::intrinsicSize(QTextDocument *doc, int posInDocument, con
ret = desiredSize;
}
}
+ qDebug() << ret;
return ret;
}
@@ -317,10 +376,10 @@ void TextIconHandler::drawObject(QPainter *painter, const QRectF &rect, QTextDoc
// qDebug() << "render icon " << iconText << iconName << " in " << rect;
if (iconName.isEmpty()) {
- auto font = charFormat.font();
- font.setPixelSize(rect.height());
+ auto font = adjustFontSize(charFormat);
+ font.setPixelSize(font.pixelSize());
painter->setFont(font);
- painter->drawText(rect, iconText);
+ painter->drawText(rect, Qt::AlignHCenter | Qt::AlignTop, iconText);
} else {
auto pixmap = IconsetFactory::iconPixmap(iconName, rect.size().toSize());
auto alignedSize = rect.size().toSize();
@@ -481,6 +540,7 @@ static QString convertIconsToObjectReplacementCharacters(const QStringView &text
std::optional minHeight;
std::optional maxWidth;
std::optional maxHeight;
+ std::optional fontSize;
QString iconName;
QString iconText;
QString iconType;
@@ -524,13 +584,15 @@ static QString convertIconsToObjectReplacementCharacters(const QStringView &text
}
} else if (match.capturedView(1) == QLatin1String("type")) {
iconType = match.captured(2);
+ } else if (match.capturedView(1) == QLatin1String("font-size")) {
+ fontSize = parseSize(match.capturedView(2));
}
}
if (!iconName.isEmpty() || !iconText.isEmpty()) {
auto format = new TextIconFormat(iconName, iconText, std::move(width), std::move(height),
std::move(minWidth), std::move(minHeight), std::move(maxWidth),
- std::move(maxHeight), std::move(valign));
+ std::move(maxHeight), std::move(valign), std::move(fontSize));
if (iconType == QLatin1String("smiley") && iconName.isEmpty()) {
format->setFontFamilies(emojiFontFamilies);
}