From fc81b118c75d21be14810aef232278cd6729841b Mon Sep 17 00:00:00 2001 From: fourtf Date: Sat, 23 Dec 2017 21:18:13 +0100 Subject: [PATCH] replaced qt font scaling remove the qt font scaling and added code that uses the actual scale/dpi value --- chatterino.pro | 6 +- src/fontmanager.cpp | 33 +++++++--- src/fontmanager.hpp | 8 ++- src/main.cpp | 3 +- src/messages/message.cpp | 12 ++-- src/messages/messagebuilder.cpp | 6 +- src/messages/messageref.cpp | 90 +++++++++++--------------- src/messages/messageref.hpp | 8 ++- src/messages/word.cpp | 99 ++++++++++++++++++++++------- src/messages/word.hpp | 56 ++++++++++------ src/messages/wordflags.hpp | 1 + src/messages/wordpart.cpp | 12 ++-- src/messages/wordpart.hpp | 6 +- src/precompiled_headers.hpp | 51 +++++++++++++++ src/settingsmanager.cpp | 4 +- src/settingsmanager.hpp | 4 +- src/twitch/twitchmessagebuilder.cpp | 22 ++++--- src/widgets/emotepopup.cpp | 12 ++-- src/widgets/helper/channelview.cpp | 12 ++-- src/widgets/helper/splitinput.cpp | 6 +- src/widgets/settingsdialog.cpp | 2 +- 21 files changed, 298 insertions(+), 155 deletions(-) create mode 100644 src/messages/wordflags.hpp create mode 100644 src/precompiled_headers.hpp diff --git a/chatterino.pro b/chatterino.pro index 1c71d8e4a..c66fe3574 100644 --- a/chatterino.pro +++ b/chatterino.pro @@ -8,6 +8,7 @@ QT += core gui network multimedia CONFIG += communi COMMUNI += core model util CONFIG += c++14 +PRECOMPILED_HEADER = precompiled_header.hpp greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -111,6 +112,7 @@ SOURCES += \ src/widgets/accountswitchpopupwidget.cpp HEADERS += \ + src/precompiled_headers.hpp \ src/asyncexec.hpp \ src/channel.hpp \ src/colorscheme.hpp \ @@ -183,7 +185,9 @@ HEADERS += \ src/util/helpers.hpp \ src/widgets/accountswitchwidget.hpp \ src/widgets/accountswitchpopupwidget.hpp \ - src/const.hpp + src/const.hpp \ + src/precompiled_headers.hpp \ + src/messages/wordflags.hpp PRECOMPILED_HEADER = diff --git a/src/fontmanager.cpp b/src/fontmanager.cpp index 5129ac4cc..f44d7924a 100644 --- a/src/fontmanager.cpp +++ b/src/fontmanager.cpp @@ -6,29 +6,33 @@ namespace chatterino { FontManager::FontManager() : currentFontFamily("/appearance/currentFontFamily", "Arial") - , currentFontSize("/appearance/currentFontSize", 14) - , currentFont(this->currentFontFamily.getValue().c_str(), currentFontSize.getValue()) + , currentFontSize("/appearance/currentFontSize", 12) +// , currentFont(this->currentFontFamily.getValue().c_str(), currentFontSize.getValue()) { this->currentFontFamily.connect([this](const std::string &newValue, auto) { this->incGeneration(); - this->currentFont.setFamily(newValue.c_str()); + // this->currentFont.setFamily(newValue.c_str()); + this->currentFontByDpi.clear(); this->fontChanged.invoke(); }); this->currentFontSize.connect([this](const int &newValue, auto) { this->incGeneration(); - this->currentFont.setSize(newValue); + // this->currentFont.setSize(newValue); + this->currentFontByDpi.clear(); this->fontChanged.invoke(); }); } -QFont &FontManager::getFont(Type type) +QFont &FontManager::getFont(Type type, float dpi) { - return this->currentFont.getFont(type); + // return this->currentFont.getFont(type); + return this->getCurrentFont(dpi).getFont(type); } -QFontMetrics &FontManager::getFontMetrics(Type type) +QFontMetrics &FontManager::getFontMetrics(Type type, float dpi) { - return this->currentFont.getFontMetrics(type); + // return this->currentFont.getFontMetrics(type); + return this->getCurrentFont(dpi).getFontMetrics(type); } FontManager::FontData &FontManager::Font::getFontData(Type type) @@ -62,4 +66,17 @@ QFontMetrics &FontManager::Font::getFontMetrics(Type type) return this->getFontData(type).metrics; } +FontManager::Font &FontManager::getCurrentFont(float dpi) +{ + for (auto it = this->currentFontByDpi.begin(); it != this->currentFontByDpi.end(); it++) { + if (it->first == dpi) { + return it->second; + } + } + this->currentFontByDpi.push_back(std::make_pair( + dpi, + Font(this->currentFontFamily.getValue().c_str(), this->currentFontSize.getValue() * dpi))); + + return this->currentFontByDpi.back().second; +} } // namespace chatterino diff --git a/src/fontmanager.hpp b/src/fontmanager.hpp index 289514cba..905835e7c 100644 --- a/src/fontmanager.hpp +++ b/src/fontmanager.hpp @@ -30,8 +30,8 @@ public: return instance; } - QFont &getFont(Type type); - QFontMetrics &getFontMetrics(Type type); + QFont &getFont(Type type, float dpi); + QFontMetrics &getFontMetrics(Type type, float dpi); int getGeneration() const { @@ -122,10 +122,12 @@ private: FontData veryLarge; }; + Font &getCurrentFont(float dpi); + // Future plans: // Could have multiple fonts in here, such as "Menu font", "Application font", "Chat font" - Font currentFont; + std::list> currentFontByDpi; int generation = 0; }; diff --git a/src/main.cpp b/src/main.cpp index b33264096..22ed54d54 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -44,7 +44,8 @@ inline bool initSettings(bool portable) int main(int argc, char *argv[]) { - // QApplication::setAttribute(Qt::AA_Use96Dpi, true); + QApplication::setAttribute(Qt::AA_Use96Dpi, true); + QApplication::setAttribute(Qt::AA_DisableHighDpiScaling, true); QApplication::setAttribute(Qt::AA_UseSoftwareOpenGL, true); QApplication a(argc, argv); diff --git a/src/messages/message.cpp b/src/messages/message.cpp index 353d32733..dac42a08f 100644 --- a/src/messages/message.cpp +++ b/src/messages/message.cpp @@ -83,13 +83,15 @@ void AddCurrentTimestamp(Message *message) strftime(timeStampBuffer, 69, "%H:%M", localtime(&t)); QString timestampNoSeconds(timeStampBuffer); message->getWords().push_back(Word(timestampNoSeconds, Word::TimestampNoSeconds, - MessageColor(MessageColor::System), QString(), QString())); + MessageColor(MessageColor::System), FontManager::Medium, + QString(), QString())); // Add word for timestamp with seconds strftime(timeStampBuffer, 69, "%H:%M:%S", localtime(&t)); QString timestampWithSeconds(timeStampBuffer); message->getWords().push_back(Word(timestampWithSeconds, Word::TimestampWithSeconds, - MessageColor(MessageColor::System), QString(), QString())); + MessageColor(MessageColor::System), FontManager::Medium, + QString(), QString())); } } // namespace @@ -101,7 +103,8 @@ Message *Message::createSystemMessage(const QString &text) AddCurrentTimestamp(message); - Word word(text, Word::Type::Default, MessageColor(MessageColor::Type::System), text, QString()); + Word word(text, Word::Flags::Default, MessageColor(MessageColor::Type::System), + FontManager::Medium, text, QString()); message->getWords().push_back(word); @@ -142,7 +145,8 @@ Message *Message::createTimeoutMessage(const QString &username, const QString &d } text.append("."); - Word word(text, Word::Type::Default, MessageColor(MessageColor::Type::System), text, QString()); + Word word(text, Word::Flags::Default, MessageColor(MessageColor::Type::System), + FontManager::Medium, text, QString()); message->getWords().push_back(word); diff --git a/src/messages/messagebuilder.cpp b/src/messages/messagebuilder.cpp index e1513081f..37b9aab05 100644 --- a/src/messages/messagebuilder.cpp +++ b/src/messages/messagebuilder.cpp @@ -42,13 +42,15 @@ void MessageBuilder::appendTimestamp(time_t time) strftime(timeStampBuffer, 69, "%H:%M", localtime(&time)); QString timestampNoSeconds(timeStampBuffer); this->appendWord(Word(timestampNoSeconds, Word::TimestampNoSeconds, - MessageColor(MessageColor::System), QString(), QString())); + MessageColor(MessageColor::System), FontManager::Medium, QString(), + QString())); // Add word for timestamp with seconds strftime(timeStampBuffer, 69, "%H:%M:%S", localtime(&time)); QString timestampWithSeconds(timeStampBuffer); this->appendWord(Word(timestampWithSeconds, Word::TimestampWithSeconds, - MessageColor(MessageColor::System), QString(), QString())); + MessageColor(MessageColor::System), FontManager::Medium, QString(), + QString())); } QString MessageBuilder::matchLink(const QString &string) diff --git a/src/messages/messageref.cpp b/src/messages/messageref.cpp index 5a632a493..b347c6fc3 100644 --- a/src/messages/messageref.cpp +++ b/src/messages/messageref.cpp @@ -4,10 +4,10 @@ #include -#define MARGIN_LEFT (int)(8 * this->dpiMultiplier) -#define MARGIN_RIGHT (int)(8 * this->dpiMultiplier) -#define MARGIN_TOP (int)(4 * this->dpiMultiplier) -#define MARGIN_BOTTOM (int)(4 * this->dpiMultiplier) +#define MARGIN_LEFT (int)(8 * this->scale) +#define MARGIN_RIGHT (int)(8 * this->scale) +#define MARGIN_TOP (int)(4 * this->scale) +#define MARGIN_BOTTOM (int)(4 * this->scale) using namespace chatterino::messages; @@ -32,11 +32,11 @@ int MessageRef::getHeight() const } // return true if redraw is required -bool MessageRef::layout(int width, float dpiMultiplyer) +bool MessageRef::layout(int width, float scale) { auto &emoteManager = EmoteManager::getInstance(); - bool layoutRequired = false; + bool rebuildRequired = false, layoutRequired = false; // check if width changed bool widthChanged = width != this->currentLayoutWidth; @@ -60,11 +60,11 @@ bool MessageRef::layout(int width, float dpiMultiplyer) this->currentWordTypes = SettingsManager::getInstance().getWordTypeMask(); // check if dpi changed - bool dpiChanged = this->dpiMultiplier != dpiMultiplyer; - layoutRequired |= dpiChanged; - this->dpiMultiplier = dpiMultiplyer; - imagesChanged |= dpiChanged; - textChanged |= dpiChanged; + bool scaleChanged = this->scale != scale; + layoutRequired |= scaleChanged; + this->scale = scale; + imagesChanged |= scaleChanged; + textChanged |= scaleChanged; // update word sizes if needed if (imagesChanged) { @@ -119,7 +119,7 @@ void MessageRef::actuallyLayout(int width) Word &word = *it; // Check if given word is supposed to be rendered by comparing it to the current setting - if ((word.getType() & flags) == Word::None) { + if ((word.getFlags() & flags) == Word::None) { continue; } @@ -135,7 +135,7 @@ void MessageRef::actuallyLayout(int width) /// } // word wrapping - if (word.isText() && word.getWidth() + MARGIN_LEFT > right) { + if (word.isText() && word.getWidth(this->scale) + MARGIN_LEFT > right) { // align and end the current line alignWordParts(lineStart, lineHeight, width, firstLineHeight); y += lineHeight; @@ -145,17 +145,17 @@ void MessageRef::actuallyLayout(int width) // go through the text, break text when it doesn't fit in the line anymore for (int i = 1; i <= word.getText().length(); i++) { - currentLineWidth += word.getCharWidth(i - 1); + currentLineWidth += word.getCharWidth(i - 1, this->scale); if (currentLineWidth + MARGIN_LEFT > right) { // add the current line QString mid = word.getText().mid(currentPartStart, i - currentPartStart - 1); this->wordParts.push_back(WordPart(word, MARGIN_LEFT, y, currentLineWidth, - word.getHeight(), lineNumber, mid, mid, - false, currentPartStart)); + word.getHeight(this->scale), lineNumber, mid, + mid, false, currentPartStart)); - y += word.getFontMetrics().height(); + y += word.getFontMetrics(this->scale).height(); currentPartStart = i - 1; @@ -165,27 +165,27 @@ void MessageRef::actuallyLayout(int width) } QString mid(word.getText().mid(currentPartStart)); - currentLineWidth = word.getFontMetrics().width(mid); + currentLineWidth = word.getFontMetrics(this->scale).width(mid); - this->wordParts.push_back(WordPart(word, MARGIN_LEFT, y - word.getHeight(), - currentLineWidth, word.getHeight(), lineNumber, mid, - mid, true, currentPartStart)); + this->wordParts.push_back(WordPart(word, MARGIN_LEFT, y - word.getHeight(this->scale), + currentLineWidth, word.getHeight(this->scale), + lineNumber, mid, mid, true, currentPartStart)); x = currentLineWidth + MARGIN_LEFT + spaceWidth; - lineHeight = word.getHeight(); + lineHeight = word.getHeight(this->scale); lineStart = this->wordParts.size() - 1; first = false; } // fits in the current line - else if (first || x + word.getWidth() + xOffset <= right) { - this->wordParts.push_back( - WordPart(word, x, y - word.getHeight(), lineNumber, word.getCopyText())); + else if (first || x + word.getWidth(this->scale) + xOffset <= right) { + this->wordParts.push_back(WordPart(word, x, y - word.getHeight(this->scale), scale, + lineNumber, word.getCopyText())); - x += word.getWidth() + xOffset; + x += word.getWidth(this->scale) + xOffset; x += spaceWidth; - lineHeight = std::max(word.getHeight(), lineHeight); + lineHeight = std::max(word.getHeight(this->scale), lineHeight); first = false; } @@ -198,14 +198,14 @@ void MessageRef::actuallyLayout(int width) lineNumber++; - this->wordParts.push_back( - WordPart(word, MARGIN_LEFT, y - word.getHeight(), lineNumber, word.getCopyText())); + this->wordParts.push_back(WordPart(word, MARGIN_LEFT, y - word.getHeight(this->scale), + this->scale, lineNumber, word.getCopyText())); lineStart = this->wordParts.size() - 1; - lineHeight = word.getHeight(); + lineHeight = word.getHeight(this->scale); - x = word.getWidth() + MARGIN_LEFT; + x = word.getWidth(this->scale) + MARGIN_LEFT; x += spaceWidth; } } @@ -213,7 +213,7 @@ void MessageRef::actuallyLayout(int width) // align and end the current line alignWordParts(lineStart, lineHeight, width, firstLineHeight); - this->collapsedHeight = firstLineHeight == -1 ? (int)(24 * dpiMultiplier) + this->collapsedHeight = firstLineHeight == -1 ? (int)(24 * this->scale) : firstLineHeight + MARGIN_TOP + MARGIN_BOTTOM; // update height @@ -236,37 +236,21 @@ void MessageRef::actuallyLayout(int width) void MessageRef::updateTextSizes() { for (auto &word : this->message->getWords()) { - if (!word.isText()) + if (!word.isText()) { continue; + } - QFontMetrics &metrics = word.getFontMetrics(); - word.setSize((int)(metrics.width(word.getText()) * this->dpiMultiplier), - (int)(metrics.height() * this->dpiMultiplier)); + word.updateSize(); } } void MessageRef::updateImageSizes() { - const int mediumTextLineHeight = - FontManager::getInstance().getFontMetrics(FontManager::Medium).height(); - const qreal emoteScale = SettingsManager::getInstance().emoteScale.get() * this->dpiMultiplier; - const bool scaleEmotesByLineHeight = SettingsManager::getInstance().scaleEmotesByLineHeight; - for (auto &word : this->message->getWords()) { if (!word.isImage()) continue; - auto &image = word.getImage(); - - qreal w = image.getWidth(); - qreal h = image.getHeight(); - - if (scaleEmotesByLineHeight) { - word.setSize(w * mediumTextLineHeight / h * emoteScale, - mediumTextLineHeight * emoteScale); - } else { - word.setSize(w * image.getScale() * emoteScale, h * image.getScale() * emoteScale); - } + word.updateSize(); } } @@ -406,7 +390,7 @@ int MessageRef::getSelectionIndex(QPoint position) } index++; - x = part.getX() + part.getWord().getFontMetrics().width(text, j + 1); + x = part.getX() + part.getWord().getFontMetrics(this->scale).width(text, j + 1); } } diff --git a/src/messages/messageref.hpp b/src/messages/messageref.hpp index 48c0ea7cd..ae2542b2a 100644 --- a/src/messages/messageref.hpp +++ b/src/messages/messageref.hpp @@ -22,7 +22,7 @@ public: Message *getMessage(); int getHeight() const; - bool layout(int width, float dpiMultiplier); + bool layout(int width, float scale); const std::vector &getWordParts() const; @@ -36,6 +36,7 @@ public: bool isCollapsed() const; void setCollapsed(bool value); int getCollapsedHeight() const; + int getCollapsedLineCount() const; private: // variables @@ -47,14 +48,15 @@ private: int currentLayoutWidth = -1; int fontGeneration = -1; int emoteGeneration = -1; - float dpiMultiplier = -1; + float scale = -1; - Word::Type currentWordTypes = Word::None; + Word::Flags currentWordTypes = Word::None; bool collapsed; int collapsedHeight = 32; // methods + void rebuild(); void actuallyLayout(int width); void alignWordParts(int lineStart, int lineHeight, int width, int &firstLineHeight); void updateTextSizes(); diff --git a/src/messages/word.cpp b/src/messages/word.cpp index 398b9b3f0..fb120cd70 100644 --- a/src/messages/word.cpp +++ b/src/messages/word.cpp @@ -1,11 +1,12 @@ #include "messages/word.hpp" +#include "settingsmanager.hpp" #include "util/benchmark.hpp" namespace chatterino { namespace messages { // Image word -Word::Word(LazyLoadedImage *image, Type type, const QString ©text, const QString &tooltip, +Word::Word(LazyLoadedImage *image, Flags type, const QString ©text, const QString &tooltip, const Link &link) : image(image) , _isImage(true) @@ -14,15 +15,15 @@ Word::Word(LazyLoadedImage *image, Type type, const QString ©text, const QSt , tooltip(tooltip) , link(link) { - image->getWidth(); // professional segfault test } // Text word -Word::Word(const QString &text, Type type, const MessageColor &color, const QString ©text, - const QString &tooltip, const Link &link) +Word::Word(const QString &text, Flags type, const MessageColor &color, FontManager::Type font, + const QString ©text, const QString &tooltip, const Link &link) : image(nullptr) , text(text) , color(color) + , font(font) , _isImage(false) , type(type) , copyText(copytext) @@ -41,20 +42,54 @@ const QString &Word::getText() const return this->text; } -int Word::getWidth() const +int Word::getWidth(float scale) const { - return this->width; + return this->getSize(scale).width(); } -int Word::getHeight() const +int Word::getHeight(float scale) const { - return this->height; + return this->getSize(scale).height(); } -void Word::setSize(int width, int height) +QSize Word::getSize(float scale) const { - this->width = width; - this->height = height; + auto &data = this->getDataByScale(scale); + + if (data.size.isEmpty()) { + // no size found + if (this->isText()) { + QFontMetrics &metrics = this->getFontMetrics(scale); + data.size.setWidth((int)(metrics.width(this->getText()))); + data.size.setHeight((int)(metrics.height())); + } else { + const int mediumTextLineHeight = + FontManager::getInstance().getFontMetrics(this->font, scale).height(); + const qreal emoteScale = SettingsManager::getInstance().emoteScale.get() * scale; + const bool scaleEmotesByLineHeight = + SettingsManager::getInstance().scaleEmotesByLineHeight; + + auto &image = this->getImage(); + + qreal w = image.getWidth(); + qreal h = image.getHeight(); + + if (scaleEmotesByLineHeight) { + data.size.setWidth(w * mediumTextLineHeight / h * emoteScale); + data.size.setHeight(mediumTextLineHeight * emoteScale); + } else { + data.size.setWidth(w * image.getScale() * emoteScale); + data.size.setHeight(h * image.getScale() * emoteScale); + } + } + } + + return data.size; +} + +void Word::updateSize() +{ + this->dataByScale.clear(); } bool Word::isImage() const @@ -77,17 +112,17 @@ bool Word::hasTrailingSpace() const return this->_hasTrailingSpace; } -QFont &Word::getFont() const +QFont &Word::getFont(float scale) const { - return FontManager::getInstance().getFont(this->font); + return FontManager::getInstance().getFont(this->font, scale); } -QFontMetrics &Word::getFontMetrics() const +QFontMetrics &Word::getFontMetrics(float scale) const { - return FontManager::getInstance().getFontMetrics(this->font); + return FontManager::getInstance().getFontMetrics(this->font, scale); } -Word::Type Word::getType() const +Word::Flags Word::getFlags() const { return this->type; } @@ -97,7 +132,7 @@ const QString &Word::getTooltip() const return this->tooltip; } -const MessageColor &Word::getColor() const +const MessageColor &Word::getTextColor() const { return this->color; } @@ -128,24 +163,42 @@ int Word::getCharacterLength() const return this->isImage() ? 2 : this->getText().length() + 1; } -short Word::getCharWidth(int index) const +short Word::getCharWidth(int index, float scale) const { - return this->getCharacterWidthCache().at(index); + return this->getCharacterWidthCache(scale).at(index); } -std::vector &Word::getCharacterWidthCache() const +std::vector &Word::getCharacterWidthCache(float scale) const { + auto &data = this->getDataByScale(scale); + // lock not required because there is only one gui thread // std::lock_guard lock(this->charWidthCacheMutex); - if (this->charWidthCache.size() == 0 && this->isText()) { + if (data.charWidthCache.size() == 0 && this->isText()) { for (int i = 0; i < this->getText().length(); i++) { - this->charWidthCache.push_back(this->getFontMetrics().charWidth(this->getText(), i)); + data.charWidthCache.push_back( + this->getFontMetrics(scale).charWidth(this->getText(), i)); } } // TODO: on font change - return this->charWidthCache; + return data.charWidthCache; +} + +Word::ScaleDependantData &Word::getDataByScale(float scale) const +{ + // try to find and return data for scale + for (auto it = this->dataByScale.begin(); it != this->dataByScale.end(); it++) { + if (it->scale == scale) { + return *it; + } + } + + // create new data element and return that + this->dataByScale.emplace_back(scale); + + return this->dataByScale.back(); } } // namespace messages diff --git a/src/messages/word.hpp b/src/messages/word.hpp index cfab92c0b..38c551769 100644 --- a/src/messages/word.hpp +++ b/src/messages/word.hpp @@ -4,6 +4,7 @@ #include "messages/lazyloadedimage.hpp" #include "messages/link.hpp" #include "messages/messagecolor.hpp" +//#include "wordflags.hpp" #include #include @@ -15,7 +16,7 @@ namespace messages { class Word { public: - enum Type : uint32_t { + enum Flags : uint32_t { None = 0, Misc = (1 << 0), Text = (1 << 1), @@ -92,33 +93,36 @@ public: { } - explicit Word(LazyLoadedImage *_image, Type getType, const QString ©text, + explicit Word(LazyLoadedImage *_image, Flags getFlags, const QString ©text, const QString &tooltip, const Link &getLink = Link()); - explicit Word(const QString &_text, Type getType, const MessageColor &getColor, - const QString ©text, const QString &tooltip, const Link &getLink = Link()); - - LazyLoadedImage &getImage() const; - const QString &getText() const; - int getWidth() const; - int getHeight() const; - void setSize(int _width, int _height); + explicit Word(const QString &_text, Flags getFlags, const MessageColor &textColor, + FontManager::Type font, const QString ©text, const QString &tooltip, + const Link &getLink = Link()); bool isImage() const; bool isText() const; + + LazyLoadedImage &getImage() const; + const QString &getText() const; const QString &getCopyText() const; bool hasTrailingSpace() const; - QFont &getFont() const; - QFontMetrics &getFontMetrics() const; - Type getType() const; + Flags getFlags() const; const QString &getTooltip() const; - const MessageColor &getColor() const; + const MessageColor &getTextColor() const; const Link &getLink() const; int getXOffset() const; int getYOffset() const; void setOffset(int _xOffset, int _yOffset); int getCharacterLength() const; - short getCharWidth(int index) const; + void updateSize(); + + QFont &getFont(float scale) const; + QFontMetrics &getFontMetrics(float scale) const; + int getWidth(float scale) const; + int getHeight(float scale) const; + QSize getSize(float scale) const; + short getCharWidth(int index, float scale) const; private: LazyLoadedImage *image; @@ -126,12 +130,10 @@ private: MessageColor color; bool _isImage; - Type type; + Flags type; QString copyText; QString tooltip; - int width = 16; - int height = 16; int xOffset = 0; int yOffset = 0; @@ -139,8 +141,22 @@ private: FontManager::Type font = FontManager::Medium; Link link; - std::vector &getCharacterWidthCache() const; - mutable std::vector charWidthCache; + struct ScaleDependantData { + float scale; + QSize size; + mutable std::vector charWidthCache; + + ScaleDependantData(float _scale) + : scale(_scale) + , size() + { + } + }; + + mutable std::list dataByScale; + + inline ScaleDependantData &getDataByScale(float scale) const; + std::vector &getCharacterWidthCache(float scale) const; }; } // namespace messages diff --git a/src/messages/wordflags.hpp b/src/messages/wordflags.hpp new file mode 100644 index 000000000..50e96676b --- /dev/null +++ b/src/messages/wordflags.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/src/messages/wordpart.cpp b/src/messages/wordpart.cpp index e4182ea05..64f3d61f3 100644 --- a/src/messages/wordpart.cpp +++ b/src/messages/wordpart.cpp @@ -4,15 +4,15 @@ namespace chatterino { namespace messages { -WordPart::WordPart(Word &_word, int _x, int _y, int _lineNumber, const QString &_copyText, - bool _allowTrailingSpace) +WordPart::WordPart(Word &_word, int _x, int _y, float scale, int _lineNumber, + const QString &_copyText, bool _allowTrailingSpace) : word(_word) , copyText(_copyText) , text(_word.isText() ? _word.getText() : QString()) , x(_x) , y(_y) - , width(_word.getWidth()) - , height(_word.getHeight()) + , width(_word.getWidth(scale)) + , height(_word.getHeight(scale)) , lineNumber(_lineNumber) , _trailingSpace(!_word.getCopyText().isEmpty() && _word.hasTrailingSpace() & _allowTrailingSpace) @@ -115,9 +115,9 @@ int WordPart::getCharacterLength() const return this->getWord().isImage() ? 2 : this->getText().length() + 1; } -short WordPart::getCharWidth(int index) const +short WordPart::getCharWidth(int index, float scale) const { - return this->getWord().getCharWidth(index + this->wordCharOffset); + return this->getWord().getCharWidth(index + this->wordCharOffset, scale); } } // namespace messages } // namespace chatterino diff --git a/src/messages/wordpart.hpp b/src/messages/wordpart.hpp index 110eb623e..6a54fd0c2 100644 --- a/src/messages/wordpart.hpp +++ b/src/messages/wordpart.hpp @@ -11,8 +11,8 @@ class Word; class WordPart { public: - WordPart(Word &getWord, int getX, int getY, int _lineNumber, const QString &getCopyText, - bool allowTrailingSpace = true); + WordPart(Word &getWord, int getX, int getY, float scale, int _lineNumber, + const QString &getCopyText, bool allowTrailingSpace = true); WordPart(Word &getWord, int getX, int getY, int getWidth, int getHeight, int _lineNumber, const QString &getCopyText, const QString &customText, bool allowTrailingSpace = true, @@ -33,7 +33,7 @@ public: const QString &getText() const; int getLineNumber() const; int getCharacterLength() const; - short getCharWidth(int index) const; + short getCharWidth(int index, float scale) const; private: Word &word; diff --git a/src/precompiled_headers.hpp b/src/precompiled_headers.hpp new file mode 100644 index 000000000..21b20393d --- /dev/null +++ b/src/precompiled_headers.hpp @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/src/settingsmanager.cpp b/src/settingsmanager.cpp index a1cdb4bc6..cfada6bed 100644 --- a/src/settingsmanager.cpp +++ b/src/settingsmanager.cpp @@ -75,7 +75,7 @@ void SettingsManager::load() } } -Word::Type SettingsManager::getWordTypeMask() +Word::Flags SettingsManager::getWordTypeMask() { return this->wordTypeMask; } @@ -120,7 +120,7 @@ void SettingsManager::updateWordTypeMask() newMaskUint |= Word::AlwaysShow; - Word::Type newMask = static_cast(newMaskUint); + Word::Flags newMask = static_cast(newMaskUint); if (newMask != this->wordTypeMask) { this->wordTypeMask = newMask; diff --git a/src/settingsmanager.hpp b/src/settingsmanager.hpp index 79a28e6d0..addca5551 100644 --- a/src/settingsmanager.hpp +++ b/src/settingsmanager.hpp @@ -21,7 +21,7 @@ public: void load(); void save(); - messages::Word::Type getWordTypeMask(); + messages::Word::Flags getWordTypeMask(); bool isIgnoredEmote(const QString &emote); QSettings &getQSettings(); SettingsSnapshot createSnapshot(); @@ -95,7 +95,7 @@ private: QSettings settings; std::vector> settingsItems; - messages::Word::Type wordTypeMask = messages::Word::Default; + messages::Word::Flags wordTypeMask = messages::Word::Default; pajlada::Settings::SettingListener wordMaskListener; }; diff --git a/src/twitch/twitchmessagebuilder.cpp b/src/twitch/twitchmessagebuilder.cpp index 85bc01658..12b6143ce 100644 --- a/src/twitch/twitchmessagebuilder.cpp +++ b/src/twitch/twitchmessagebuilder.cpp @@ -120,7 +120,7 @@ SharedMessage TwitchMessageBuilder::parse() currentTwitchEmote->second.image->getName() + QString("\nTwitch Emote"))); this->appendWord( Word(currentTwitchEmote->second.image->getName(), Word::TwitchEmoteText, textColor, - currentTwitchEmote->second.image->getName(), + FontManager::Medium, currentTwitchEmote->second.image->getName(), currentTwitchEmote->second.image->getName() + QString("\nTwitch Emote"))); i += split.length() + 1; @@ -193,7 +193,7 @@ SharedMessage TwitchMessageBuilder::parse() this->appendWord(Word( QString("x" + string.mid(5)), Word::BitsAmount, MessageColor(bitsColor), - QString(string.mid(5)), QString("Twitch Cheer"), + FontManager::Medium, QString(string.mid(5)), QString("Twitch Cheer"), Link(Link::Url, QString("https://blog.twitch.tv/" "introducing-cheering-celebrate-together-da62af41fac6")))); @@ -223,11 +223,12 @@ SharedMessage TwitchMessageBuilder::parse() textColor = MessageColor(MessageColor::Link); } - this->appendWord(Word(string, Word::Text, textColor, string, QString(), link)); + this->appendWord(Word(string, Word::Text, textColor, FontManager::Medium, string, + QString(), link)); } else { // is emoji this->appendWord(Word(emoteData.image, Word::EmojiImage, emoteData.image->getName(), emoteData.image->getTooltip())); - Word(emoteData.image->getName(), Word::EmojiText, textColor, + Word(emoteData.image->getName(), Word::EmojiText, textColor, FontManager::Medium, emoteData.image->getName(), emoteData.image->getTooltip()); } } @@ -272,7 +273,7 @@ void TwitchMessageBuilder::parseChannelName() { QString channelName("#" + this->channel->name); this->appendWord(Word(channelName, Word::Misc, MessageColor(MessageColor::System), - QString(channelName), QString(), + FontManager::Medium, QString(channelName), QString(), Link(Link::Url, this->channel->name + "\n" + this->messageID))); } @@ -360,7 +361,8 @@ void TwitchMessageBuilder::appendUsername() } this->appendWord(Word(usernameString, Word::Username, MessageColor(this->usernameColor), - usernameString, QString(), Link(Link::UserInfo, this->userName))); + FontManager::Medium, usernameString, QString(), + Link(Link::UserInfo, this->userName))); } void TwitchMessageBuilder::parseHighlights() @@ -636,7 +638,7 @@ void TwitchMessageBuilder::parseTwitchBadges() auto badgeSetIt = channelResources.badgeSets.find("subscriber"); if (badgeSetIt == channelResources.badgeSets.end()) { // Fall back to default badge - appendWord(Word(this->resources.badgeSubscriber, Word::Type::BadgeSubscription, + appendWord(Word(this->resources.badgeSubscriber, Word::Flags::BadgeSubscription, QString(), QString("Twitch Subscriber"))); continue; } @@ -649,14 +651,14 @@ void TwitchMessageBuilder::parseTwitchBadges() if (badgeVersionIt == badgeSet.versions.end()) { // Fall back to default badge - appendWord(Word(this->resources.badgeSubscriber, Word::Type::BadgeSubscription, + appendWord(Word(this->resources.badgeSubscriber, Word::Flags::BadgeSubscription, QString(), QString("Twitch Subscriber"))); continue; } auto &badgeVersion = badgeVersionIt->second; - appendWord(Word(badgeVersion.badgeImage1x, Word::Type::BadgeSubscription, QString(), + appendWord(Word(badgeVersion.badgeImage1x, Word::Flags::BadgeSubscription, QString(), QString("Twitch " + QString::fromStdString(badgeVersion.title)))); } else { if (!this->resources.dynamicBadgesLoaded) { @@ -671,7 +673,7 @@ void TwitchMessageBuilder::parseTwitchBadges() continue; } - Word::Type badgeType = Word::Type::BadgeVanity; + Word::Flags badgeType = Word::Flags::BadgeVanity; std::string badgeSetKey = parts[0].toStdString(); std::string versionKey = parts[1].toStdString(); diff --git a/src/widgets/emotepopup.cpp b/src/widgets/emotepopup.cpp index 5257d8cf8..121d2d4f7 100644 --- a/src/widgets/emotepopup.cpp +++ b/src/widgets/emotepopup.cpp @@ -45,8 +45,8 @@ void EmotePopup::loadChannel(std::shared_ptr _channel) // TITLE messages::MessageBuilder builder1; - builder1.appendWord( - Word(title, Word::Type::Text, MessageColor(MessageColor::Text), QString(), QString())); + builder1.appendWord(Word(title, Word::Flags::Text, MessageColor(MessageColor::Text), + FontManager::Medium, QString(), QString())); builder1.getMessage()->centered = true; emoteChannel->addMessage(builder1.getMessage()); @@ -56,7 +56,7 @@ void EmotePopup::loadChannel(std::shared_ptr _channel) builder2.getMessage()->centered = true; map.each([&](const QString &key, const EmoteData &value) { - builder2.appendWord(Word(value.image, Word::Type::AlwaysShow, key, emoteDesc, + builder2.appendWord(Word(value.image, Word::Flags::AlwaysShow, key, emoteDesc, Link(Link::Type::InsertText, key))); }); @@ -85,8 +85,8 @@ void EmotePopup::loadEmojis() // title messages::MessageBuilder builder1; - builder1.appendWord( - Word("emojis", Word::Type::Text, MessageColor(MessageColor::Text), QString(), QString())); + builder1.appendWord(Word("emojis", Word::Flags::Text, MessageColor(MessageColor::Text), + FontManager::Medium, QString(), QString())); builder1.getMessage()->centered = true; emojiChannel->addMessage(builder1.getMessage()); @@ -95,7 +95,7 @@ void EmotePopup::loadEmojis() messages::MessageBuilder builder; builder.getMessage()->centered = true; emojis.each([this, &builder](const QString &key, const EmoteData &value) { - builder.appendWord(Word(value.image, Word::Type::AlwaysShow, key, "emoji", + builder.appendWord(Word(value.image, Word::Flags::AlwaysShow, key, "emoji", Link(Link::Type::InsertText, key))); }); emojiChannel->addMessage(builder.getMessage()); diff --git a/src/widgets/helper/channelview.cpp b/src/widgets/helper/channelview.cpp index aafbefad7..0e0e27880 100644 --- a/src/widgets/helper/channelview.cpp +++ b/src/widgets/helper/channelview.cpp @@ -554,12 +554,14 @@ void ChannelView::updateMessageBuffer(messages::MessageRef *messageRef, QPixmap } // text else { - QColor color = wordPart.getWord().getColor().getColor(this->colorScheme); + QColor color = wordPart.getWord().getTextColor().getColor(this->colorScheme); this->colorScheme.normalizeColor(color); painter.setPen(color); - painter.setFont(wordPart.getWord().getFont()); + painter.setFont(wordPart.getWord().getFont(this->getDpiMultiplier())); + + qDebug() << wordPart.getWord().getFont(this->getDpiMultiplier()).pointSize(); painter.drawText(QRectF(wordPart.getX(), wordPart.getY(), 10000, 10000), wordPart.getText(), QTextOption(Qt::AlignLeft | Qt::AlignTop)); @@ -626,7 +628,7 @@ void ChannelView::drawMessageSelection(QPainter &painter, messages::MessageRef * int offset = this->selection.min.charIndex - charIndex; for (int j = 0; j < offset; j++) { - rect.setLeft(rect.left() + part.getCharWidth(j)); + rect.setLeft(rect.left() + part.getCharWidth(j, this->getDpiMultiplier())); } if (isSingleWord) { @@ -635,7 +637,7 @@ void ChannelView::drawMessageSelection(QPainter &painter, messages::MessageRef * rect.setRight(part.getX()); for (int j = 0; j < offset + length; j++) { - rect.setRight(rect.right() + part.getCharWidth(j)); + rect.setRight(rect.right() + part.getCharWidth(j, this->getDpiMultiplier())); } painter.fillRect(rect, selectionColor); @@ -692,7 +694,7 @@ void ChannelView::drawMessageSelection(QPainter &painter, messages::MessageRef * rect.setRight(part.getX()); for (int j = 0; j < offset + length; j++) { - rect.setRight(rect.right() + part.getCharWidth(j)); + rect.setRight(rect.right() + part.getCharWidth(j, this->getDpiMultiplier())); } } else { if (this->selection.max.charIndex == charIndex) { diff --git a/src/widgets/helper/splitinput.cpp b/src/widgets/helper/splitinput.cpp index 2b983d413..ed43f9857 100644 --- a/src/widgets/helper/splitinput.cpp +++ b/src/widgets/helper/splitinput.cpp @@ -29,9 +29,11 @@ SplitInput::SplitInput(Split *_chatWidget) auto &fontManager = FontManager::getInstance(); - this->textInput.setFont(fontManager.getFont(FontManager::Type::Medium)); + this->textInput.setFont( + fontManager.getFont(FontManager::Type::Medium, this->getDpiMultiplier())); this->managedConnections.emplace_back(fontManager.fontChanged.connect([this, &fontManager]() { - this->textInput.setFont(fontManager.getFont(FontManager::Type::Medium)); + this->textInput.setFont( + fontManager.getFont(FontManager::Type::Medium, this->getDpiMultiplier())); })); this->editContainer.addWidget(&this->textInput); diff --git a/src/widgets/settingsdialog.cpp b/src/widgets/settingsdialog.cpp index 7c2922a7b..421c02651 100644 --- a/src/widgets/settingsdialog.cpp +++ b/src/widgets/settingsdialog.cpp @@ -180,7 +180,7 @@ QVBoxLayout *SettingsDialog::createAppearanceTab() fontButton->connect(fontButton, &QPushButton::clicked, []() { auto &fontManager = FontManager::getInstance(); - QFontDialog dialog(fontManager.getFont(FontManager::Medium)); + QFontDialog dialog(fontManager.getFont(FontManager::Medium, 1.)); dialog.connect(&dialog, &QFontDialog::fontSelected, [](const QFont &font) { auto &fontManager = FontManager::getInstance();