mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 14:17:12 +02:00
Support reaction button with gradient bubbles.
This commit is contained in:
parent
68d45a2c08
commit
51e96bf074
2 changed files with 83 additions and 6 deletions
|
@ -51,6 +51,26 @@ constexpr auto kCacheColumsCount = 3;
|
|||
return CountMaxSizeWithMargins(st::reactionCornerShadow);
|
||||
}
|
||||
|
||||
void CopyImagePart(QImage &to, const QImage &from, QRect source) {
|
||||
Expects(to.size() == source.size());
|
||||
Expects(QRect(QPoint(), from.size()).contains(source));
|
||||
Expects(to.format() == from.format());
|
||||
Expects(to.bytesPerLine() == to.width() * 4);
|
||||
|
||||
const auto perPixel = 4;
|
||||
const auto fromPerLine = from.bytesPerLine();
|
||||
const auto toPerLine = to.bytesPerLine();
|
||||
auto toBytes = reinterpret_cast<char*>(to.bits());
|
||||
auto fromBytes = reinterpret_cast<const char*>(from.bits())
|
||||
+ (source.y() * fromPerLine)
|
||||
+ (source.x() * perPixel);
|
||||
for (auto y = 0, height = source.height(); y != height; ++y) {
|
||||
memcpy(toBytes, fromBytes, toPerLine);
|
||||
toBytes += toPerLine;
|
||||
fromBytes += fromPerLine;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
InlineList::InlineList(Data &&data)
|
||||
|
@ -399,6 +419,10 @@ Manager::Manager(QWidget *selectorParent, Fn<void(QRect)> buttonUpdate)
|
|||
QImage::Format_ARGB32_Premultiplied);
|
||||
_cacheParts.setDevicePixelRatio(ratio);
|
||||
_cacheParts.fill(Qt::transparent);
|
||||
_cacheForPattern = QImage(
|
||||
_outer * ratio,
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
_cacheForPattern.setDevicePixelRatio(ratio);
|
||||
_shadowBuffer = QImage(
|
||||
_outer * ratio,
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
|
@ -556,7 +580,11 @@ void Manager::paintButton(
|
|||
position,
|
||||
_cacheParts,
|
||||
validateShadow(frameIndex, scale, shadow));
|
||||
// #TODO reactions
|
||||
|
||||
validateCacheForPattern(frameIndex, scale, geometry, context);
|
||||
p.drawImage(geometry, _cacheForPattern);
|
||||
|
||||
p.drawImage(position, _cacheParts, validateEmoji(frameIndex, scale));
|
||||
} else {
|
||||
const auto &stm = context.st->messageStyle(outbg, false);
|
||||
const auto background = stm.msgBg->c;
|
||||
|
@ -573,6 +601,24 @@ void Manager::paintButton(
|
|||
}
|
||||
}
|
||||
|
||||
void Manager::validateCacheForPattern(
|
||||
int frameIndex,
|
||||
float64 scale,
|
||||
const QRect &geometry,
|
||||
const PaintContext &context) {
|
||||
CopyImagePart(
|
||||
_cacheForPattern,
|
||||
_cacheParts,
|
||||
validateMask(frameIndex, scale));
|
||||
auto q = QPainter(&_cacheForPattern);
|
||||
q.setCompositionMode(QPainter::CompositionMode_SourceIn);
|
||||
Ui::PaintPatternBubblePart(
|
||||
q,
|
||||
context.viewport.translated(-geometry.topLeft()),
|
||||
context.bubblesPattern->pixmap,
|
||||
QRect(QPoint(), _outer));
|
||||
}
|
||||
|
||||
void Manager::applyPatternedShadow(const QColor &shadow) {
|
||||
if (_shadow == shadow) {
|
||||
return;
|
||||
|
@ -702,6 +748,30 @@ QRect Manager::validateFrame(
|
|||
return result;
|
||||
}
|
||||
|
||||
QRect Manager::validateMask(int frameIndex, float64 scale) {
|
||||
const auto result = cacheRect(frameIndex, kMaskCacheIndex);
|
||||
if (_validMask[frameIndex]) {
|
||||
return result;
|
||||
}
|
||||
|
||||
auto p = QPainter(&_cacheParts);
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
const auto position = result.topLeft() / style::DevicePixelRatio();
|
||||
const auto inner = _inner.translated(position);
|
||||
const auto radius = inner.height() / 2;
|
||||
const auto center = inner.center();
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(Qt::white);
|
||||
p.save();
|
||||
p.translate(center);
|
||||
p.scale(scale, scale);
|
||||
p.translate(-center);
|
||||
p.drawRoundedRect(inner, radius, radius);
|
||||
|
||||
_validMask[frameIndex] = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
void Manager::showSelector(Fn<QPoint(QPoint)> mapToGlobal) {
|
||||
if (!_button) {
|
||||
showSelector({}, {});
|
||||
|
|
|
@ -206,6 +206,12 @@ private:
|
|||
float64 scale,
|
||||
const QColor &background,
|
||||
const QColor &shadow);
|
||||
QRect validateMask(int frameIndex, float64 scale);
|
||||
void validateCacheForPattern(
|
||||
int frameIndex,
|
||||
float64 scale,
|
||||
const QRect &geometry,
|
||||
const PaintContext &context);
|
||||
|
||||
rpl::event_stream<Chosen> _chosen;
|
||||
std::vector<Data::Reaction> _list;
|
||||
|
@ -214,12 +220,13 @@ private:
|
|||
QRect _innerActive;
|
||||
QImage _cacheInOut;
|
||||
QImage _cacheParts;
|
||||
QImage _cacheForPattern;
|
||||
QImage _shadowBuffer;
|
||||
std::array<bool, kFramesCount> _validIn;
|
||||
std::array<bool, kFramesCount> _validOut;
|
||||
std::array<bool, kFramesCount> _validShadow;
|
||||
std::array<bool, kFramesCount> _validEmoji;
|
||||
std::array<bool, kFramesCount> _validMask;
|
||||
std::array<bool, kFramesCount> _validIn = { { false } };
|
||||
std::array<bool, kFramesCount> _validOut = { { false } };
|
||||
std::array<bool, kFramesCount> _validShadow = { { false } };
|
||||
std::array<bool, kFramesCount> _validEmoji = { { false } };
|
||||
std::array<bool, kFramesCount> _validMask = { { false } };
|
||||
QColor _backgroundIn;
|
||||
QColor _backgroundOut;
|
||||
QColor _shadow;
|
||||
|
|
Loading…
Add table
Reference in a new issue