mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 02:01:40 -05:00
Use QImage instead of QPixmap for theme preview.
Working with QPixmap from non-main thread is not defined.
This commit is contained in:
parent
e89350d4b7
commit
0ef3e19bc2
6 changed files with 113 additions and 77 deletions
|
@ -1710,14 +1710,16 @@ void MediaView::initThemePreview() {
|
|||
|
||||
Window::Theme::CurrentData current;
|
||||
current.backgroundId = Window::Theme::Background()->id();
|
||||
current.backgroundImage = Window::Theme::Background()->pixmap();
|
||||
current.backgroundImage = Window::Theme::Background()->pixmap().toImage();
|
||||
current.backgroundTiled = Window::Theme::Background()->tile();
|
||||
|
||||
const auto path = _doc->location().name();
|
||||
const auto id = _themePreviewId = rand_value<uint64>();
|
||||
const auto weak = make_weak(this);
|
||||
crl::async([=] {
|
||||
auto preview = Window::Theme::GeneratePreview(path, current);
|
||||
crl::async([=, data = std::move(current)]() mutable {
|
||||
auto preview = Window::Theme::GeneratePreview(
|
||||
path,
|
||||
std::move(data));
|
||||
crl::on_main(weak, [=, result = std::move(preview)]() mutable {
|
||||
if (id != _themePreviewId) {
|
||||
return;
|
||||
|
@ -2261,12 +2263,19 @@ void MediaView::paintThemePreview(Painter &p, QRect clip) {
|
|||
auto fill = _themePreviewRect.intersected(clip);
|
||||
if (!fill.isEmpty()) {
|
||||
if (_themePreview) {
|
||||
p.drawPixmapLeft(_themePreviewRect.x(), _themePreviewRect.y(), width(), _themePreview->preview);
|
||||
p.drawImage(
|
||||
myrtlrect(_themePreviewRect).topLeft(),
|
||||
_themePreview->preview);
|
||||
} else {
|
||||
p.fillRect(fill, st::themePreviewBg);
|
||||
p.setFont(st::themePreviewLoadingFont);
|
||||
p.setPen(st::themePreviewLoadingFg);
|
||||
p.drawText(_themePreviewRect, lang(_themePreviewId ? lng_theme_preview_generating : lng_theme_preview_invalid), QTextOption(style::al_center));
|
||||
p.drawText(
|
||||
_themePreviewRect,
|
||||
lang(_themePreviewId
|
||||
? lng_theme_preview_generating
|
||||
: lng_theme_preview_invalid),
|
||||
QTextOption(style::al_center));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,13 @@ const QPixmap &circleMask(int width, int height) {
|
|||
|
||||
} // namespace
|
||||
|
||||
QPixmap PixmapFast(QImage &&image) {
|
||||
Expects(image.format() == QImage::Format_ARGB32_Premultiplied
|
||||
|| image.format() == QImage::Format_RGB32);
|
||||
|
||||
return QPixmap::fromImage(std::move(image), Qt::NoFormatConversion);
|
||||
}
|
||||
|
||||
QImage prepareBlur(QImage img) {
|
||||
auto ratio = img.devicePixelRatio();
|
||||
auto fmt = img.format();
|
||||
|
|
|
@ -22,6 +22,62 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
|
||||
#include "base/flags.h"
|
||||
|
||||
enum class ImageRoundRadius {
|
||||
None,
|
||||
Large,
|
||||
Small,
|
||||
Ellipse,
|
||||
};
|
||||
|
||||
namespace Images {
|
||||
|
||||
QPixmap PixmapFast(QImage &&image);
|
||||
|
||||
QImage prepareBlur(QImage image);
|
||||
void prepareRound(
|
||||
QImage &image,
|
||||
ImageRoundRadius radius,
|
||||
RectParts corners = RectPart::AllCorners,
|
||||
QRect target = QRect());
|
||||
void prepareRound(
|
||||
QImage &image,
|
||||
QImage *cornerMasks,
|
||||
RectParts corners = RectPart::AllCorners,
|
||||
QRect target = QRect());
|
||||
void prepareCircle(QImage &image);
|
||||
QImage prepareColored(style::color add, QImage image);
|
||||
QImage prepareOpaque(QImage image);
|
||||
|
||||
enum class Option {
|
||||
None = 0,
|
||||
Smooth = (1 << 0),
|
||||
Blurred = (1 << 1),
|
||||
Circled = (1 << 2),
|
||||
RoundedLarge = (1 << 3),
|
||||
RoundedSmall = (1 << 4),
|
||||
RoundedTopLeft = (1 << 5),
|
||||
RoundedTopRight = (1 << 6),
|
||||
RoundedBottomLeft = (1 << 7),
|
||||
RoundedBottomRight = (1 << 8),
|
||||
RoundedAll = (None
|
||||
| RoundedTopLeft
|
||||
| RoundedTopRight
|
||||
| RoundedBottomLeft
|
||||
| RoundedBottomRight),
|
||||
Colored = (1 << 9),
|
||||
TransparentBackground = (1 << 10),
|
||||
};
|
||||
using Options = base::flags<Option>;
|
||||
inline constexpr auto is_flag_type(Option) { return true; };
|
||||
|
||||
QImage prepare(QImage img, int w, int h, Options options, int outerw, int outerh, const style::color *colored = nullptr);
|
||||
|
||||
inline QPixmap pixmap(QImage img, int w, int h, Options options, int outerw, int outerh, const style::color *colored = nullptr) {
|
||||
return QPixmap::fromImage(prepare(img, w, h, options, outerw, outerh, colored), Qt::ColorOnly);
|
||||
}
|
||||
|
||||
} // namespace Images
|
||||
|
||||
class FileLoader;
|
||||
class mtpFileLoader;
|
||||
|
||||
|
@ -35,13 +91,6 @@ enum LoadToCacheSetting {
|
|||
LoadToCacheAsWell,
|
||||
};
|
||||
|
||||
enum class ImageRoundRadius {
|
||||
None,
|
||||
Large,
|
||||
Small,
|
||||
Ellipse,
|
||||
};
|
||||
|
||||
inline uint32 packInt(int32 a) {
|
||||
return (a < 0) ? uint32(int64(a) + 0x100000000LL) : uint32(a);
|
||||
}
|
||||
|
@ -192,53 +241,6 @@ inline bool operator!=(const WebFileImageLocation &a, const WebFileImageLocation
|
|||
return !(a == b);
|
||||
}
|
||||
|
||||
namespace Images {
|
||||
|
||||
QImage prepareBlur(QImage image);
|
||||
void prepareRound(
|
||||
QImage &image,
|
||||
ImageRoundRadius radius,
|
||||
RectParts corners = RectPart::AllCorners,
|
||||
QRect target = QRect());
|
||||
void prepareRound(
|
||||
QImage &image,
|
||||
QImage *cornerMasks,
|
||||
RectParts corners = RectPart::AllCorners,
|
||||
QRect target = QRect());
|
||||
void prepareCircle(QImage &image);
|
||||
QImage prepareColored(style::color add, QImage image);
|
||||
QImage prepareOpaque(QImage image);
|
||||
|
||||
enum class Option {
|
||||
None = 0,
|
||||
Smooth = (1 << 0),
|
||||
Blurred = (1 << 1),
|
||||
Circled = (1 << 2),
|
||||
RoundedLarge = (1 << 3),
|
||||
RoundedSmall = (1 << 4),
|
||||
RoundedTopLeft = (1 << 5),
|
||||
RoundedTopRight = (1 << 6),
|
||||
RoundedBottomLeft = (1 << 7),
|
||||
RoundedBottomRight = (1 << 8),
|
||||
RoundedAll = (None
|
||||
| RoundedTopLeft
|
||||
| RoundedTopRight
|
||||
| RoundedBottomLeft
|
||||
| RoundedBottomRight),
|
||||
Colored = (1 << 9),
|
||||
TransparentBackground = (1 << 10),
|
||||
};
|
||||
using Options = base::flags<Option>;
|
||||
inline constexpr auto is_flag_type(Option) { return true; };
|
||||
|
||||
QImage prepare(QImage img, int w, int h, Options options, int outerw, int outerh, const style::color *colored = nullptr);
|
||||
|
||||
inline QPixmap pixmap(QImage img, int w, int h, Options options, int outerw, int outerh, const style::color *colored = nullptr) {
|
||||
return QPixmap::fromImage(prepare(img, w, h, options, outerw, outerh, colored), Qt::ColorOnly);
|
||||
}
|
||||
|
||||
} // namespace Images
|
||||
|
||||
class DelayedStorageImage;
|
||||
|
||||
class HistoryItem;
|
||||
|
|
|
@ -57,7 +57,7 @@ struct Preview {
|
|||
QString path;
|
||||
Instance instance;
|
||||
QByteArray content;
|
||||
QPixmap preview;
|
||||
QImage preview;
|
||||
};
|
||||
|
||||
bool Apply(const QString &filepath);
|
||||
|
|
|
@ -94,9 +94,9 @@ QString fillLetters(const QString &name) {
|
|||
|
||||
class Generator {
|
||||
public:
|
||||
Generator(const Instance &theme, const CurrentData ¤t);
|
||||
Generator(const Instance &theme, CurrentData &¤t);
|
||||
|
||||
QPixmap generate();
|
||||
QImage generate();
|
||||
|
||||
private:
|
||||
enum class Status {
|
||||
|
@ -173,7 +173,7 @@ private:
|
|||
|
||||
const Instance &_theme;
|
||||
const style::palette &_palette;
|
||||
const CurrentData &_current;
|
||||
CurrentData _current;
|
||||
Painter *_p = nullptr;
|
||||
|
||||
QRect _rect;
|
||||
|
@ -350,16 +350,18 @@ void Generator::generateData() {
|
|||
_bubbles.back().replyText.setText(st::messageTextStyle, "Mark Twain said that " + QString() + QChar(9757) + QChar(55356) + QChar(57339), Ui::DialogTextOptions());
|
||||
}
|
||||
|
||||
Generator::Generator(const Instance &theme, const CurrentData ¤t)
|
||||
Generator::Generator(const Instance &theme, CurrentData &¤t)
|
||||
: _theme(theme)
|
||||
, _palette(_theme.palette)
|
||||
, _current(current) {
|
||||
, _current(std::move(current)) {
|
||||
}
|
||||
|
||||
QPixmap Generator::generate() {
|
||||
QImage Generator::generate() {
|
||||
prepare();
|
||||
|
||||
auto result = QImage(_rect.size() * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
||||
auto result = QImage(
|
||||
_rect.size() * cIntRetinaFactor(),
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
result.setDevicePixelRatio(cRetinaFactor());
|
||||
result.fill(st::themePreviewBg->c);
|
||||
|
||||
|
@ -379,7 +381,7 @@ QPixmap Generator::generate() {
|
|||
}
|
||||
Platform::PreviewWindowFramePaint(result, _palette, _body, _rect.width());
|
||||
|
||||
return App::pixmapFromImageInPlace(std::move(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
void Generator::paintHistoryList() {
|
||||
|
@ -408,11 +410,12 @@ void Generator::paintHistoryBackground() {
|
|||
background.load(qsl(":/gui/art/bg.jpg"));
|
||||
tiled = false;
|
||||
} else {
|
||||
background = _current.backgroundImage.toImage();
|
||||
background = std::move(_current.backgroundImage);
|
||||
tiled = _current.backgroundTiled;
|
||||
}
|
||||
}
|
||||
background = std::move(background).convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
background = std::move(background).convertToFormat(
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
background.setDevicePixelRatio(cRetinaFactor());
|
||||
_p->setClipRect(_history);
|
||||
if (tiled) {
|
||||
|
@ -420,7 +423,10 @@ void Generator::paintHistoryBackground() {
|
|||
auto height = background.height();
|
||||
auto repeatTimesX = qCeil(_history.width() * cIntRetinaFactor() / float64(width));
|
||||
auto repeatTimesY = qCeil((_history.height() - fromy) * cIntRetinaFactor() / float64(height));
|
||||
auto imageForTiled = QImage(width * repeatTimesX, height * repeatTimesY, QImage::Format_ARGB32_Premultiplied);
|
||||
auto imageForTiled = QImage(
|
||||
width * repeatTimesX,
|
||||
height * repeatTimesY,
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
imageForTiled.setDevicePixelRatio(background.devicePixelRatio());
|
||||
auto imageForTiledBytes = imageForTiled.bits();
|
||||
auto bytesInLine = width * sizeof(uint32);
|
||||
|
@ -432,7 +438,8 @@ void Generator::paintHistoryBackground() {
|
|||
imageForTiledBytes += bytesInLine;
|
||||
}
|
||||
imageBytes += background.bytesPerLine();
|
||||
imageForTiledBytes += imageForTiled.bytesPerLine() - (repeatTimesX * bytesInLine);
|
||||
imageForTiledBytes += imageForTiled.bytesPerLine()
|
||||
- (repeatTimesX * bytesInLine);
|
||||
}
|
||||
}
|
||||
_p->drawImage(_history.x(), _history.y() + fromy, imageForTiled);
|
||||
|
@ -891,13 +898,18 @@ void Generator::restoreTextPalette() {
|
|||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<Preview> GeneratePreview(const QString &filepath, const CurrentData &data) {
|
||||
std::unique_ptr<Preview> GeneratePreview(
|
||||
const QString &filepath,
|
||||
CurrentData &&data) {
|
||||
auto result = std::make_unique<Preview>();
|
||||
result->path = filepath;
|
||||
if (!LoadFromFile(filepath, &result->instance, &result->content)) {
|
||||
return nullptr;
|
||||
}
|
||||
result->preview = Generator(result->instance, data).generate();
|
||||
result->preview = Generator(
|
||||
result->instance,
|
||||
std::move(data)
|
||||
).generate();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,14 +27,20 @@ namespace Theme {
|
|||
|
||||
struct CurrentData {
|
||||
int32 backgroundId = 0;
|
||||
QPixmap backgroundImage;
|
||||
QImage backgroundImage;
|
||||
bool backgroundTiled = false;
|
||||
};
|
||||
|
||||
std::unique_ptr<Preview> GeneratePreview(const QString &filepath, const CurrentData &data);
|
||||
std::unique_ptr<Preview> GeneratePreview(
|
||||
const QString &filepath,
|
||||
CurrentData &&data);
|
||||
|
||||
int DefaultPreviewTitleHeight();
|
||||
void DefaultPreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRect body, int outerWidth);
|
||||
void DefaultPreviewWindowFramePaint(
|
||||
QImage &preview,
|
||||
const style::palette &palette,
|
||||
QRect body,
|
||||
int outerWidth);
|
||||
|
||||
} // namespace Theme
|
||||
} // namespace Window
|
||||
|
|
Loading…
Add table
Reference in a new issue