mirror of https://github.com/procxx/kepka.git
gif redesign done, started ClipReader - gif animation reader in separate thread
This commit is contained in:
parent
6100c1dcca
commit
a66c051eb5
|
@ -148,6 +148,13 @@ void AnimatedGif::step_frame(float64 ms, bool timer) {
|
||||||
if (img.size() != QSize(w, h)) img = img.scaled(w, h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
if (img.size() != QSize(w, h)) img = img.scaled(w, h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||||
images[f] = img;
|
images[f] = img;
|
||||||
frames[f] = QPixmap();
|
frames[f] = QPixmap();
|
||||||
|
for (int32 i = 0; i < f; ++i) {
|
||||||
|
if (!images[i].isNull() || !frames[i].isNull()) {
|
||||||
|
images[i] = QImage();
|
||||||
|
frames[i] = QPixmap();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (frame != f) {
|
if (frame != f) {
|
||||||
|
@ -253,3 +260,30 @@ const QPixmap &AnimatedGif::current(int32 width, int32 height, bool rounded) {
|
||||||
}
|
}
|
||||||
return frames[frame];
|
return frames[frame];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClipReader::ClipReader(const FileLocation &location, const QByteArray &data) : _state(ClipStopped)
|
||||||
|
, _location(location.isEmpty() ? 0 : new FileLocation(location))
|
||||||
|
, _data(data)
|
||||||
|
, _width(0)
|
||||||
|
, _height(0)
|
||||||
|
, _rounded(false)
|
||||||
|
, _currentDisplayed(true) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClipReader::start(int32 framew, int32 frameh, bool rounded) {
|
||||||
|
_rounded = rounded;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QPixmap &ClipReader::current(int32 framew, int32 frameh) {
|
||||||
|
_currentDisplayed = true;
|
||||||
|
return _current;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClipState ClipReader::state() const {
|
||||||
|
return _state;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClipReader::~ClipReader() {
|
||||||
|
delete _location;
|
||||||
|
setBadPointer(_location);
|
||||||
|
}
|
||||||
|
|
|
@ -470,3 +470,34 @@ private:
|
||||||
Animation _a_frames;
|
Animation _a_frames;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ClipState {
|
||||||
|
ClipPlaying,
|
||||||
|
ClipStopped,
|
||||||
|
};
|
||||||
|
|
||||||
|
class ClipReader {
|
||||||
|
public:
|
||||||
|
|
||||||
|
ClipReader(const FileLocation &location, const QByteArray &data);
|
||||||
|
|
||||||
|
void start(int32 framew, int32 frameh, bool rounded);
|
||||||
|
const QPixmap ¤t(int32 framew, int32 frameh);
|
||||||
|
|
||||||
|
ClipState state() const;
|
||||||
|
|
||||||
|
~ClipReader();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
ClipState _state;
|
||||||
|
|
||||||
|
FileLocation *_location;
|
||||||
|
QByteArray _data;
|
||||||
|
int32 _width, _height;
|
||||||
|
bool _rounded;
|
||||||
|
|
||||||
|
QPixmap _current;
|
||||||
|
bool _currentDisplayed;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
|
@ -3430,7 +3430,6 @@ void HistoryPhoto::draw(Painter &p, const HistoryItem *parent, const QRect &r, b
|
||||||
}
|
}
|
||||||
|
|
||||||
// date
|
// date
|
||||||
QString time(parent->timeText());
|
|
||||||
if (_caption.isEmpty()) {
|
if (_caption.isEmpty()) {
|
||||||
int32 fullRight = skipx + width, fullBottom = skipy + height;
|
int32 fullRight = skipx + width, fullBottom = skipy + height;
|
||||||
parent->drawInfo(p, fullRight, fullBottom, 2 * skipx + width, selected, InfoDisplayOverImage);
|
parent->drawInfo(p, fullRight, fullBottom, 2 * skipx + width, selected, InfoDisplayOverImage);
|
||||||
|
@ -3562,9 +3561,9 @@ void HistoryFileMedia::setLinks(ITextLink *openl, ITextLink *savel, ITextLink *c
|
||||||
void HistoryFileMedia::setStatusSize(int32 newSize, int32 fullSize, int32 duration, qint64 realDuration) const {
|
void HistoryFileMedia::setStatusSize(int32 newSize, int32 fullSize, int32 duration, qint64 realDuration) const {
|
||||||
_statusSize = newSize;
|
_statusSize = newSize;
|
||||||
if (_statusSize == FileStatusSizeReady) {
|
if (_statusSize == FileStatusSizeReady) {
|
||||||
_statusText = (duration >= 0) ? formatDurationAndSizeText(duration, fullSize) : formatSizeText(fullSize);
|
_statusText = (duration >= 0) ? formatDurationAndSizeText(duration, fullSize) : (duration < -1 ? formatGifAndSizeText(fullSize) : formatSizeText(fullSize));
|
||||||
} else if (_statusSize == FileStatusSizeLoaded) {
|
} else if (_statusSize == FileStatusSizeLoaded) {
|
||||||
_statusText = (duration >= 0) ? formatDurationText(duration) : formatSizeText(fullSize);
|
_statusText = (duration >= 0) ? formatDurationText(duration) : (duration < -1 ? qsl("GIF") : formatSizeText(fullSize));
|
||||||
} else if (_statusSize == FileStatusSizeFailed) {
|
} else if (_statusSize == FileStatusSizeFailed) {
|
||||||
_statusText = lang(lng_attach_failed);
|
_statusText = lang(lng_attach_failed);
|
||||||
} else if (_statusSize >= 0) {
|
} else if (_statusSize >= 0) {
|
||||||
|
@ -3618,7 +3617,7 @@ void HistoryFileMedia::checkAnimationFinished() {
|
||||||
HistoryFileMedia::~HistoryFileMedia() {
|
HistoryFileMedia::~HistoryFileMedia() {
|
||||||
if (_animation) {
|
if (_animation) {
|
||||||
delete _animation;
|
delete _animation;
|
||||||
setBadLink(_animation);
|
setBadPointer(_animation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3876,7 +3875,6 @@ void HistoryVideo::draw(Painter &p, const HistoryItem *parent, const QRect &r, b
|
||||||
p.drawTextLeft(statusX, statusY, w, _statusText, statusW - 2 * st::msgDateImgPadding.x());
|
p.drawTextLeft(statusX, statusY, w, _statusText, statusW - 2 * st::msgDateImgPadding.x());
|
||||||
|
|
||||||
// date
|
// date
|
||||||
QString time(parent->timeText());
|
|
||||||
if (_caption.isEmpty()) {
|
if (_caption.isEmpty()) {
|
||||||
int32 fullRight = skipx + width, fullBottom = skipy + height;
|
int32 fullRight = skipx + width, fullBottom = skipy + height;
|
||||||
parent->drawInfo(p, fullRight, fullBottom, 2 * skipx + width, selected, InfoDisplayOverImage);
|
parent->drawInfo(p, fullRight, fullBottom, 2 * skipx + width, selected, InfoDisplayOverImage);
|
||||||
|
@ -4568,22 +4566,56 @@ ImagePtr HistoryDocument::replyPreview() {
|
||||||
return _data->makeReplyPreview();
|
return _data->makeReplyPreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryGif::HistoryGif(DocumentData *document) : HistoryMedia()
|
HistoryGif::HistoryGif(DocumentData *document) : HistoryFileMedia()
|
||||||
, _data(document)
|
, _data(document)
|
||||||
, _openl(new DocumentOpenLink(_data))
|
, _thumbw(1)
|
||||||
, _savel(new DocumentSaveLink(_data))
|
, _thumbh(1) {
|
||||||
, _cancell(new DocumentCancelLink(_data))
|
setLinks(new DocumentOpenLink(_data), new DocumentSaveLink(_data), new DocumentCancelLink(_data));
|
||||||
, _name(documentName(_data))
|
|
||||||
, _statusSize(-1) {
|
setStatusSize(FileStatusSizeReady);
|
||||||
|
|
||||||
_data->thumb->load();
|
_data->thumb->load();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryGif::initDimensions(const HistoryItem *parent) {
|
void HistoryGif::initDimensions(const HistoryItem *parent) {
|
||||||
|
bool bubble = parent->hasBubble();
|
||||||
|
int32 tw = 0, th = 0;
|
||||||
if (parent == animated.msg) {
|
if (parent == animated.msg) {
|
||||||
_maxw = animated.w / cIntRetinaFactor();
|
tw = convertScale(animated.w / cIntRetinaFactor());
|
||||||
_minh = animated.h / cIntRetinaFactor();
|
th = convertScale(animated.h / cIntRetinaFactor());
|
||||||
} else {
|
} else {
|
||||||
|
tw = convertScale(_data->dimensions.width()), th = convertScale(_data->dimensions.height());
|
||||||
|
if (!tw || !th) {
|
||||||
|
tw = convertScale(_data->thumb->width());
|
||||||
|
th = convertScale(_data->thumb->height());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tw > st::maxMediaSize) {
|
||||||
|
th = (st::maxMediaSize * th) / tw;
|
||||||
|
tw = st::maxMediaSize;
|
||||||
|
}
|
||||||
|
if (th > st::maxMediaSize) {
|
||||||
|
tw = (st::maxMediaSize * tw) / th;
|
||||||
|
th = st::maxMediaSize;
|
||||||
|
}
|
||||||
|
if (!tw || !th) {
|
||||||
|
tw = th = 1;
|
||||||
|
}
|
||||||
|
_thumbw = tw;
|
||||||
|
_thumbh = th;
|
||||||
|
if (parent == animated.msg) {
|
||||||
|
_maxw = qMax(tw, int32(st::minPhotoSize));
|
||||||
|
_minh = qMax(th, int32(st::minPhotoSize));
|
||||||
|
} else {
|
||||||
|
int32 minWidth = qMax(st::minPhotoSize, parent->infoWidth() + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x()));
|
||||||
|
minWidth = qMax(minWidth, gifMaxStatusWidth(_data) + 2 * int32(st::msgDateImgDelta + st::msgDateImgPadding.x()));
|
||||||
|
_maxw = qMax(tw, minWidth);
|
||||||
|
_minh = qMax(th, int32(st::minPhotoSize));
|
||||||
|
}
|
||||||
|
w = _maxw;
|
||||||
|
if (bubble) {
|
||||||
|
_maxw += st::mediaPadding.left() + st::mediaPadding.right();
|
||||||
|
_minh += st::mediaPadding.top() + st::mediaPadding.bottom();
|
||||||
}
|
}
|
||||||
_height = _minh;
|
_height = _minh;
|
||||||
}
|
}
|
||||||
|
@ -4592,25 +4624,115 @@ void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, boo
|
||||||
if (w < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
if (w < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||||
int32 width = w, height = _height, skipx = 0, skipy = 0;
|
int32 width = w, height = _height, skipx = 0, skipy = 0;
|
||||||
|
|
||||||
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel, hovered, pressed;
|
bool animating = (parent == animated.msg);
|
||||||
bool already = !_data->already().isEmpty(), hasdata = !_data->data.isEmpty();
|
bool bubble = parent->hasBubble();
|
||||||
if (parent == animated.msg) {
|
bool fromChannel = parent->fromChannel(), out = parent->out(), outbg = out && !fromChannel;
|
||||||
int32 pw = animated.w / cIntRetinaFactor(), ph = animated.h / cIntRetinaFactor();
|
|
||||||
if (width < pw) {
|
if (!animating) {
|
||||||
pw = width;
|
if (_data->loader) {
|
||||||
ph = (pw == w) ? _height : (pw * animated.h / animated.w);
|
ensureAnimation(parent);
|
||||||
if (ph < 1) ph = 1;
|
if (!_animation->radial.animating()) {
|
||||||
|
_animation->radial.start(_data->progress());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
updateStatusText(parent);
|
||||||
|
}
|
||||||
|
bool radial = !animating && isRadialAnimation(ms);
|
||||||
|
|
||||||
App::roundShadow(p, 0, 0, pw, ph, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners);
|
if (bubble) {
|
||||||
|
skipx = st::mediaPadding.left();
|
||||||
|
skipy = st::mediaPadding.top();
|
||||||
|
|
||||||
p.drawPixmap(0, 0, animated.current(pw * cIntRetinaFactor(), ph * cIntRetinaFactor(), true));
|
width -= st::mediaPadding.left() + st::mediaPadding.right();
|
||||||
|
height -= skipy + st::mediaPadding.bottom();
|
||||||
|
} else {
|
||||||
|
App::roundShadow(p, 0, 0, width, _height, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners);
|
||||||
|
}
|
||||||
|
_data->thumb->checkload();
|
||||||
|
|
||||||
|
QRect rthumb(rtlrect(skipx, skipy, width, height, w));
|
||||||
|
|
||||||
|
if (animating) {
|
||||||
|
p.drawPixmap(rthumb.topLeft(), animated.current(width, height, true));
|
||||||
|
} else {
|
||||||
|
p.drawPixmap(rthumb.topLeft(), _data->thumb->pixBlurredSingle(_thumbw, _thumbh, width, height));
|
||||||
|
}
|
||||||
if (selected) {
|
if (selected) {
|
||||||
App::roundRect(p, 0, 0, pw, ph, textstyleCurrent()->selectOverlay, SelectedOverlayCorners);
|
App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayCorners);
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!animating) {
|
||||||
|
QRect inner(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
|
||||||
|
p.setPen(Qt::NoPen);
|
||||||
|
if (selected) {
|
||||||
|
p.setBrush(st::msgDateImgBgSelected);
|
||||||
|
} else if (_animation && _animation->_a_thumbOver.animating()) {
|
||||||
|
_animation->_a_thumbOver.step(ms);
|
||||||
|
float64 over = _animation->a_thumbOver.current();
|
||||||
|
p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over));
|
||||||
|
p.setBrush(st::black);
|
||||||
|
} else {
|
||||||
|
bool over = textlnkDrawOver(_data->loader ? _cancell : _savel);
|
||||||
|
p.setBrush(over ? st::msgDateImgBgOver : st::msgDateImgBg);
|
||||||
|
}
|
||||||
|
|
||||||
|
p.setRenderHint(QPainter::HighQualityAntialiasing);
|
||||||
|
p.drawEllipse(inner);
|
||||||
|
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
|
||||||
|
|
||||||
|
if (!selected && _animation) {
|
||||||
|
p.setOpacity(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
style::sprite icon;
|
||||||
|
if (!_data->already().isEmpty()) {
|
||||||
|
icon = (selected ? st::msgFileInPlaySelected : st::msgFileInPlay);
|
||||||
|
} else if (_data->loader) {
|
||||||
|
icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel);
|
||||||
|
} else {
|
||||||
|
icon = (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload);
|
||||||
|
}
|
||||||
|
p.drawSpriteCenter(inner, icon);
|
||||||
|
if (radial) {
|
||||||
|
QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine)));
|
||||||
|
_animation->radial.draw(p, rinner, selected ? st::msgInBgSelected : st::msgInBg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 statusX = skipx + st::msgDateImgDelta + st::msgDateImgPadding.x(), statusY = skipy + st::msgDateImgDelta + st::msgDateImgPadding.y();
|
||||||
|
int32 statusW = st::normalFont->width(_statusText) + 2 * st::msgDateImgPadding.x();
|
||||||
|
int32 statusH = st::normalFont->height + 2 * st::msgDateImgPadding.y();
|
||||||
|
App::roundRect(p, rtlrect(statusX - st::msgDateImgPadding.x(), statusY - st::msgDateImgPadding.y(), statusW, statusH, w), selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners);
|
||||||
|
p.setFont(st::normalFont);
|
||||||
|
p.setPen(st::white);
|
||||||
|
p.drawTextLeft(statusX, statusY, w, _statusText, statusW - 2 * st::msgDateImgPadding.x());
|
||||||
|
|
||||||
|
// date
|
||||||
|
int32 fullRight = skipx + width, fullBottom = skipy + height;
|
||||||
|
parent->drawInfo(p, fullRight, fullBottom, 2 * skipx + width, selected, InfoDisplayOverImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryGif::setStatusSize(int32 newSize) const {
|
||||||
|
HistoryFileMedia::setStatusSize(newSize, _data->size, -2, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryGif::updateStatusText(const HistoryItem *parent) const {
|
||||||
|
bool showPause = false;
|
||||||
|
int32 statusSize = 0, realDuration = 0;
|
||||||
|
if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) {
|
||||||
|
statusSize = FileStatusSizeFailed;
|
||||||
|
} else if (_data->status == FileUploading) {
|
||||||
|
statusSize = _data->uploadOffset;
|
||||||
|
} else if (_data->loader) {
|
||||||
|
statusSize = _data->loader->currentOffset();
|
||||||
|
} else if (!_data->already().isEmpty()) {
|
||||||
|
statusSize = FileStatusSizeLoaded;
|
||||||
|
} else {
|
||||||
|
statusSize = FileStatusSizeReady;
|
||||||
|
}
|
||||||
|
if (statusSize != _statusSize) {
|
||||||
|
setStatusSize(statusSize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryGif::regItem(HistoryItem *item) {
|
void HistoryGif::regItem(HistoryItem *item) {
|
||||||
|
@ -4628,40 +4750,65 @@ void HistoryGif::updateFrom(const MTPMessageMedia &media, HistoryItem *parent, b
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 HistoryGif::resize(int32 width, const HistoryItem *parent) {
|
int32 HistoryGif::resize(int32 width, const HistoryItem *parent) {
|
||||||
w = qMin(width, _maxw);
|
bool bubble = parent->hasBubble();
|
||||||
|
|
||||||
|
int32 tw = 0, th = 0;
|
||||||
if (parent == animated.msg) {
|
if (parent == animated.msg) {
|
||||||
if (w > st::maxMediaSize) {
|
tw = convertScale(animated.w / cIntRetinaFactor());
|
||||||
w = st::maxMediaSize;
|
th = convertScale(animated.h / cIntRetinaFactor());
|
||||||
}
|
|
||||||
_height = animated.h / cIntRetinaFactor();
|
|
||||||
if (animated.w / cIntRetinaFactor() > w) {
|
|
||||||
_height = (w * _height / (animated.w / cIntRetinaFactor()));
|
|
||||||
if (_height <= 0) _height = 1;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
_height = _minh;
|
tw = convertScale(_data->dimensions.width()), th = convertScale(_data->dimensions.height());
|
||||||
|
if (!tw || !th) {
|
||||||
|
tw = convertScale(_data->thumb->width());
|
||||||
|
th = convertScale(_data->thumb->height());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tw > st::maxMediaSize) {
|
||||||
|
th = (st::maxMediaSize * th) / tw;
|
||||||
|
tw = st::maxMediaSize;
|
||||||
|
}
|
||||||
|
if (th > st::maxMediaSize) {
|
||||||
|
tw = (st::maxMediaSize * tw) / th;
|
||||||
|
th = st::maxMediaSize;
|
||||||
|
}
|
||||||
|
if (!tw || !th) {
|
||||||
|
tw = th = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bubble) {
|
||||||
|
width -= st::mediaPadding.left() + st::mediaPadding.right();
|
||||||
|
}
|
||||||
|
if (width < tw) {
|
||||||
|
th = qRound((width / float64(tw)) * th);
|
||||||
|
tw = width;
|
||||||
|
}
|
||||||
|
w = _thumbw = tw;
|
||||||
|
_thumbh = th;
|
||||||
|
|
||||||
|
if (parent != animated.msg) {
|
||||||
|
int32 minWidth = qMax(st::minPhotoSize, parent->infoWidth() + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x()));
|
||||||
|
minWidth = qMax(minWidth, gifMaxStatusWidth(_data) + 2 * int32(st::msgDateImgDelta + st::msgDateImgPadding.x()));
|
||||||
|
w = qMax(w, minWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
_height = qMax(th, int32(st::minPhotoSize));
|
||||||
|
if (bubble) {
|
||||||
|
w += st::mediaPadding.left() + st::mediaPadding.right();
|
||||||
|
_height += st::mediaPadding.top() + st::mediaPadding.bottom();
|
||||||
}
|
}
|
||||||
return _height;
|
return _height;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString HistoryGif::inDialogsText() const {
|
const QString HistoryGif::inDialogsText() const {
|
||||||
return _name.isEmpty() ? lang(lng_in_dlg_file) : _name;
|
return _data->name.isEmpty() ? lang(lng_in_dlg_file) : _data->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString HistoryGif::inHistoryText() const {
|
const QString HistoryGif::inHistoryText() const {
|
||||||
return qsl("[ ") + lang(lng_in_dlg_file) + (_name.isEmpty() ? QString() : (qsl(" : ") + _name)) + qsl(" ]");
|
return qsl("[ ") + lang(lng_in_dlg_file) + (_data->name.isEmpty() ? QString() : (qsl(" : ") + _data->name)) + qsl(" ]");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryGif::hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width) const {
|
bool HistoryGif::hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width) const {
|
||||||
if (width < 0) width = w;
|
if (width < 0) width = w;
|
||||||
if (width >= _maxw) {
|
|
||||||
width = _maxw;
|
|
||||||
}
|
|
||||||
if (parent == animated.msg) {
|
|
||||||
int32 h = (width == w) ? _height : (width * animated.h / animated.w);
|
|
||||||
if (h < 1) h = 1;
|
|
||||||
return (x >= 0 && y >= 0 && x < width && y < h);
|
|
||||||
}
|
|
||||||
return (x >= 0 && y >= 0 && x < width && y < _height);
|
return (x >= 0 && y >= 0 && x < width && y < _height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4670,29 +4817,75 @@ int32 HistoryGif::countHeight(const HistoryItem *parent, int32 width) const {
|
||||||
if (width >= _maxw) {
|
if (width >= _maxw) {
|
||||||
width = _maxw;
|
width = _maxw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool bubble = parent->hasBubble();
|
||||||
|
|
||||||
|
int32 tw = 0, th = 0;
|
||||||
if (parent == animated.msg) {
|
if (parent == animated.msg) {
|
||||||
int32 h = (width == w) ? _height : (width * animated.h / animated.w);
|
tw = convertScale(animated.w / cIntRetinaFactor());
|
||||||
if (h < 1) h = 1;
|
th = convertScale(animated.h / cIntRetinaFactor());
|
||||||
return h;
|
} else {
|
||||||
|
tw = convertScale(_data->dimensions.width()), th = convertScale(_data->dimensions.height());
|
||||||
|
if (!tw || !th) {
|
||||||
|
tw = convertScale(_data->thumb->width());
|
||||||
|
th = convertScale(_data->thumb->height());
|
||||||
}
|
}
|
||||||
return _height;
|
}
|
||||||
|
if (tw > st::maxMediaSize) {
|
||||||
|
th = (st::maxMediaSize * th) / tw;
|
||||||
|
tw = st::maxMediaSize;
|
||||||
|
}
|
||||||
|
if (th > st::maxMediaSize) {
|
||||||
|
tw = (st::maxMediaSize * tw) / th;
|
||||||
|
th = st::maxMediaSize;
|
||||||
|
}
|
||||||
|
if (!tw || !th) {
|
||||||
|
tw = th = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bubble) {
|
||||||
|
width -= st::mediaPadding.left() + st::mediaPadding.right();
|
||||||
|
}
|
||||||
|
if (width < tw) {
|
||||||
|
th = qRound((width / float64(tw)) * th);
|
||||||
|
tw = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 h = qMax(th, int32(st::minPhotoSize));
|
||||||
|
if (bubble) {
|
||||||
|
tw += st::mediaPadding.left() + st::mediaPadding.right();
|
||||||
|
h += st::mediaPadding.top() + st::mediaPadding.bottom();
|
||||||
|
}
|
||||||
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryGif::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width) const {
|
void HistoryGif::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width) const {
|
||||||
|
bool bubble = parent->hasBubble();
|
||||||
|
|
||||||
if (width < 0) width = w;
|
if (width < 0) width = w;
|
||||||
if (width < 1) return;
|
if (width < 1) return;
|
||||||
|
|
||||||
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel, hovered, pressed;
|
int skipx = 0, skipy = 0, height = _height;
|
||||||
if (width >= _maxw) {
|
if (bubble) {
|
||||||
width = _maxw;
|
skipx = st::mediaPadding.left();
|
||||||
|
skipy = st::mediaPadding.top();
|
||||||
|
width -= st::mediaPadding.left() + st::mediaPadding.right();
|
||||||
|
height -= skipy + st::mediaPadding.bottom();
|
||||||
}
|
}
|
||||||
|
if (x >= skipx && y >= skipy && x < skipx + width && y < skipy + height) {
|
||||||
if (parent == animated.msg) {
|
if (parent == animated.msg) {
|
||||||
int32 h = (width == w) ? _height : (width * animated.h / animated.w);
|
lnk = _openl;
|
||||||
if (h < 1) h = 1;
|
} else {
|
||||||
lnk = (x >= 0 && y >= 0 && x < width && y < h) ? _openl : TextLinkPtr();
|
lnk = _data->already().isEmpty() ? (_data->loader ? _cancell : _savel) : _openl;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32 fullRight = skipx + width, fullBottom = skipy + height;
|
||||||
|
bool inDate = parent->pointInTime(fullRight, fullBottom, x, y, InfoDisplayOverImage);
|
||||||
|
if (inDate) {
|
||||||
|
state = HistoryInDateCursorState;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryMedia *HistoryGif::clone() const {
|
HistoryMedia *HistoryGif::clone() const {
|
||||||
|
@ -6452,6 +6645,8 @@ void HistoryMessage::initMediaFromText(QString ¤tText) {
|
||||||
void HistoryMessage::initMediaFromDocument(DocumentData *doc) {
|
void HistoryMessage::initMediaFromDocument(DocumentData *doc) {
|
||||||
if (doc->sticker()) {
|
if (doc->sticker()) {
|
||||||
_media = new HistorySticker(doc);
|
_media = new HistorySticker(doc);
|
||||||
|
} else if (doc->type == AnimatedDocument) {
|
||||||
|
_media = new HistoryGif(doc);
|
||||||
} else {
|
} else {
|
||||||
_media = new HistoryDocument(doc);
|
_media = new HistoryDocument(doc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1015,9 +1015,6 @@ public:
|
||||||
virtual int32 timeLeft() const {
|
virtual int32 timeLeft() const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
virtual QString timeText() const {
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
virtual int32 timeWidth() const {
|
virtual int32 timeWidth() const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1326,6 +1323,7 @@ protected:
|
||||||
mutable int32 _statusSize;
|
mutable int32 _statusSize;
|
||||||
mutable QString _statusText;
|
mutable QString _statusText;
|
||||||
|
|
||||||
|
// duration = -1 - no duration, duration = -2 - "GIF" duration
|
||||||
void setStatusSize(int32 newSize, int32 fullSize, int32 duration, qint64 realDuration) const;
|
void setStatusSize(int32 newSize, int32 fullSize, int32 duration, qint64 realDuration) const;
|
||||||
|
|
||||||
void step_thumbOver(const HistoryItem *parent, float64 ms, bool timer);
|
void step_thumbOver(const HistoryItem *parent, float64 ms, bool timer);
|
||||||
|
@ -1559,7 +1557,7 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class HistoryGif : public HistoryMedia {
|
class HistoryGif : public HistoryFileMedia {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
HistoryGif(DocumentData *document);
|
HistoryGif(DocumentData *document);
|
||||||
|
@ -1603,18 +1601,32 @@ public:
|
||||||
bool customInfoLayout() const {
|
bool customInfoLayout() const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
bool hideFromName() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool hideForwardedFrom() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
float64 dataProgress() const {
|
||||||
|
return _data->progress();
|
||||||
|
}
|
||||||
|
bool dataFinished() const {
|
||||||
|
return !_data->loader;
|
||||||
|
}
|
||||||
|
bool dataLoaded() const {
|
||||||
|
return !_data->already().isEmpty() && !_data->data.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
DocumentData *_data;
|
DocumentData *_data;
|
||||||
TextLinkPtr _openl, _savel, _cancell;
|
int32 _thumbw, _thumbh;
|
||||||
|
|
||||||
int32 _namew;
|
void setStatusSize(int32 newSize) const;
|
||||||
QString _name, _size;
|
void updateStatusText(const HistoryItem *parent) const;
|
||||||
int32 _thumbw, _thumbx, _thumby;
|
|
||||||
|
|
||||||
mutable QString _statusText;
|
|
||||||
mutable int32 _statusSize; // -1 will contain just size string, -2 will contain "failed" language key
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1980,9 +1992,6 @@ public:
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
QString timeText() const {
|
|
||||||
return _timeText;
|
|
||||||
}
|
|
||||||
int32 timeWidth() const {
|
int32 timeWidth() const {
|
||||||
return _timeWidth;
|
return _timeWidth;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5366,6 +5366,8 @@ void HistoryWidget::onDocumentUploaded(const FullMsgId &newId, const MTPInputFil
|
||||||
DocumentData *document = 0;
|
DocumentData *document = 0;
|
||||||
if (HistoryDocument *media = dynamic_cast<HistoryDocument*>(item->getMedia())) {
|
if (HistoryDocument *media = dynamic_cast<HistoryDocument*>(item->getMedia())) {
|
||||||
document = media->document();
|
document = media->document();
|
||||||
|
} else if (HistoryGif *media = dynamic_cast<HistoryGif*>(item->getMedia())) {
|
||||||
|
document = media->document();
|
||||||
} else if (HistorySticker *media = dynamic_cast<HistorySticker*>(item->getMedia())) {
|
} else if (HistorySticker *media = dynamic_cast<HistorySticker*>(item->getMedia())) {
|
||||||
document = media->document();
|
document = media->document();
|
||||||
}
|
}
|
||||||
|
@ -5395,6 +5397,8 @@ void HistoryWidget::onThumbDocumentUploaded(const FullMsgId &newId, const MTPInp
|
||||||
DocumentData *document = 0;
|
DocumentData *document = 0;
|
||||||
if (HistoryDocument *media = dynamic_cast<HistoryDocument*>(item->getMedia())) {
|
if (HistoryDocument *media = dynamic_cast<HistoryDocument*>(item->getMedia())) {
|
||||||
document = media->document();
|
document = media->document();
|
||||||
|
} else if (HistoryGif *media = dynamic_cast<HistoryGif*>(item->getMedia())) {
|
||||||
|
document = media->document();
|
||||||
} else if (HistorySticker *media = dynamic_cast<HistorySticker*>(item->getMedia())) {
|
} else if (HistorySticker *media = dynamic_cast<HistorySticker*>(item->getMedia())) {
|
||||||
document = media->document();
|
document = media->document();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1888,7 +1888,7 @@ void MainWidget::documentLoadProgress(mtpFileLoader *loader) {
|
||||||
if (location.accessEnable()) {
|
if (location.accessEnable()) {
|
||||||
QImageReader reader(location.name());
|
QImageReader reader(location.name());
|
||||||
if (reader.canRead()) {
|
if (reader.canRead()) {
|
||||||
if (reader.supportsAnimation() && reader.imageCount() > 1 && item) {
|
if (reader.supportsAnimation() && reader.imageCount() > 1 && item && item->getMedia() && item->getMedia()->type() == MediaTypeGif) {
|
||||||
startGif(item, location);
|
startGif(item, location);
|
||||||
} else if (item) {
|
} else if (item) {
|
||||||
App::wnd()->showDocument(document, item);
|
App::wnd()->showDocument(document, item);
|
||||||
|
|
|
@ -888,7 +888,7 @@ void DocumentOpenLink::doOpen(DocumentData *data) {
|
||||||
} else if (data->size < MediaViewImageSizeLimit && location.accessEnable()) {
|
} else if (data->size < MediaViewImageSizeLimit && location.accessEnable()) {
|
||||||
QImageReader reader(location.name());
|
QImageReader reader(location.name());
|
||||||
if (reader.canRead()) {
|
if (reader.canRead()) {
|
||||||
if (reader.supportsAnimation() && reader.imageCount() > 1 && App::hoveredLinkItem()) {
|
if (reader.supportsAnimation() && reader.imageCount() > 1 && App::hoveredLinkItem() && App::hoveredLinkItem()->getMedia() && App::hoveredLinkItem()->getMedia()->type() == MediaTypeGif) {
|
||||||
startGif(App::hoveredLinkItem(), location);
|
startGif(App::hoveredLinkItem(), location);
|
||||||
} else if (App::hoveredLinkItem() || App::contextItem()) {
|
} else if (App::hoveredLinkItem() || App::contextItem()) {
|
||||||
App::wnd()->showDocument(data, App::hoveredLinkItem() ? App::hoveredLinkItem() : App::contextItem());
|
App::wnd()->showDocument(data, App::hoveredLinkItem() ? App::hoveredLinkItem() : App::contextItem());
|
||||||
|
|
|
@ -21,7 +21,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
void setBadLink(Type *&link) {
|
void setBadPointer(Type *&link) {
|
||||||
link = reinterpret_cast<Type*>(0x00000bad);
|
link = reinterpret_cast<Type*>(0x00000bad);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue