2
0
mirror of https://github.com/kotatogram/kotatogram-desktop synced 2025-08-31 06:35:14 +00:00

Use objects instead of pointers for corners.

Also don't change mask corner images when color theme is changed.
This prevents race condition in mask corner images access, because
the GIF frame readers access mask corner images from other threads.
This commit is contained in:
John Preston
2017-07-13 17:42:46 +03:00
parent 9fd8b040b7
commit 2f816942b8
11 changed files with 65 additions and 74 deletions

View File

@@ -111,15 +111,12 @@ namespace {
style::font monofont;
struct CornersPixmaps {
CornersPixmaps() {
memset(p, 0, sizeof(p));
}
QPixmap *p[4];
QPixmap p[4];
};
CornersPixmaps corners[RoundCornersCount];
QVector<CornersPixmaps> corners;
using CornersMap = QMap<uint32, CornersPixmaps>;
CornersMap cornersMap;
QImage *cornersMaskLarge[4] = { nullptr }, *cornersMaskSmall[4] = { nullptr };
QImage cornersMaskLarge[4], cornersMaskSmall[4];
using EmojiImagesMap = QMap<int, QPixmap>;
EmojiImagesMap MainEmojiMap;
@@ -2174,6 +2171,7 @@ namespace {
}
void prepareCorners(RoundCorners index, int32 radius, const QBrush &brush, const style::color *shadow = nullptr, QImage *cors = nullptr) {
Expects(::corners.size() > index);
int32 r = radius * cIntRetinaFactor(), s = st::msgShadow * cIntRetinaFactor();
QImage rect(r * 3, r * 3 + (shadow ? s : 0), QImage::Format_ARGB32_Premultiplied), localCors[4];
{
@@ -2198,8 +2196,8 @@ namespace {
cors[3] = rect.copy(r * 2, r * 2, r, r + (shadow ? s : 0));
if (index != SmallMaskCorners && index != LargeMaskCorners) {
for (int i = 0; i < 4; ++i) {
::corners[index].p[i] = new QPixmap(pixmapFromImageInPlace(std::move(cors[i])));
::corners[index].p[i]->setDevicePixelRatio(cRetinaFactor());
::corners[index].p[i] = pixmapFromImageInPlace(std::move(cors[i]));
::corners[index].p[i].setDevicePixelRatio(cRetinaFactor());
}
}
}
@@ -2221,18 +2219,21 @@ namespace {
return MsgRadius;
}
void createCorners() {
void createMaskCorners() {
QImage mask[4];
prepareCorners(LargeMaskCorners, msgRadius(), QColor(255, 255, 255), nullptr, mask);
for (int i = 0; i < 4; ++i) {
::cornersMaskLarge[i] = new QImage(mask[i].convertToFormat(QImage::Format_ARGB32_Premultiplied));
::cornersMaskLarge[i]->setDevicePixelRatio(cRetinaFactor());
}
prepareCorners(SmallMaskCorners, st::buttonRadius, QColor(255, 255, 255), nullptr, mask);
for (int i = 0; i < 4; ++i) {
::cornersMaskSmall[i] = new QImage(mask[i].convertToFormat(QImage::Format_ARGB32_Premultiplied));
::cornersMaskSmall[i]->setDevicePixelRatio(cRetinaFactor());
::cornersMaskSmall[i] = mask[i].convertToFormat(QImage::Format_ARGB32_Premultiplied);
::cornersMaskSmall[i].setDevicePixelRatio(cRetinaFactor());
}
prepareCorners(LargeMaskCorners, msgRadius(), QColor(255, 255, 255), nullptr, mask);
for (int i = 0; i < 4; ++i) {
::cornersMaskLarge[i] = mask[i].convertToFormat(QImage::Format_ARGB32_Premultiplied);
::cornersMaskLarge[i].setDevicePixelRatio(cRetinaFactor());
}
}
void createPaletteCorners() {
prepareCorners(MenuCorners, st::buttonRadius, st::menuBg);
prepareCorners(BoxCorners, st::boxRadius, st::boxBg);
prepareCorners(BotKbOverCorners, st::dateRadius, st::msgBotKbOverBgAdd);
@@ -2262,19 +2263,14 @@ namespace {
prepareCorners(MessageOutSelectedCorners, msgRadius(), st::msgOutBgSelected, &st::msgOutShadowSelected);
}
void createCorners() {
::corners.resize(RoundCornersCount);
createMaskCorners();
createPaletteCorners();
}
void clearCorners() {
for (int j = 0; j < 4; ++j) {
for (int i = 0; i < RoundCornersCount; ++i) {
delete ::corners[i].p[j]; ::corners[i].p[j] = nullptr;
}
delete ::cornersMaskSmall[j]; ::cornersMaskSmall[j] = nullptr;
delete ::cornersMaskLarge[j]; ::cornersMaskLarge[j] = nullptr;
}
for (auto i = ::cornersMap.cbegin(), e = ::cornersMap.cend(); i != e; ++i) {
for (int j = 0; j < 4; ++j) {
delete i->p[j];
}
}
::corners.clear();
::cornersMap.clear();
}
@@ -2303,18 +2299,13 @@ namespace {
using Update = Window::Theme::BackgroundUpdate;
static auto subscription = Window::Theme::Background()->add_subscription([](const Update &update) {
if (update.paletteChanged()) {
clearCorners();
createCorners();
createPaletteCorners();
if (App::main()) {
App::main()->updateScrollColors();
}
HistoryLayout::serviceColorsUpdated();
} else if (update.type == Update::Type::New) {
for (int i = 0; i < 4; ++i) {
delete ::corners[StickerCorners].p[i]; ::corners[StickerCorners].p[i] = nullptr;
delete ::corners[StickerSelectedCorners].p[i]; ::corners[StickerSelectedCorners].p[i] = nullptr;
}
prepareCorners(StickerCorners, st::dateRadius, st::msgServiceBg);
prepareCorners(StickerSelectedCorners, st::dateRadius, st::msgServiceBgSelected);
@@ -2778,7 +2769,7 @@ namespace {
roundRect(p, rect, st::msgInBg, MessageInCorners, nullptr, parts);
}
QImage **cornersMask(ImageRoundRadius radius) {
QImage *cornersMask(ImageRoundRadius radius) {
switch (radius) {
case ImageRoundRadius::Large: return ::cornersMaskLarge;
case ImageRoundRadius::Small:
@@ -2788,8 +2779,8 @@ namespace {
}
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, const CornersPixmaps &corner, const style::color *shadow, RectParts parts) {
auto cornerWidth = corner.p[0]->width() / cIntRetinaFactor();
auto cornerHeight = corner.p[0]->height() / cIntRetinaFactor();
auto cornerWidth = corner.p[0].width() / cIntRetinaFactor();
auto cornerHeight = corner.p[0].height() / cIntRetinaFactor();
if (w < 2 * cornerWidth || h < 2 * cornerHeight) return;
if (w > 2 * cornerWidth) {
if (parts & RectPart::Top) {
@@ -2818,16 +2809,16 @@ namespace {
}
}
if (parts & RectPart::TopLeft) {
p.drawPixmap(x, y, *corner.p[0]);
p.drawPixmap(x, y, corner.p[0]);
}
if (parts & RectPart::TopRight) {
p.drawPixmap(x + w - cornerWidth, y, *corner.p[1]);
p.drawPixmap(x + w - cornerWidth, y, corner.p[1]);
}
if (parts & RectPart::BottomLeft) {
p.drawPixmap(x, y + h - cornerHeight, *corner.p[2]);
p.drawPixmap(x, y + h - cornerHeight, corner.p[2]);
}
if (parts & RectPart::BottomRight) {
p.drawPixmap(x + w - cornerWidth, y + h - cornerHeight, *corner.p[3]);
p.drawPixmap(x + w - cornerWidth, y + h - cornerHeight, corner.p[3]);
}
}
@@ -2837,18 +2828,18 @@ namespace {
void roundShadow(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, RoundCorners index, RectParts parts) {
auto &corner = ::corners[index];
auto cornerWidth = corner.p[0]->width() / cIntRetinaFactor();
auto cornerHeight = corner.p[0]->height() / cIntRetinaFactor();
auto cornerWidth = corner.p[0].width() / cIntRetinaFactor();
auto cornerHeight = corner.p[0].height() / cIntRetinaFactor();
if (parts & RectPart::Bottom) {
p.fillRect(x + cornerWidth, y + h, w - 2 * cornerWidth, st::msgShadow, shadow);
}
if (parts & RectPart::BottomLeft) {
p.fillRect(x, y + h - cornerHeight, cornerWidth, st::msgShadow, shadow);
p.drawPixmap(x, y + h - cornerHeight + st::msgShadow, *corner.p[2]);
p.drawPixmap(x, y + h - cornerHeight + st::msgShadow, corner.p[2]);
}
if (parts & RectPart::BottomRight) {
p.fillRect(x + w - cornerWidth, y + h - cornerHeight, cornerWidth, st::msgShadow, shadow);
p.drawPixmap(x + w - cornerWidth, y + h - cornerHeight + st::msgShadow, *corner.p[3]);
p.drawPixmap(x + w - cornerWidth, y + h - cornerHeight + st::msgShadow, corner.p[3]);
}
}
@@ -2865,8 +2856,8 @@ namespace {
CornersPixmaps pixmaps;
for (int j = 0; j < 4; ++j) {
pixmaps.p[j] = new QPixmap(pixmapFromImageInPlace(std::move(images[j])));
pixmaps.p[j]->setDevicePixelRatio(cRetinaFactor());
pixmaps.p[j] = pixmapFromImageInPlace(std::move(images[j]));
pixmaps.p[j].setDevicePixelRatio(cRetinaFactor());
}
i = cornersMap.insert(colorKey, pixmaps);
}