Use base::SafeRound instead of std::round.

Previous assertion violations because of NaN from std::round were
in video streaming, see commits 27d58ba07b, 8f5830d520.

Now the crashes happened in the ConvertScale() call from a background
thread when preparing an image from clipboard for sending to a chat.
This commit is contained in:
John Preston 2021-09-27 12:13:57 +04:00
parent 21b10cebe0
commit 19ce1edc16
52 changed files with 101 additions and 112 deletions

View file

@ -210,7 +210,7 @@ void ServiceCheck::Generator::paintFrame(
const auto frames = framesForStyle(st);
auto &image = frames->image;
const auto count = int(frames->ready.size());
const auto index = int(std::round(toggled * (count - 1)));
const auto index = int(base::SafeRound(toggled * (count - 1)));
Assert(index >= 0 && index < count);
if (!frames->ready[index]) {
frames->ready[index] = true;

View file

@ -268,7 +268,8 @@ void Row::update(const InviteLinkData &data, TimeId now) {
void Row::updateExpireProgress(TimeId now) {
const auto updated = ComputeProgress(_data, now);
if (std::round(_progressTillExpire * 360) != std::round(updated * 360)) {
if (base::SafeRound(_progressTillExpire * 360)
!= base::SafeRound(updated * 360)) {
_progressTillExpire = updated;
const auto color = ComputeColor(_data, _progressTillExpire);
if (_color != color) {
@ -291,7 +292,8 @@ crl::time Row::updateExpireIn() const {
if (_data.expireDate <= start) {
return 0;
}
return std::round((_data.expireDate - start) * crl::time(1000) / 720.);
return base::SafeRound(
(_data.expireDate - start) * crl::time(1000) / 720.);
}
QString Row::generateName() {

View file

@ -209,7 +209,7 @@ void VideoBubble::updateSizeToFrame(QSize frame) {
size = frame.scaled((_min + _max) / 2, Qt::KeepAspectRatio);
} else {
const auto area = size.width() * size.height();
const auto w = int(std::round(std::max(
const auto w = int(base::SafeRound(std::max(
std::sqrt((frame.width() * float64(area)) / (frame.height() * 1.)),
1.)));
const auto h = area / w;

View file

@ -57,7 +57,7 @@ auto RowBlobs() -> std::array<Ui::Paint::Blobs::BlobData, 2> {
}
[[nodiscard]] QString StatusPercentString(float volume) {
return QString::number(int(std::round(volume * 200))) + '%';
return QString::number(int(base::SafeRound(volume * 200))) + '%';
}
[[nodiscard]] int StatusPercentWidth(const QString &percent) {
@ -492,7 +492,7 @@ int MembersRow::statusIconWidth(bool skipIcon) const {
const auto full = iconWidth
+ _statusIcon->percentWidth
+ st::normalFont->spacew;
return int(std::round(shown * full));
return int(base::SafeRound(shown * full));
}
int MembersRow::statusIconHeight() const {

View file

@ -461,15 +461,15 @@ Viewport::Layout Viewport::countWide(int outerWidth, int outerHeight) const {
const auto columns = slices;
const auto sizew = (outerWidth + skip) / float64(columns);
for (auto column = 0; column != columns; ++column) {
const auto left = int(std::round(column * sizew));
const auto width = int(std::round(column * sizew + sizew - skip))
- left;
const auto rows = int(std::round((count - index)
const auto left = int(base::SafeRound(column * sizew));
const auto width = int(
base::SafeRound(column * sizew + sizew - skip)) - left;
const auto rows = int(base::SafeRound((count - index)
/ float64(columns - column)));
const auto sizeh = (outerHeight + skip) / float64(rows);
for (auto row = 0; row != rows; ++row) {
const auto top = int(std::round(row * sizeh));
const auto height = int(std::round(
const auto top = int(base::SafeRound(row * sizeh));
const auto height = int(base::SafeRound(
row * sizeh + sizeh - skip)) - top;
auto &geometry = sizes[index];
geometry.columns = {
@ -493,15 +493,15 @@ Viewport::Layout Viewport::countWide(int outerWidth, int outerHeight) const {
const auto rows = slices;
const auto sizeh = (outerHeight + skip) / float64(rows);
for (auto row = 0; row != rows; ++row) {
const auto top = int(std::round(row * sizeh));
const auto height = int(std::round(row * sizeh + sizeh - skip))
- top;
const auto columns = int(std::round((count - index)
const auto top = int(base::SafeRound(row * sizeh));
const auto height = int(
base::SafeRound(row * sizeh + sizeh - skip)) - top;
const auto columns = int(base::SafeRound((count - index)
/ float64(rows - row)));
const auto sizew = (outerWidth + skip) / float64(columns);
for (auto column = 0; column != columns; ++column) {
const auto left = int(std::round(column * sizew));
const auto width = int(std::round(
const auto left = int(base::SafeRound(column * sizew));
const auto width = int(base::SafeRound(
column * sizew + sizew - skip)) - left;
auto &geometry = sizes[index];
geometry.rows = {

View file

@ -242,7 +242,7 @@ vec4 background() {
QSize outer,
float factor) {
factor *= kBlurTextureSizeFactor;
const auto area = outer / int(std::round(factor * cScale() / 100));
const auto area = outer / int(base::SafeRound(factor * cScale() / 100));
const auto scaled = unscaled.scaled(area, Qt::KeepAspectRatio);
return (scaled.width() > unscaled.width()
|| scaled.height() > unscaled.height())

View file

@ -92,7 +92,7 @@ MenuVolumeItem::MenuVolumeItem(
const auto volume = _localMuted
? 0
: std::round(_slider->value() * kMaxVolumePercent);
: base::SafeRound(_slider->value() * kMaxVolumePercent);
const auto muteProgress =
_crossLineAnimation.value((!volume) ? 1. : 0.);
@ -140,7 +140,7 @@ MenuVolumeItem::MenuVolumeItem(
};
_slider->setChangeFinishedCallback([=](float64 value) {
const auto newVolume = std::round(value * _maxVolume);
const auto newVolume = base::SafeRound(value * _maxVolume);
const auto muted = (value == 0);
if (!_cloudMuted && muted) {
@ -175,7 +175,7 @@ MenuVolumeItem::MenuVolumeItem(
}
if (_waitingForUpdateVolume) {
const auto localVolume =
std::round(_slider->value() * _maxVolume);
base::SafeRound(_slider->value() * _maxVolume);
if ((localVolume != newVolume)
&& (_cloudVolume == newVolume)) {
_changeVolumeRequests.fire(int(localVolume));

View file

@ -186,7 +186,7 @@ void EmojiInteractions::startIncoming(
}
const auto now = crl::now();
for (const auto &single : bunch.interactions) {
const auto at = now + crl::time(std::round(single.time * 1000));
const auto at = now + crl::time(base::SafeRound(single.time * 1000));
if (!animations.empty() && animations.back().scheduledAt >= at) {
continue;
}

View file

@ -68,7 +68,7 @@ QImage EmojiImageLoader::prepare(EmojiPtr emoji) const {
{ -1, 1 },
{ 1, 1 },
} };
const auto corrected = int(std::round(delta / sqrt(2.)));
const auto corrected = int(base::SafeRound(delta / sqrt(2.)));
for (const auto &shift : diagonal) {
for (auto i = 0; i != corrected; ++i) {
p.drawImage(QPoint(delta, delta) + shift * (i + 1), tinted);

View file

@ -617,7 +617,7 @@ public:
[[nodiscard]] static bool ThirdColumnByDefault();
[[nodiscard]] static float64 DefaultDialogsWidthRatio();
[[nodiscard]] static qint32 SerializePlaybackSpeed(float64 speed) {
return int(std::round(std::clamp(speed, 0.5, 2.0) * 100));
return int(base::SafeRound(std::clamp(speed, 0.5, 2.0) * 100));
}
[[nodiscard]] static float64 DeserializePlaybackSpeed(qint32 speed) {
if (speed < 10) {

View file

@ -586,7 +586,7 @@ bool ParseCommonMap(
}
return string.toULongLong();
} else if ((*version).isDouble()) {
return uint64(std::round((*version).toDouble()));
return uint64(base::SafeRound((*version).toDouble()));
}
return 0ULL;
}();

View file

@ -80,8 +80,9 @@ Storage::Cache::Key GeoPointCacheKey(const GeoPointLocation &location) {
| (uint32(location.height) & 0xFFFFU);
return Storage::Cache::Key{
Data::kGeoPointCacheTag | (uint64(zoomscale) << 32) | widthheight,
(uint64(std::round(std::abs(location.lat + 360.) * 1000000)) << 32)
| uint64(std::round(std::abs(location.lon + 360.) * 1000000))
(uint64(base::SafeRound(
std::abs(location.lat + 360.) * 1000000)) << 32)
| uint64(base::SafeRound(std::abs(location.lon + 360.) * 1000000))
};
}

View file

@ -150,7 +150,7 @@ void ItemBase::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
const auto angle = Normalized((isLeft ? 180 : 0)
+ (std::atan2(diff.y(), diff.x()) * 180 / M_PI));
setRotation(shift
? (std::round(angle / kSnapAngle) * kSnapAngle) // Snap rotation.
? (base::SafeRound(angle / kSnapAngle) * kSnapAngle)
: angle);
} else {
QGraphicsItem::mouseMoveEvent(event);

View file

@ -130,7 +130,7 @@ void PaintWaveform(
const auto samplesCount = wf
? wf->size()
: ::Media::Player::kWaveformSamplesCount;
const auto activeWidth = std::round(availableWidth * progress);
const auto activeWidth = base::SafeRound(availableWidth * progress);
const auto &barWidth = st::historyRecordWaveformBar;
const auto barFullWidth = barWidth + st::msgWaveformSkip;
@ -774,7 +774,7 @@ void RecordLock::drawProgress(Painter &p) {
_lockToStopProgress);
const auto blockRectTop = anim::interpolateF(
size.height() - blockHeight,
std::round((size.height() - blockRectHeight) / 2.),
base::SafeRound((size.height() - blockRectHeight) / 2.),
_lockToStopProgress);
const auto blockRect = QRectF(

View file

@ -477,7 +477,8 @@ void ListWidget::scrollToAnimationCallback(
int relativeTo) {
if (!attachToId) {
// Animated scroll to bottom.
const auto current = int(std::round(_scrollToAnimation.value(0)));
const auto current = int(base::SafeRound(
_scrollToAnimation.value(0)));
_delegate->listScrollTo(height()
- (_visibleBottom - _visibleTop)
+ current);
@ -488,7 +489,7 @@ void ListWidget::scrollToAnimationCallback(
if (!attachToView) {
_scrollToAnimation.stop();
} else {
const auto current = int(std::round(_scrollToAnimation.value(
const auto current = int(base::SafeRound(_scrollToAnimation.value(
relativeTo)));
_delegate->listScrollTo(itemTop(attachToView) + current);
}

View file

@ -308,7 +308,7 @@ bool SendActionPainter::updateNeedsAnimating(crl::time now, bool force) {
// We have to use QFontMetricsF instead of
// FontData::spacew for more precise calculation.
const auto mf = QFontMetricsF(_st.font->f);
_spacesCount = std::round(
_spacesCount = base::SafeRound(
_sendActionAnimation.widthNoMargins()
/ mf.horizontalAdvance(' '));
}

View file

@ -91,7 +91,7 @@ void PaintWaveform(
const auto wfSize = wf
? wf->size()
: ::Media::Player::kWaveformSamplesCount;
const auto activeWidth = std::round(availableWidth * progress);
const auto activeWidth = base::SafeRound(availableWidth * progress);
const auto &barWidth = st::msgWaveformBar;
const auto barCount = std::min(
@ -526,7 +526,7 @@ void Document::draw(
}();
if (voice->seeking()) {
voiceStatusOverride = Ui::FormatPlayedText(
std::round(progress * voice->_lastDurationMs) / 1000,
base::SafeRound(progress * voice->_lastDurationMs) / 1000,
voice->_lastDurationMs / 1000);
}

View file

@ -182,7 +182,7 @@ QSize GroupedMedia::countCurrentSize(int newWidth) {
const auto initialSpacing = st::historyGroupSkip;
const auto factor = newWidth / float64(maxWidth());
const auto scale = [&](int value) {
return int(std::round(value * factor));
return int(base::SafeRound(value * factor));
};
const auto spacing = scale(initialSpacing);
for (auto &part : _parts) {

View file

@ -963,7 +963,7 @@ void Poll::paintCloseByTimer(
const auto part = std::max(
left / float64(radial),
1. / FullArcLength);
const auto length = int(std::round(FullArcLength * part));
const auto length = int(base::SafeRound(FullArcLength * part));
auto pen = regular->p;
pen.setWidth(st::historyPollRadio.thickness);
pen.setCapStyle(Qt::RoundCap);
@ -1050,7 +1050,7 @@ int Poll::paintAnswer(
}
if (opacity > 0.) {
const auto percent = QString::number(
int(std::round(animation->percent.current()))) + '%';
int(base::SafeRound(animation->percent.current()))) + '%';
const auto percentWidth = st::historyPollPercentFont->width(
percent);
p.setOpacity(opacity);

View file

@ -49,7 +49,7 @@ int CoarseTuneForSpeed(float64 speed) {
constexpr auto kTuneSteps = 12;
const auto tuneRatio = std::log(speed) / std::log(2.);
return -int(std::round(kTuneSteps * tuneRatio));
return -int(base::SafeRound(kTuneSteps * tuneRatio));
}
} // namespace

View file

@ -654,7 +654,7 @@ void Instance::finishSeeking(AudioMsgId::Type type, float64 progress) {
const auto &info = streamed->instance.info();
const auto duration = info.audio.state.duration;
if (duration != kTimeUnknown) {
const auto position = crl::time(std::round(
const auto position = crl::time(base::SafeRound(
std::clamp(progress, 0., 1.) * duration));
streamed->instance.play(streamingOptions(
streamed->id,

View file

@ -12,8 +12,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/concurrent_timer.h"
#include "core/crash_reports.h"
#include <cfenv>
namespace Media {
namespace Streaming {
namespace {
@ -71,31 +69,6 @@ static_assert(kDisplaySkipped != kTimeUnknown);
return result;
}
[[nodiscard]] float64 SafeRound(float64 value) {
Expects(!std::isnan(value));
if (const auto result = std::round(value); !std::isnan(result)) {
return result;
}
const auto errors = std::fetestexcept(FE_ALL_EXCEPT);
if (const auto result = std::round(value); !std::isnan(result)) {
return result;
}
LOG(("Streaming Error: Got second NAN in std::round(%1), fe: %2."
).arg(value
).arg(errors));
std::feclearexcept(FE_ALL_EXCEPT);
if (const auto result = std::round(value); !std::isnan(result)) {
return result;
}
CrashReports::SetAnnotation("FE-Error-Value", QString::number(value));
CrashReports::SetAnnotation("FE-Errors-Were", QString::number(errors));
CrashReports::SetAnnotation(
"FE-Errors-Now",
QString::number(std::fetestexcept(FE_ALL_EXCEPT)));
Unexpected("NAN after third std::round.");
}
} // namespace
class VideoTrackObject final {
@ -713,7 +686,7 @@ TimePoint VideoTrackObject::trackTime() const {
}
const auto adjust = (result.worldTime - _syncTimePoint.worldTime);
const auto adjustSpeed = adjust * _options.speed;
const auto roundAdjustSpeed = SafeRound(adjustSpeed);
const auto roundAdjustSpeed = base::SafeRound(adjustSpeed);
const auto timeRoundAdjustSpeed = crl::time(roundAdjustSpeed);
result.trackTime = _syncTimePoint.trackTime + timeRoundAdjustSpeed;
return result;
@ -848,7 +821,7 @@ auto VideoTrack::Shared::presentFrame(
}
const auto trackLeft = position - time.trackTime;
const auto adjustedBySpeed = trackLeft / playbackSpeed;
const auto roundedAdjustedBySpeed = SafeRound(adjustedBySpeed);
const auto roundedAdjustedBySpeed = base::SafeRound(adjustedBySpeed);
frame->display = time.worldTime
+ addedWorldTimeDelay
+ crl::time(roundedAdjustedBySpeed);

View file

@ -32,7 +32,7 @@ namespace {
constexpr auto kThumbDuration = crl::time(150);
int Round(float64 value) {
return int(std::round(value));
return int(base::SafeRound(value));
}
using Context = GroupThumbs::Context;

View file

@ -441,7 +441,7 @@ void OverlayWidget::RendererGL::paintControl(
Assert(meta.icon == &icon);
const auto &bg = st::mediaviewControlBg->c;
const auto bgAlpha = int(std::round(bg.alpha() * outerOpacity));
const auto bgAlpha = int(base::SafeRound(bg.alpha() * outerOpacity));
const auto offset = kControlsOffset + (meta.index * kControlValues) / 4;
const auto fgOffset = offset + 2;
const auto bgRect = transformRect(outer);

View file

@ -1396,7 +1396,7 @@ void Pip::paintProgressBar(
float64 progress,
int radius,
float64 active) const {
const auto done = int(std::round(rect.width() * progress));
const auto done = int(base::SafeRound(rect.width() * progress));
PainterHighQualityEnabler hq(p);
p.setPen(Qt::NoPen);
if (done > 0) {

View file

@ -485,9 +485,9 @@ void Pip::RendererGL::paintRadialLoading(
const auto fadeAlpha = controlsShown * fade.alphaF();
const auto fgAlpha = 1. - fadeAlpha;
const auto color = (fadeAlpha == 0.) ? fg : QColor(
int(std::round(fg.red() * fgAlpha + fade.red() * fadeAlpha)),
int(std::round(fg.green() * fgAlpha + fade.green() * fadeAlpha)),
int(std::round(fg.blue() * fgAlpha + fade.blue() * fadeAlpha)),
int(base::SafeRound(fg.red() * fgAlpha + fade.red() * fadeAlpha)),
int(base::SafeRound(fg.green() * fgAlpha + fade.green() * fadeAlpha)),
int(base::SafeRound(fg.blue() * fgAlpha + fade.blue() * fadeAlpha)),
fg.alpha());
_owner->paintRadialLoadingContent(p, newInner, color);

View file

@ -102,7 +102,7 @@ MenuSpeedItem::MenuSpeedItem(
enableMouseSelecting(_slider.get());
_slider->setAlwaysDisplayMarker(true);
_slider->setValue((std::round(startSpeed * 100.) - kMinSpeed)
_slider->setValue((base::SafeRound(startSpeed * 100.) - kMinSpeed)
/ (kMaxSpeed - kMinSpeed));
for (const auto &sticked : kSpeedStickedValues) {
@ -438,7 +438,7 @@ void PlaybackControls::setLoadingProgress(int ready, int total) {
_loadingPercent = -1;
}
const auto progress = total ? (ready / float64(total)) : 0.;
const auto percent = int(std::round(progress * 100));
const auto percent = int(base::SafeRound(progress * 100));
if (_loadingPercent != percent) {
_loadingPercent = percent;
_downloadProgress->setText(QString::number(percent) + '%');

View file

@ -114,7 +114,7 @@ std::vector<DnsEntry> ParseDnsResponse(
const auto object = elem.toObject();
if (typeRestriction) {
const auto typeIt = object.find("type");
const auto type = int(std::round((*typeIt).toDouble()));
const auto type = int(base::SafeRound((*typeIt).toDouble()));
if (!(*typeIt).isDouble()) {
LOG(("Config Error: Not a number in type field "
"in Answer array in dns response JSON."));
@ -136,7 +136,7 @@ std::vector<DnsEntry> ParseDnsResponse(
const auto ttlIt = object.find("TTL");
const auto ttl = (ttlIt != object.constEnd())
? crl::time(std::round((*ttlIt).toDouble()))
? crl::time(base::SafeRound((*ttlIt).toDouble()))
: crl::time(0);
result.push_back({ (*dataIt).toString(), ttl });
}

View file

@ -544,7 +544,9 @@ MTPVector<MTPJSONObjectValue> SessionPrivate::prepareInitParams() {
sliced -= 24 * 3600;
}
const auto sign = (sliced < 0) ? -1 : 1;
const auto rounded = std::round(std::abs(sliced) / 900.) * 900 * sign;
const auto rounded = base::SafeRound(std::abs(sliced) / 900.)
* 900
* sign;
return MTP_vector<MTPJSONObjectValue>(
1,
MTP_jsonObjectValue(

View file

@ -229,7 +229,7 @@ struct SimpleFieldState {
QString()
).toDouble();
return QString::number(
int64(std::round(real * std::pow(10., rule.exponent))));
int64(base::SafeRound(real * std::pow(10., rule.exponent))));
} else if (config.type == FieldType::CardNumber
|| config.type == FieldType::CardCVC) {
return QString(parsed).replace(

View file

@ -452,8 +452,12 @@ void FormSummary::setupSuggestedTips(not_null<VerticalLayout*> layout) {
for (auto i = 0; i != count; ++i) {
const auto button = buttons[rowStart + i].widget;
auto right = x + buttonWidths[i];
button->setFullWidth(int(std::round(right) - std::round(x)));
button->moveToLeft(int(std::round(x)), height, outerWidth);
button->setFullWidth(
int(base::SafeRound(right) - base::SafeRound(x)));
button->moveToLeft(
int(base::SafeRound(x)),
height,
outerWidth);
x = right + skip;
}
height += buttons[0].widget->height() + skip;

View file

@ -240,7 +240,8 @@ TimeId CalculateOnlineTill(not_null<PeerData*> peer) {
: indexOf(peer);
const auto &entry = _pins[index];
entry->shift = entry->deltaShift
+ std::round(entry->shiftAnimation.value(entry->finalShift));
+ base::SafeRound(
entry->shiftAnimation.value(entry->finalShift));
if (entry->deltaShift && !entry->shiftAnimation.animating()) {
entry->finalShift += entry->deltaShift;
entry->deltaShift = 0;

View file

@ -362,7 +362,7 @@ void ColorsPalette::updateInnerGeometry() {
const auto y = st::settingsSectionSkip * 2;
auto x = float64(padding.left());
for (const auto &button : _buttons) {
button->moveToLeft(int(std::round(x)), y);
button->moveToLeft(int(base::SafeRound(x)), y);
x += size + skip;
}
inner->resize(inner->width(), y + size);
@ -1159,7 +1159,7 @@ void SetupDefaultThemes(
auto left = padding.left() + 0.;
for (const auto button : buttons) {
button->resizeToWidth(single);
button->moveToLeft(int(std::round(left)), 0);
button->moveToLeft(int(base::SafeRound(left)), 0);
left += button->width() + skip;
}
}, block->lifetime());

View file

@ -64,11 +64,11 @@ PreparedFileThumbnail PrepareFileThumbnail(QImage &&original) {
const auto scaledWidth = [&] {
return (width > height)
? kThumbnailSize
: int(std::round(kThumbnailSize * width / float64(height)));
: int(base::SafeRound(kThumbnailSize * width / float64(height)));
};
const auto scaledHeight = [&] {
return (width > height)
? int(std::round(kThumbnailSize * height / float64(width)))
? int(base::SafeRound(kThumbnailSize * height / float64(width)))
: kThumbnailSize;
};
result.image = scaled

View file

@ -85,7 +85,7 @@ QString StateDescription(const BlobState &state, tr::phrase<> activeText) {
return tr::lng_emoji_set_loading(
tr::now,
lt_percent,
QString::number(int(std::round(percent))) + '%',
QString::number(int(base::SafeRound(percent))) + '%',
lt_progress,
Ui::FormatDownloadText(data.already, data.size));
}, [](const Failed &data) {

View file

@ -329,6 +329,10 @@ void UpdateImageDetails(PreparedFile &file, int previewWidth) {
: image->data;
Assert(!preview.isNull());
file.shownDimensions = PrepareShownDimensions(preview);
const auto scaledWidth = style::ConvertScale(preview.width());
constexpr auto kIntMin = std::numeric_limits<int>::min();
static_assert(kIntMin == -2147483648);
scaledWidth;
const auto toWidth = std::min(
previewWidth,
style::ConvertScale(preview.width())

View file

@ -128,7 +128,7 @@ object_ptr<Ui::RpWidget> CreateSliderForTTL(
// Try to fill the line with exact number of dash segments.
// UPD Doesn't work so well because it changes when clicking.
//const auto length = till - from;
//const auto offSegmentsCount = int(std::round(
//const auto offSegmentsCount = int(base::SafeRound(
// (length - st->dashOn) / (st->dashOn + st->dashOff)));
//const auto onSegmentsCount = offSegmentsCount + 1;
//const auto idealLength = offSegmentsCount * st->dashOff

View file

@ -263,7 +263,7 @@ void AlbumPreview::updateSize() {
} else if (!_sendWay.groupFiles()) {
return _photosHeight;
} else {
return int(std::round(_thumbsHeightAnimation.value(
return int(base::SafeRound(_thumbsHeightAnimation.value(
_thumbsHeight)));
}
}();

View file

@ -270,7 +270,7 @@ void AlbumThumbnail::drawSimpleFrame(Painter &p, QRect to, QSize size) const {
const auto scaleWidth = to.width() / float64(width);
const auto scaleHeight = to.height() / float64(height);
const auto Round = [](float64 value) {
return int(std::round(value));
return int(base::SafeRound(value));
};
const auto [from, fillBlack] = [&] {
if (previewWidth < width && previewHeight < height) {
@ -474,7 +474,7 @@ void AlbumThumbnail::suggestMove(float64 delta, Fn<void()> callback) {
}
QRect AlbumThumbnail::countRealGeometry() const {
const auto addLeft = int(std::round(
const auto addLeft = int(base::SafeRound(
_suggestedMoveAnimation.value(_suggestedMove) * _lastShrinkValue));
const auto current = _layout.geometry;
const auto realTopLeft = current.topLeft()

View file

@ -63,7 +63,7 @@ rpl::producer<bool> GroupCallScheduledLeft::late() const {
void GroupCallScheduledLeft::update() {
const auto now = crl::now();
const auto duration = (_datePrecise - now);
const auto left = crl::time(std::round(std::abs(duration) / 1000.));
const auto left = crl::time(base::SafeRound(std::abs(duration) / 1000.));
const auto late = (duration < 0) && (left > 0);
_late = late;
constexpr auto kDay = 24 * 60 * 60;

View file

@ -1002,7 +1002,7 @@ void CallMuteButton::shake() {
? -1.
: 0.;
const auto shift = from * (1. - part) + to * part;
_labelShakeShift = int(std::round(shift * st::shakeShift));
_labelShakeShift = int(base::SafeRound(shift * st::shakeShift));
updateLabelsGeometry();
};
_shakeAnimation.start(

View file

@ -176,7 +176,7 @@ QPixmap CheckCaches::frame(
auto &frames = framesForStyle(st, displayInactive);
const auto frameCount = int(frames.list.size());
const auto frameIndex = int(std::round(progress * (frameCount - 1)));
const auto frameIndex = int(base::SafeRound(progress * (frameCount - 1)));
Assert(frameIndex >= 0 && frameIndex < frameCount);
if (!frames.list[frameIndex]) {

View file

@ -44,11 +44,11 @@ void PaintSavedMessagesInner(
// X XX XX X | |
// XX XX --- ---
const auto thinkness = std::round(size * 0.055);
const auto thinkness = base::SafeRound(size * 0.055);
const auto increment = int(thinkness) % 2 + (size % 2);
const auto width = std::round(size * 0.15) * 2 + increment;
const auto height = std::round(size * 0.19) * 2 + increment;
const auto add = std::round(size * 0.064);
const auto width = base::SafeRound(size * 0.15) * 2 + increment;
const auto height = base::SafeRound(size * 0.19) * 2 + increment;
const auto add = base::SafeRound(size * 0.064);
const auto left = x + (size - width) / 2;
const auto top = y + (size - height) / 2;

View file

@ -11,7 +11,7 @@ namespace Ui {
namespace {
int Round(float64 value) {
return int(std::round(value));
return int(base::SafeRound(value));
}
class Layouter {

View file

@ -694,8 +694,9 @@ InMemoryKey inMemoryKey(const WebFileLocation &location) {
InMemoryKey inMemoryKey(const GeoPointLocation &location) {
return InMemoryKey(
(uint64(std::round(std::abs(location.lat + 360.) * 1000000)) << 32)
| uint64(std::round(std::abs(location.lon + 360.) * 1000000)),
(uint64(base::SafeRound(
std::abs(location.lat + 360.) * 1000000)) << 32)
| uint64(base::SafeRound(std::abs(location.lon + 360.) * 1000000)),
(uint64(location.width) << 32) | uint64(location.height));
}

View file

@ -329,7 +329,7 @@ void MediaSlider::paintEvent(QPaintEvent *e) {
const auto dividerValue = horizontal
? divider.atValue
: (1. - divider.atValue);
const auto dividerMid = std::round(from
const auto dividerMid = base::SafeRound(from
+ dividerValue * length);
const auto &size = divider.size;
const auto rect = horizontal

View file

@ -167,14 +167,14 @@ public:
}
}
setAdjustCallback([=](float64 value) {
return std::round(value * sectionsCount) / sectionsCount;
return base::SafeRound(value * sectionsCount) / sectionsCount;
});
setChangeProgressCallback([
=,
convert = std::forward<Convert>(convert),
callback = std::forward<Callback>(callback)
](float64 value) {
const auto index = int(std::round(value * sectionsCount));
const auto index = int(base::SafeRound(value * sectionsCount));
callback(convert(index));
});
}

View file

@ -723,7 +723,7 @@ int CloudList::resizeGetHeight(int newWidth) {
for (const auto &element : _elements) {
const auto button = element.button.get();
button->resizeToWidth(single);
button->moveToLeft(int(std::round(x)), y);
button->moveToLeft(int(base::SafeRound(x)), y);
accumulate_max(rowHeight, button->height());
x += single + skip;
if (++index == kShowPerRow) {

@ -1 +1 @@
Subproject commit c42df26ff4a2359d996ceadbc84fd798b1b116fb
Subproject commit 4e5c7cd97a7bab5007e5ff050829aaa8b0688313

@ -1 +1 @@
Subproject commit d134c0361ef96b5061c2719a0e984eaaed2c1a81
Subproject commit 33427eb49c0b9a22651956df3290ec06d436742d

@ -1 +1 @@
Subproject commit 29cfdad44c22cb653fe756e4e1fba0f172fb3ca7
Subproject commit e62d92f655a60b507bada9e387fb48aae89a5e72

@ -1 +1 @@
Subproject commit 29d51317915ca43db45d436cba8eac3f40dea36b
Subproject commit 86194868334e3b51bc6300176d935c2beb84e37d