Formalize zero-width emote implementation (#4314)
Co-authored-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com>
This commit is contained in:
@@ -15,6 +15,14 @@
|
||||
namespace {
|
||||
|
||||
const QChar RTL_EMBED(0x202B);
|
||||
|
||||
void alignRectBottomCenter(QRectF &rect, const QRectF &reference)
|
||||
{
|
||||
QPointF newCenter(reference.center().x(),
|
||||
reference.bottom() - (rect.height() / 2.0));
|
||||
rect.moveCenter(newCenter);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace chatterino {
|
||||
@@ -184,6 +192,133 @@ int ImageLayoutElement::getXFromIndex(int index)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// LAYERED IMAGE
|
||||
//
|
||||
|
||||
LayeredImageLayoutElement::LayeredImageLayoutElement(
|
||||
MessageElement &creator, std::vector<ImagePtr> images,
|
||||
std::vector<QSize> sizes, QSize largestSize)
|
||||
: MessageLayoutElement(creator, largestSize)
|
||||
, images_(std::move(images))
|
||||
, sizes_(std::move(sizes))
|
||||
{
|
||||
assert(this->images_.size() == this->sizes_.size());
|
||||
this->trailingSpace = creator.hasTrailingSpace();
|
||||
}
|
||||
|
||||
void LayeredImageLayoutElement::addCopyTextToString(QString &str, uint32_t from,
|
||||
uint32_t to) const
|
||||
{
|
||||
const auto *layeredEmoteElement =
|
||||
dynamic_cast<LayeredEmoteElement *>(&this->getCreator());
|
||||
if (layeredEmoteElement)
|
||||
{
|
||||
// cleaning is taken care in call
|
||||
str += layeredEmoteElement->getCleanCopyString();
|
||||
if (this->hasTrailingSpace())
|
||||
{
|
||||
str += " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int LayeredImageLayoutElement::getSelectionIndexCount() const
|
||||
{
|
||||
return this->trailingSpace ? 2 : 1;
|
||||
}
|
||||
|
||||
void LayeredImageLayoutElement::paint(QPainter &painter)
|
||||
{
|
||||
auto fullRect = QRectF(this->getRect());
|
||||
|
||||
for (size_t i = 0; i < this->images_.size(); ++i)
|
||||
{
|
||||
auto &img = this->images_[i];
|
||||
if (img == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto pixmap = img->pixmapOrLoad();
|
||||
if (img->animated())
|
||||
{
|
||||
// As soon as we see an animated emote layer, we can stop rendering
|
||||
// the static emotes. The paintAnimated function will render any
|
||||
// static emotes layered on top of the first seen animated emote.
|
||||
return;
|
||||
}
|
||||
|
||||
if (pixmap)
|
||||
{
|
||||
// Matching the web chat behavior, we center the emote within the overall
|
||||
// binding box. E.g. small overlay emotes like cvMask will sit in the direct
|
||||
// center of even wide emotes.
|
||||
auto &size = this->sizes_[i];
|
||||
QRectF destRect(0, 0, size.width(), size.height());
|
||||
alignRectBottomCenter(destRect, fullRect);
|
||||
|
||||
painter.drawPixmap(destRect, *pixmap, QRectF());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LayeredImageLayoutElement::paintAnimated(QPainter &painter, int yOffset)
|
||||
{
|
||||
auto fullRect = QRectF(this->getRect());
|
||||
fullRect.moveTop(fullRect.y() + yOffset);
|
||||
bool animatedFlag = false;
|
||||
|
||||
for (size_t i = 0; i < this->images_.size(); ++i)
|
||||
{
|
||||
auto &img = this->images_[i];
|
||||
if (img == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we have a static emote layered on top of an animated emote, we need
|
||||
// to render the static emote again after animating anything below it.
|
||||
if (img->animated() || animatedFlag)
|
||||
{
|
||||
if (auto pixmap = img->pixmapOrLoad())
|
||||
{
|
||||
// Matching the web chat behavior, we center the emote within the overall
|
||||
// binding box. E.g. small overlay emotes like cvMask will sit in the direct
|
||||
// center of even wide emotes.
|
||||
auto &size = this->sizes_[i];
|
||||
QRectF destRect(0, 0, size.width(), size.height());
|
||||
alignRectBottomCenter(destRect, fullRect);
|
||||
|
||||
painter.drawPixmap(destRect, *pixmap, QRectF());
|
||||
animatedFlag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int LayeredImageLayoutElement::getMouseOverIndex(const QPoint &abs) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LayeredImageLayoutElement::getXFromIndex(int index)
|
||||
{
|
||||
if (index <= 0)
|
||||
{
|
||||
return this->getRect().left();
|
||||
}
|
||||
else if (index == 1)
|
||||
{
|
||||
// fourtf: remove space width
|
||||
return this->getRect().right();
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->getRect().right();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// IMAGE WITH BACKGROUND
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user