/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once namespace Ui { class ChatTheme; class ChatStyle; enum class BubbleCornerRounding : uchar { None, Tail, Small, Large, }; struct BubbleRounding { BubbleCornerRounding topLeft : 2 = BubbleCornerRounding(); BubbleCornerRounding topRight : 2 = BubbleCornerRounding(); BubbleCornerRounding bottomLeft : 2 = BubbleCornerRounding(); BubbleCornerRounding bottomRight : 2 = BubbleCornerRounding(); struct ConstProxy { constexpr ConstProxy( not_null that, int index) noexcept : that(that) , index(index) { Expects(index >= 0 && index < 4); } constexpr operator BubbleCornerRounding() const noexcept { switch (index) { case 0: return that->topLeft; case 1: return that->topRight; case 2: return that->bottomLeft; case 3: return that->bottomRight; } Unexpected("Index value in BubbleRounding::ConstProxy."); } not_null that; int index = 0; }; struct Proxy : ConstProxy { constexpr Proxy(not_null that, int index) noexcept : ConstProxy(that, index) { } using ConstProxy::operator BubbleCornerRounding; constexpr Proxy &operator=(BubbleCornerRounding value) noexcept { const auto nonconst = const_cast(that.get()); switch (index) { case 0: nonconst->topLeft = value; break; case 1: nonconst->topRight = value; break; case 2: nonconst->bottomLeft = value; break; case 3: nonconst->bottomRight = value; break; } return *this; } }; [[nodiscard]] constexpr ConstProxy operator[](int index) const { return { this, index }; } [[nodiscard]] constexpr Proxy operator[](int index) { return { this, index }; } [[nodiscard]] uchar key() const { static_assert(sizeof(*this) == sizeof(uchar)); return uchar(*reinterpret_cast(this)); } inline friend constexpr auto operator<=>( BubbleRounding, BubbleRounding) = default; }; struct BubbleSelectionInterval { int top = 0; int height = 0; }; struct BubblePattern { QPixmap pixmap; std::array cornersSmall; std::array cornersLarge; QImage tailLeft; QImage tailRight; mutable QImage cornerTopSmallCache; mutable QImage cornerTopLargeCache; mutable QImage cornerBottomSmallCache; mutable QImage cornerBottomLargeCache; mutable QImage tailCache; }; [[nodiscard]] std::unique_ptr PrepareBubblePattern( not_null st); void FinishBubblePatternOnMain(not_null pattern); struct SimpleBubble { not_null st; QRect geometry; const BubblePattern *pattern = nullptr; QRect patternViewport; int outerWidth = 0; bool selected = false; bool shadowed = true; bool outbg = false; BubbleRounding rounding; }; struct ComplexBubble { SimpleBubble simple; const std::vector &selection; }; void PaintBubble(QPainter &p, const SimpleBubble &args); void PaintBubble(QPainter &p, const ComplexBubble &args); void PaintPatternBubblePart( QPainter &p, const QRect &viewport, const QPixmap &pixmap, const QRect &target); void PaintPatternBubblePart( QPainter &p, const QRect &viewport, const QPixmap &pixmap, const QRect &target, const QImage &mask, QImage &cache); void PaintPatternBubblePart( QPainter &p, const QRect &viewport, const QPixmap &pixmap, const QRect &target, Fn paintContent, QImage &cache); } // namespace Ui