Merge branch 'master' into HEAD
This commit is contained in:
commit
40f0e3c6d4
9 changed files with 167 additions and 28 deletions
|
|
@ -268,4 +268,6 @@ PUBLIC
|
||||||
target_link_libraries(lib_ui
|
target_link_libraries(lib_ui
|
||||||
PUBLIC
|
PUBLIC
|
||||||
desktop-app::lib_base
|
desktop-app::lib_base
|
||||||
|
PRIVATE
|
||||||
|
desktop-app::external_zlib
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ constexpr auto kSetVersion = uint32(2);
|
||||||
constexpr auto kCacheVersion = uint32(6);
|
constexpr auto kCacheVersion = uint32(6);
|
||||||
constexpr auto kMaxId = uint32(1 << 8);
|
constexpr auto kMaxId = uint32(1 << 8);
|
||||||
|
|
||||||
#if defined Q_OS_MAC && !defined OS_MAC_OLD
|
#ifdef Q_OS_MAC
|
||||||
constexpr auto kScaleForTouchBar = 150;
|
constexpr auto kScaleForTouchBar = 150;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -80,7 +80,7 @@ auto CanClearUniversal = false;
|
||||||
auto WaitingToSwitchBackToId = 0;
|
auto WaitingToSwitchBackToId = 0;
|
||||||
auto Updates = rpl::event_stream<>();
|
auto Updates = rpl::event_stream<>();
|
||||||
|
|
||||||
#if defined Q_OS_MAC && !defined OS_MAC_OLD
|
#ifdef Q_OS_MAC
|
||||||
auto TouchbarSize = -1;
|
auto TouchbarSize = -1;
|
||||||
auto TouchbarInstance = std::unique_ptr<Instance>();
|
auto TouchbarInstance = std::unique_ptr<Instance>();
|
||||||
auto TouchbarEmoji = (Instance*)nullptr;
|
auto TouchbarEmoji = (Instance*)nullptr;
|
||||||
|
|
@ -498,7 +498,7 @@ void Init() {
|
||||||
InstanceNormal = std::make_unique<Instance>(SizeNormal);
|
InstanceNormal = std::make_unique<Instance>(SizeNormal);
|
||||||
InstanceLarge = std::make_unique<Instance>(SizeLarge);
|
InstanceLarge = std::make_unique<Instance>(SizeLarge);
|
||||||
|
|
||||||
#if defined Q_OS_MAC && !defined OS_MAC_OLD
|
#ifdef Q_OS_MAC
|
||||||
if (style::Scale() != kScaleForTouchBar) {
|
if (style::Scale() != kScaleForTouchBar) {
|
||||||
TouchbarSize = int(style::ConvertScale(18 * 4 / 3.,
|
TouchbarSize = int(style::ConvertScale(18 * 4 / 3.,
|
||||||
kScaleForTouchBar * style::DevicePixelRatio()));
|
kScaleForTouchBar * style::DevicePixelRatio()));
|
||||||
|
|
@ -516,7 +516,7 @@ void Clear() {
|
||||||
|
|
||||||
InstanceNormal = nullptr;
|
InstanceNormal = nullptr;
|
||||||
InstanceLarge = nullptr;
|
InstanceLarge = nullptr;
|
||||||
#if defined Q_OS_MAC && !defined OS_MAC_OLD
|
#ifdef Q_OS_MAC
|
||||||
TouchbarInstance = nullptr;
|
TouchbarInstance = nullptr;
|
||||||
TouchbarEmoji = nullptr;
|
TouchbarEmoji = nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -620,7 +620,7 @@ int GetSizeLarge() {
|
||||||
return SizeLarge;
|
return SizeLarge;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined Q_OS_MAC && !defined OS_MAC_OLD
|
#ifdef Q_OS_MAC
|
||||||
int GetSizeTouchbar() {
|
int GetSizeTouchbar() {
|
||||||
return (style::Scale() == kScaleForTouchBar)
|
return (style::Scale() == kScaleForTouchBar)
|
||||||
? GetSizeLarge()
|
? GetSizeLarge()
|
||||||
|
|
@ -763,7 +763,7 @@ const QPixmap &SinglePixmap(EmojiPtr emoji, int fontHeight) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Draw(QPainter &p, EmojiPtr emoji, int size, int x, int y) {
|
void Draw(QPainter &p, EmojiPtr emoji, int size, int x, int y) {
|
||||||
#if defined Q_OS_MAC && !defined OS_MAC_OLD
|
#ifdef Q_OS_MAC
|
||||||
const auto s = (style::Scale() == kScaleForTouchBar)
|
const auto s = (style::Scale() == kScaleForTouchBar)
|
||||||
? SizeLarge
|
? SizeLarge
|
||||||
: TouchbarSize;
|
: TouchbarSize;
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ void ClearNeedSwitchToId();
|
||||||
|
|
||||||
[[nodiscard]] int GetSizeNormal();
|
[[nodiscard]] int GetSizeNormal();
|
||||||
[[nodiscard]] int GetSizeLarge();
|
[[nodiscard]] int GetSizeLarge();
|
||||||
#if defined Q_OS_MAC && !defined OS_MAC_OLD
|
#ifdef Q_OS_MAC
|
||||||
[[nodiscard]] int GetSizeTouchbar();
|
[[nodiscard]] int GetSizeTouchbar();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,22 @@
|
||||||
#include "ui/style/style_core.h"
|
#include "ui/style/style_core.h"
|
||||||
#include "ui/painter.h"
|
#include "ui/painter.h"
|
||||||
#include "base/flat_map.h"
|
#include "base/flat_map.h"
|
||||||
|
#include "base/debug_log.h"
|
||||||
#include "styles/palette.h"
|
#include "styles/palette.h"
|
||||||
#include "styles/style_basic.h"
|
#include "styles/style_basic.h"
|
||||||
|
|
||||||
|
#include "zlib.h"
|
||||||
|
#include <QtCore/QFile>
|
||||||
|
#include <QtCore/QBuffer>
|
||||||
|
#include <QtGui/QImageReader>
|
||||||
|
#include <QtSvg/QSvgRenderer>
|
||||||
|
|
||||||
namespace Images {
|
namespace Images {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
// They should be smaller.
|
||||||
|
constexpr auto kMaxGzipFileSize = 5 * 1024 * 1024;
|
||||||
|
|
||||||
TG_FORCE_INLINE uint64 blurGetColors(const uchar *p) {
|
TG_FORCE_INLINE uint64 blurGetColors(const uchar *p) {
|
||||||
return (uint64)p[0] + ((uint64)p[1] << 16) + ((uint64)p[2] << 32) + ((uint64)p[3] << 48);
|
return (uint64)p[0] + ((uint64)p[1] << 16) + ((uint64)p[2] << 32) + ((uint64)p[3] << 48);
|
||||||
}
|
}
|
||||||
|
|
@ -111,6 +121,131 @@ std::array<QImage, 4> PrepareCorners(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] QByteArray UnpackGzip(const QByteArray &bytes) {
|
||||||
|
z_stream stream;
|
||||||
|
stream.zalloc = nullptr;
|
||||||
|
stream.zfree = nullptr;
|
||||||
|
stream.opaque = nullptr;
|
||||||
|
stream.avail_in = 0;
|
||||||
|
stream.next_in = nullptr;
|
||||||
|
int res = inflateInit2(&stream, 16 + MAX_WBITS);
|
||||||
|
if (res != Z_OK) {
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
const auto guard = gsl::finally([&] { inflateEnd(&stream); });
|
||||||
|
|
||||||
|
auto result = QByteArray(kMaxGzipFileSize + 1, char(0));
|
||||||
|
stream.avail_in = bytes.size();
|
||||||
|
stream.next_in = reinterpret_cast<Bytef*>(const_cast<char*>(bytes.data()));
|
||||||
|
stream.avail_out = 0;
|
||||||
|
while (!stream.avail_out) {
|
||||||
|
stream.avail_out = result.size();
|
||||||
|
stream.next_out = reinterpret_cast<Bytef*>(result.data());
|
||||||
|
int res = inflate(&stream, Z_NO_FLUSH);
|
||||||
|
if (res != Z_OK && res != Z_STREAM_END) {
|
||||||
|
return bytes;
|
||||||
|
} else if (!stream.avail_out) {
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.resize(result.size() - stream.avail_out);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] ReadResult ReadGzipSvg(const ReadArgs &args) {
|
||||||
|
const auto bytes = UnpackGzip(args.content);
|
||||||
|
if (bytes.isEmpty()) {
|
||||||
|
LOG(("Svg Error: Couldn't unpack gzip-ed content."));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
auto renderer = QSvgRenderer(bytes);
|
||||||
|
if (!renderer.isValid()) {
|
||||||
|
LOG(("Svg Error: Invalid data."));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
auto size = renderer.defaultSize();
|
||||||
|
if (!args.maxSize.isEmpty()
|
||||||
|
&& (size.width() > args.maxSize.width()
|
||||||
|
|| size.height() > args.maxSize.height())) {
|
||||||
|
size = size.scaled(args.maxSize, Qt::KeepAspectRatio);
|
||||||
|
}
|
||||||
|
if (size.isEmpty()) {
|
||||||
|
LOG(("Svg Error: Bad size %1x%2."
|
||||||
|
).arg(renderer.defaultSize().width()
|
||||||
|
).arg(renderer.defaultSize().height()));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
auto result = ReadResult();
|
||||||
|
result.image = QImage(size, QImage::Format_ARGB32_Premultiplied);
|
||||||
|
result.image.fill(Qt::transparent);
|
||||||
|
{
|
||||||
|
QPainter p(&result.image);
|
||||||
|
renderer.render(&p, QRect(QPoint(), size));
|
||||||
|
}
|
||||||
|
result.format = "svg";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] ReadResult ReadOther(const ReadArgs &args) {
|
||||||
|
auto bytes = args.content;
|
||||||
|
if (bytes.isEmpty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
auto buffer = QBuffer(&bytes);
|
||||||
|
auto reader = QImageReader(&buffer);
|
||||||
|
reader.setAutoTransform(true);
|
||||||
|
if (!reader.canRead()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const auto size = reader.size();
|
||||||
|
if (size.width() * size.height() > kReadMaxArea) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
auto result = ReadResult();
|
||||||
|
if (!reader.read(&result.image) || result.image.isNull()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
result.animated = reader.supportsAnimation()
|
||||||
|
&& (reader.imageCount() > 1);
|
||||||
|
result.format = reader.format().toLower();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadResult Read(ReadArgs &&args) {
|
||||||
|
if (args.content.isEmpty()) {
|
||||||
|
auto file = QFile(args.path);
|
||||||
|
if (file.size() > kReadBytesLimit
|
||||||
|
|| !file.open(QIODevice::ReadOnly)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
args.content = file.readAll();
|
||||||
|
}
|
||||||
|
auto result = args.gzipSvg ? ReadGzipSvg(args) : ReadOther(args);
|
||||||
|
if (result.image.isNull()) {
|
||||||
|
args = ReadArgs();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (args.returnContent) {
|
||||||
|
result.content = args.content;
|
||||||
|
} else {
|
||||||
|
args.content = QByteArray();
|
||||||
|
}
|
||||||
|
if (!args.maxSize.isEmpty()
|
||||||
|
&& (result.image.width() > args.maxSize.width()
|
||||||
|
|| result.image.height() > args.maxSize.height())) {
|
||||||
|
result.image = result.image.scaled(
|
||||||
|
args.maxSize,
|
||||||
|
Qt::KeepAspectRatio,
|
||||||
|
Qt::SmoothTransformation);
|
||||||
|
}
|
||||||
|
if (args.forceOpaque
|
||||||
|
&& result.format != qstr("jpg")
|
||||||
|
&& result.format != qstr("jpeg")) {
|
||||||
|
result.image = prepareOpaque(std::move(result.image));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QImage prepareBlur(QImage img) {
|
QImage prepareBlur(QImage img) {
|
||||||
if (img.isNull()) {
|
if (img.isNull()) {
|
||||||
return img;
|
return img;
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,28 @@ namespace Images {
|
||||||
int radius,
|
int radius,
|
||||||
const style::color &color);
|
const style::color &color);
|
||||||
|
|
||||||
|
[[nodiscard]] QByteArray UnpackGzip(const QByteArray &bytes);
|
||||||
|
|
||||||
|
// Try to read images up to 64MB.
|
||||||
|
inline constexpr auto kReadBytesLimit = 64 * 1024 * 1024;
|
||||||
|
inline constexpr auto kReadMaxArea = 12'032 * 9'024;
|
||||||
|
|
||||||
|
struct ReadArgs {
|
||||||
|
QString path;
|
||||||
|
QByteArray content;
|
||||||
|
QSize maxSize;
|
||||||
|
bool gzipSvg = false;
|
||||||
|
bool forceOpaque = false;
|
||||||
|
bool returnContent = false;
|
||||||
|
};
|
||||||
|
struct ReadResult {
|
||||||
|
QImage image;
|
||||||
|
QByteArray content;
|
||||||
|
QByteArray format;
|
||||||
|
bool animated = false;
|
||||||
|
};
|
||||||
|
[[nodiscard]] ReadResult Read(ReadArgs &&args);
|
||||||
|
|
||||||
QImage prepareBlur(QImage image);
|
QImage prepareBlur(QImage image);
|
||||||
void prepareRound(
|
void prepareRound(
|
||||||
QImage &image,
|
QImage &image,
|
||||||
|
|
|
||||||
|
|
@ -144,11 +144,7 @@ namespace internal {
|
||||||
|
|
||||||
QImage createCircleMask(int size, QColor bg, QColor fg) {
|
QImage createCircleMask(int size, QColor bg, QColor fg) {
|
||||||
int realSize = size * DevicePixelRatio();
|
int realSize = size * DevicePixelRatio();
|
||||||
#ifndef OS_MAC_OLD
|
|
||||||
auto result = QImage(realSize, realSize, QImage::Format::Format_Grayscale8);
|
auto result = QImage(realSize, realSize, QImage::Format::Format_Grayscale8);
|
||||||
#else // OS_MAC_OLD
|
|
||||||
auto result = QImage(realSize, realSize, QImage::Format::Format_RGB32);
|
|
||||||
#endif // OS_MAC_OLD
|
|
||||||
{
|
{
|
||||||
QPainter p(&result);
|
QPainter p(&result);
|
||||||
PainterHighQualityEnabler hq(p);
|
PainterHighQualityEnabler hq(p);
|
||||||
|
|
|
||||||
|
|
@ -134,14 +134,7 @@ bool IsBad(QChar ch) {
|
||||||
|| (ch >= 127 && ch < 160 && ch != 156)
|
|| (ch >= 127 && ch < 160 && ch != 156)
|
||||||
|
|
||||||
// qt harfbuzz crash see https://github.com/telegramdesktop/tdesktop/issues/4551
|
// qt harfbuzz crash see https://github.com/telegramdesktop/tdesktop/issues/4551
|
||||||
|| (Platform::IsMac() && ch == 6158)
|
|| (Platform::IsMac() && ch == 6158);
|
||||||
|
|
||||||
// tmp hack see https://bugreports.qt.io/browse/QTBUG-48910
|
|
||||||
|| (Platform::IsMac10_11OrGreater()
|
|
||||||
&& !Platform::IsMac10_12OrGreater()
|
|
||||||
&& ch >= 0x0B00
|
|
||||||
&& ch <= 0x0B7F
|
|
||||||
&& IsDiac(ch));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
@ -1982,12 +1975,7 @@ private:
|
||||||
if (item == -1)
|
if (item == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef OS_MAC_OLD
|
|
||||||
auto end = _e->findItem(line.from + line.length - 1);
|
|
||||||
#else // OS_MAC_OLD
|
|
||||||
auto end = _e->findItem(line.from + line.length - 1, item);
|
auto end = _e->findItem(line.from + line.length - 1, item);
|
||||||
#endif // OS_MAC_OLD
|
|
||||||
|
|
||||||
auto blockIndex = _lineStartBlock;
|
auto blockIndex = _lineStartBlock;
|
||||||
auto currentBlock = _t->_blocks[blockIndex].get();
|
auto currentBlock = _t->_blocks[blockIndex].get();
|
||||||
auto nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex].get() : nullptr;
|
auto nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex].get() : nullptr;
|
||||||
|
|
|
||||||
|
|
@ -88,9 +88,7 @@ QRegularExpression CreateRegExp(const QString &expression) {
|
||||||
auto result = QRegularExpression(
|
auto result = QRegularExpression(
|
||||||
expression,
|
expression,
|
||||||
QRegularExpression::UseUnicodePropertiesOption);
|
QRegularExpression::UseUnicodePropertiesOption);
|
||||||
#ifndef OS_MAC_OLD
|
|
||||||
result.optimize();
|
result.optimize();
|
||||||
#endif // OS_MAC_OLD
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -170,9 +170,7 @@ void SendSynteticMouseEvent(QWidget *widget, QEvent::Type type, Qt::MouseButton
|
||||||
, button
|
, button
|
||||||
, QGuiApplication::mouseButtons() | button
|
, QGuiApplication::mouseButtons() | button
|
||||||
, QGuiApplication::keyboardModifiers()
|
, QGuiApplication::keyboardModifiers()
|
||||||
#ifndef OS_MAC_OLD
|
|
||||||
, Qt::MouseEventSynthesizedByApplication
|
, Qt::MouseEventSynthesizedByApplication
|
||||||
#endif // OS_MAC_OLD
|
|
||||||
);
|
);
|
||||||
ev.setTimestamp(crl::now());
|
ev.setTimestamp(crl::now());
|
||||||
QGuiApplication::sendEvent(windowHandle, &ev);
|
QGuiApplication::sendEvent(windowHandle, &ev);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue