Merge branch 'master' into HEAD

This commit is contained in:
John Preston 2021-08-12 09:02:35 +03:00
commit 40f0e3c6d4
9 changed files with 167 additions and 28 deletions

View file

@ -268,4 +268,6 @@ PUBLIC
target_link_libraries(lib_ui
PUBLIC
desktop-app::lib_base
PRIVATE
desktop-app::external_zlib
)

View file

@ -35,7 +35,7 @@ constexpr auto kSetVersion = uint32(2);
constexpr auto kCacheVersion = uint32(6);
constexpr auto kMaxId = uint32(1 << 8);
#if defined Q_OS_MAC && !defined OS_MAC_OLD
#ifdef Q_OS_MAC
constexpr auto kScaleForTouchBar = 150;
#endif
@ -80,7 +80,7 @@ auto CanClearUniversal = false;
auto WaitingToSwitchBackToId = 0;
auto Updates = rpl::event_stream<>();
#if defined Q_OS_MAC && !defined OS_MAC_OLD
#ifdef Q_OS_MAC
auto TouchbarSize = -1;
auto TouchbarInstance = std::unique_ptr<Instance>();
auto TouchbarEmoji = (Instance*)nullptr;
@ -498,7 +498,7 @@ void Init() {
InstanceNormal = std::make_unique<Instance>(SizeNormal);
InstanceLarge = std::make_unique<Instance>(SizeLarge);
#if defined Q_OS_MAC && !defined OS_MAC_OLD
#ifdef Q_OS_MAC
if (style::Scale() != kScaleForTouchBar) {
TouchbarSize = int(style::ConvertScale(18 * 4 / 3.,
kScaleForTouchBar * style::DevicePixelRatio()));
@ -516,7 +516,7 @@ void Clear() {
InstanceNormal = nullptr;
InstanceLarge = nullptr;
#if defined Q_OS_MAC && !defined OS_MAC_OLD
#ifdef Q_OS_MAC
TouchbarInstance = nullptr;
TouchbarEmoji = nullptr;
#endif
@ -620,7 +620,7 @@ int GetSizeLarge() {
return SizeLarge;
}
#if defined Q_OS_MAC && !defined OS_MAC_OLD
#ifdef Q_OS_MAC
int GetSizeTouchbar() {
return (style::Scale() == kScaleForTouchBar)
? GetSizeLarge()
@ -763,7 +763,7 @@ const QPixmap &SinglePixmap(EmojiPtr emoji, int fontHeight) {
}
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)
? SizeLarge
: TouchbarSize;

View file

@ -40,7 +40,7 @@ void ClearNeedSwitchToId();
[[nodiscard]] int GetSizeNormal();
[[nodiscard]] int GetSizeLarge();
#if defined Q_OS_MAC && !defined OS_MAC_OLD
#ifdef Q_OS_MAC
[[nodiscard]] int GetSizeTouchbar();
#endif

View file

@ -10,12 +10,22 @@
#include "ui/style/style_core.h"
#include "ui/painter.h"
#include "base/flat_map.h"
#include "base/debug_log.h"
#include "styles/palette.h"
#include "styles/style_basic.h"
#include "zlib.h"
#include <QtCore/QFile>
#include <QtCore/QBuffer>
#include <QtGui/QImageReader>
#include <QtSvg/QSvgRenderer>
namespace Images {
namespace {
// They should be smaller.
constexpr auto kMaxGzipFileSize = 5 * 1024 * 1024;
TG_FORCE_INLINE uint64 blurGetColors(const uchar *p) {
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;
}
[[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) {
if (img.isNull()) {
return img;

View file

@ -39,6 +39,28 @@ namespace Images {
int radius,
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);
void prepareRound(
QImage &image,

View file

@ -144,11 +144,7 @@ namespace internal {
QImage createCircleMask(int size, QColor bg, QColor fg) {
int realSize = size * DevicePixelRatio();
#ifndef OS_MAC_OLD
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);
PainterHighQualityEnabler hq(p);

View file

@ -134,14 +134,7 @@ bool IsBad(QChar ch) {
|| (ch >= 127 && ch < 160 && ch != 156)
// qt harfbuzz crash see https://github.com/telegramdesktop/tdesktop/issues/4551
|| (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));
|| (Platform::IsMac() && ch == 6158);
}
} // namespace
@ -1982,12 +1975,7 @@ private:
if (item == -1)
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);
#endif // OS_MAC_OLD
auto blockIndex = _lineStartBlock;
auto currentBlock = _t->_blocks[blockIndex].get();
auto nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex].get() : nullptr;

View file

@ -88,9 +88,7 @@ QRegularExpression CreateRegExp(const QString &expression) {
auto result = QRegularExpression(
expression,
QRegularExpression::UseUnicodePropertiesOption);
#ifndef OS_MAC_OLD
result.optimize();
#endif // OS_MAC_OLD
return result;
}

View file

@ -170,9 +170,7 @@ void SendSynteticMouseEvent(QWidget *widget, QEvent::Type type, Qt::MouseButton
, button
, QGuiApplication::mouseButtons() | button
, QGuiApplication::keyboardModifiers()
#ifndef OS_MAC_OLD
, Qt::MouseEventSynthesizedByApplication
#endif // OS_MAC_OLD
);
ev.setTimestamp(crl::now());
QGuiApplication::sendEvent(windowHandle, &ev);