From cbda03ed6c1ef8a2ff006be716c9b61cf565bcc8 Mon Sep 17 00:00:00 2001 From: in1tiate <32779090+in1tiate@users.noreply.github.com> Date: Sat, 31 Aug 2024 08:24:55 -0500 Subject: [PATCH] [Refactor] Update font outline code to account for offsets --- src/aotextboxwidgets.cpp | 128 ++++++++++++++++++++++++++++++--------- src/aotextboxwidgets.h | 20 ++++-- src/courtroom.cpp | 6 +- 3 files changed, 118 insertions(+), 36 deletions(-) diff --git a/src/aotextboxwidgets.cpp b/src/aotextboxwidgets.cpp index a6999be..c39b26f 100644 --- a/src/aotextboxwidgets.cpp +++ b/src/aotextboxwidgets.cpp @@ -1,17 +1,13 @@ #include "aotextboxwidgets.h" +// Sane outlined QLabel solution ported from PyQt solution on StackOverflow by alec +// https://stackoverflow.com/questions/64290561/qlabel-correct-positioning-for-text-outline + AOChatboxLabel::AOChatboxLabel(QWidget *parent) : QLabel(parent) -{} - -void AOChatboxLabel::setOutlineColor(QColor color) { - m_outline_color = color; -} - -void AOChatboxLabel::setOutlineWidth(int width) -{ - m_outline_width = width; + setBrush(QBrush(Qt::white)); + setPen(QPen(Qt::black)); } void AOChatboxLabel::setIsOutlined(bool outlined) @@ -19,39 +15,115 @@ void AOChatboxLabel::setIsOutlined(bool outlined) m_outline = outlined; } -void AOChatboxLabel::setTextColor(QColor color) +bool AOChatboxLabel::pointMode() { - m_text_color = color; + return m_pointmode; +} + +void AOChatboxLabel::setPointMode(bool mode) +{ + m_pointmode = mode; +} + +double AOChatboxLabel::outlineThickness() +{ + if (pointMode()) + { + return m_outline_width * font().pointSize(); + } + else + return m_outline_width; +} + +void AOChatboxLabel::setOutlineThickness(double w) +{ + m_outline_width = w; +} + +void AOChatboxLabel::setBrush(QBrush brush) +{ + m_brush = brush; +} +void AOChatboxLabel::setPen(QPen pen) +{ + m_pen = pen; +} + +QSize AOChatboxLabel::sizeHint() +{ + int nrml_w = std::ceil(outlineThickness() * 2); + return QLabel::sizeHint() + QSize(nrml_w, nrml_w); +} +QSize AOChatboxLabel::minimumSizeHint() +{ + int nrml_w = std::ceil(outlineThickness() * 2); + return QLabel::minimumSizeHint() + QSize(nrml_w, nrml_w); } void AOChatboxLabel::paintEvent(QPaintEvent *event) { if (m_outline) { - QBrush brush; - QPen pen; - QPointF baseline(m_outline_width, fontMetrics().height()); + double w = outlineThickness(); + QRectF rect = this->rect(); + QFontMetrics metrics = QFontMetrics(this->font()); + QRect tr = metrics.boundingRect(text()).adjusted(0, 0, w, w); + int l_indent; + int x; + int y; - // Set up brush (base text) - brush.setColor(m_text_color); - brush.setStyle(Qt::SolidPattern); + if (indent() == -1) + { + if (frameWidth()) + { + l_indent = (metrics.boundingRect("x").width() + w * 2) / 2; + } + else + { + l_indent = w; + } + } + else + { + l_indent = indent(); + } - // Set up outline - pen.setColor(m_outline_color); - pen.setWidthF(m_outline_width); + if (alignment() & Qt::AlignLeft) + { + x = rect.left() + l_indent - std::min(metrics.leftBearing(text()[0]), 0); + } + else if (alignment() & Qt::AlignRight) + { + x = rect.x() + rect.width() - l_indent - tr.width(); + } + else + { + x = (rect.width() - tr.width()) / 2; + } + if (alignment() & Qt::AlignTop) + { + y = rect.top() + l_indent + metrics.ascent(); + } + else if (alignment() & Qt::AlignBottom) + { + y = rect.y() + rect.height() - l_indent - metrics.descent(); + } + else + { + y = (rect.height() + metrics.ascent() - metrics.descent()) / 2; + } + + m_pen.setWidth(w * 2); QPainterPath path; - path.addText(baseline, font(), text()); + path.addText(x, y, font(), text()); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); - // draw outline - painter.setPen(pen); - painter.drawPath(path); - // remove outline pen, then draw text on top - painter.setPen(Qt::NoPen); - painter.setBrush(brush); - painter.drawPath(path); + painter.strokePath(path, m_pen); + if (1 < m_brush.style() && m_brush.style() < 15) + painter.fillPath(path, palette().window()); + painter.fillPath(path, m_brush); } else { diff --git a/src/aotextboxwidgets.h b/src/aotextboxwidgets.h index fa7288f..6f25809 100644 --- a/src/aotextboxwidgets.h +++ b/src/aotextboxwidgets.h @@ -6,6 +6,7 @@ #include #include #include +#include #include class AOChatboxLabel : public QLabel @@ -16,17 +17,26 @@ public: AOChatboxLabel(QWidget *parent); void setIsOutlined(bool outlined); - void setOutlineColor(QColor color); - void setOutlineWidth(int width); - void setTextColor(QColor color); + bool pointMode(); + void setPointMode(bool mode); + + double outlineThickness(); + void setOutlineThickness(double w); + + void setBrush(QBrush brush); + void setPen(QPen pen); + + QSize sizeHint(); + QSize minimumSizeHint(); protected: void paintEvent(QPaintEvent *event); private: bool m_outline = false; - QColor m_outline_color; + bool m_pointmode = false; int m_outline_width = 1; - QColor m_text_color; + QBrush m_brush; + QPen m_pen; }; diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 2d30108..b8e8625 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -1294,9 +1294,9 @@ void Courtroom::set_qfont(QWidget *widget, QString class_name, QFont font, QColo if (class_name == "AOChatboxLabel") { // Only shownames can be outlined ui_vp_showname->setIsOutlined(outlined); - ui_vp_showname->setOutlineColor(outline_color); - ui_vp_showname->setTextColor(f_color); - ui_vp_showname->setOutlineWidth(outline_width); + ui_vp_showname->setBrush(QBrush(f_color)); + ui_vp_showname->setPen(QPen(outline_color)); + ui_vp_showname->setOutlineThickness(outline_width); } font.setBold(bold);