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); const auto frames = framesForStyle(st);
auto &image = frames->image; auto &image = frames->image;
const auto count = int(frames->ready.size()); 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); Assert(index >= 0 && index < count);
if (!frames->ready[index]) { if (!frames->ready[index]) {
frames->ready[index] = true; frames->ready[index] = true;

View file

@ -268,7 +268,8 @@ void Row::update(const InviteLinkData &data, TimeId now) {
void Row::updateExpireProgress(TimeId now) { void Row::updateExpireProgress(TimeId now) {
const auto updated = ComputeProgress(_data, 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; _progressTillExpire = updated;
const auto color = ComputeColor(_data, _progressTillExpire); const auto color = ComputeColor(_data, _progressTillExpire);
if (_color != color) { if (_color != color) {
@ -291,7 +292,8 @@ crl::time Row::updateExpireIn() const {
if (_data.expireDate <= start) { if (_data.expireDate <= start) {
return 0; 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() { QString Row::generateName() {

View file

@ -209,7 +209,7 @@ void VideoBubble::updateSizeToFrame(QSize frame) {
size = frame.scaled((_min + _max) / 2, Qt::KeepAspectRatio); size = frame.scaled((_min + _max) / 2, Qt::KeepAspectRatio);
} else { } else {
const auto area = size.width() * size.height(); 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.)), std::sqrt((frame.width() * float64(area)) / (frame.height() * 1.)),
1.))); 1.)));
const auto h = area / w; 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) { [[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) { [[nodiscard]] int StatusPercentWidth(const QString &percent) {
@ -492,7 +492,7 @@ int MembersRow::statusIconWidth(bool skipIcon) const {
const auto full = iconWidth const auto full = iconWidth
+ _statusIcon->percentWidth + _statusIcon->percentWidth
+ st::normalFont->spacew; + st::normalFont->spacew;
return int(std::round(shown * full)); return int(base::SafeRound(shown * full));
} }
int MembersRow::statusIconHeight() const { 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 columns = slices;
const auto sizew = (outerWidth + skip) / float64(columns); const auto sizew = (outerWidth + skip) / float64(columns);
for (auto column = 0; column != columns; ++column) { for (auto column = 0; column != columns; ++column) {
const auto left = int(std::round(column * sizew)); const auto left = int(base::SafeRound(column * sizew));
const auto width = int(std::round(column * sizew + sizew - skip)) const auto width = int(
- left; base::SafeRound(column * sizew + sizew - skip)) - left;
const auto rows = int(std::round((count - index) const auto rows = int(base::SafeRound((count - index)
/ float64(columns - column))); / float64(columns - column)));
const auto sizeh = (outerHeight + skip) / float64(rows); const auto sizeh = (outerHeight + skip) / float64(rows);
for (auto row = 0; row != rows; ++row) { for (auto row = 0; row != rows; ++row) {
const auto top = int(std::round(row * sizeh)); const auto top = int(base::SafeRound(row * sizeh));
const auto height = int(std::round( const auto height = int(base::SafeRound(
row * sizeh + sizeh - skip)) - top; row * sizeh + sizeh - skip)) - top;
auto &geometry = sizes[index]; auto &geometry = sizes[index];
geometry.columns = { geometry.columns = {
@ -493,15 +493,15 @@ Viewport::Layout Viewport::countWide(int outerWidth, int outerHeight) const {
const auto rows = slices; const auto rows = slices;
const auto sizeh = (outerHeight + skip) / float64(rows); const auto sizeh = (outerHeight + skip) / float64(rows);
for (auto row = 0; row != rows; ++row) { for (auto row = 0; row != rows; ++row) {
const auto top = int(std::round(row * sizeh)); const auto top = int(base::SafeRound(row * sizeh));
const auto height = int(std::round(row * sizeh + sizeh - skip)) const auto height = int(
- top; base::SafeRound(row * sizeh + sizeh - skip)) - top;
const auto columns = int(std::round((count - index) const auto columns = int(base::SafeRound((count - index)
/ float64(rows - row))); / float64(rows - row)));
const auto sizew = (outerWidth + skip) / float64(columns); const auto sizew = (outerWidth + skip) / float64(columns);
for (auto column = 0; column != columns; ++column) { for (auto column = 0; column != columns; ++column) {
const auto left = int(std::round(column * sizew)); const auto left = int(base::SafeRound(column * sizew));
const auto width = int(std::round( const auto width = int(base::SafeRound(
column * sizew + sizew - skip)) - left; column * sizew + sizew - skip)) - left;
auto &geometry = sizes[index]; auto &geometry = sizes[index];
geometry.rows = { geometry.rows = {

View file

@ -242,7 +242,7 @@ vec4 background() {
QSize outer, QSize outer,
float factor) { float factor) {
factor *= kBlurTextureSizeFactor; 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); const auto scaled = unscaled.scaled(area, Qt::KeepAspectRatio);
return (scaled.width() > unscaled.width() return (scaled.width() > unscaled.width()
|| scaled.height() > unscaled.height()) || scaled.height() > unscaled.height())

View file

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

View file

@ -186,7 +186,7 @@ void EmojiInteractions::startIncoming(
} }
const auto now = crl::now(); const auto now = crl::now();
for (const auto &single : bunch.interactions) { 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) { if (!animations.empty() && animations.back().scheduledAt >= at) {
continue; continue;
} }

View file

@ -68,7 +68,7 @@ QImage EmojiImageLoader::prepare(EmojiPtr emoji) const {
{ -1, 1 }, { -1, 1 },
{ 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 (const auto &shift : diagonal) {
for (auto i = 0; i != corrected; ++i) { for (auto i = 0; i != corrected; ++i) {
p.drawImage(QPoint(delta, delta) + shift * (i + 1), tinted); p.drawImage(QPoint(delta, delta) + shift * (i + 1), tinted);

View file

@ -617,7 +617,7 @@ public:
[[nodiscard]] static bool ThirdColumnByDefault(); [[nodiscard]] static bool ThirdColumnByDefault();
[[nodiscard]] static float64 DefaultDialogsWidthRatio(); [[nodiscard]] static float64 DefaultDialogsWidthRatio();
[[nodiscard]] static qint32 SerializePlaybackSpeed(float64 speed) { [[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) { [[nodiscard]] static float64 DeserializePlaybackSpeed(qint32 speed) {
if (speed < 10) { if (speed < 10) {

View file

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

View file

@ -80,8 +80,9 @@ Storage::Cache::Key GeoPointCacheKey(const GeoPointLocation &location) {
| (uint32(location.height) & 0xFFFFU); | (uint32(location.height) & 0xFFFFU);
return Storage::Cache::Key{ return Storage::Cache::Key{
Data::kGeoPointCacheTag | (uint64(zoomscale) << 32) | widthheight, Data::kGeoPointCacheTag | (uint64(zoomscale) << 32) | widthheight,
(uint64(std::round(std::abs(location.lat + 360.) * 1000000)) << 32) (uint64(base::SafeRound(
| uint64(std::round(std::abs(location.lon + 360.) * 1000000)) 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) const auto angle = Normalized((isLeft ? 180 : 0)
+ (std::atan2(diff.y(), diff.x()) * 180 / M_PI)); + (std::atan2(diff.y(), diff.x()) * 180 / M_PI));
setRotation(shift setRotation(shift
? (std::round(angle / kSnapAngle) * kSnapAngle) // Snap rotation. ? (base::SafeRound(angle / kSnapAngle) * kSnapAngle)
: angle); : angle);
} else { } else {
QGraphicsItem::mouseMoveEvent(event); QGraphicsItem::mouseMoveEvent(event);

View file

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

View file

@ -477,7 +477,8 @@ void ListWidget::scrollToAnimationCallback(
int relativeTo) { int relativeTo) {
if (!attachToId) { if (!attachToId) {
// Animated scroll to bottom. // 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() _delegate->listScrollTo(height()
- (_visibleBottom - _visibleTop) - (_visibleBottom - _visibleTop)
+ current); + current);
@ -488,7 +489,7 @@ void ListWidget::scrollToAnimationCallback(
if (!attachToView) { if (!attachToView) {
_scrollToAnimation.stop(); _scrollToAnimation.stop();
} else { } else {
const auto current = int(std::round(_scrollToAnimation.value( const auto current = int(base::SafeRound(_scrollToAnimation.value(
relativeTo))); relativeTo)));
_delegate->listScrollTo(itemTop(attachToView) + current); _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 // We have to use QFontMetricsF instead of
// FontData::spacew for more precise calculation. // FontData::spacew for more precise calculation.
const auto mf = QFontMetricsF(_st.font->f); const auto mf = QFontMetricsF(_st.font->f);
_spacesCount = std::round( _spacesCount = base::SafeRound(
_sendActionAnimation.widthNoMargins() _sendActionAnimation.widthNoMargins()
/ mf.horizontalAdvance(' ')); / mf.horizontalAdvance(' '));
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -12,8 +12,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/concurrent_timer.h" #include "base/concurrent_timer.h"
#include "core/crash_reports.h" #include "core/crash_reports.h"
#include <cfenv>
namespace Media { namespace Media {
namespace Streaming { namespace Streaming {
namespace { namespace {
@ -71,31 +69,6 @@ static_assert(kDisplaySkipped != kTimeUnknown);
return result; 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 } // namespace
class VideoTrackObject final { class VideoTrackObject final {
@ -713,7 +686,7 @@ TimePoint VideoTrackObject::trackTime() const {
} }
const auto adjust = (result.worldTime - _syncTimePoint.worldTime); const auto adjust = (result.worldTime - _syncTimePoint.worldTime);
const auto adjustSpeed = adjust * _options.speed; const auto adjustSpeed = adjust * _options.speed;
const auto roundAdjustSpeed = SafeRound(adjustSpeed); const auto roundAdjustSpeed = base::SafeRound(adjustSpeed);
const auto timeRoundAdjustSpeed = crl::time(roundAdjustSpeed); const auto timeRoundAdjustSpeed = crl::time(roundAdjustSpeed);
result.trackTime = _syncTimePoint.trackTime + timeRoundAdjustSpeed; result.trackTime = _syncTimePoint.trackTime + timeRoundAdjustSpeed;
return result; return result;
@ -848,7 +821,7 @@ auto VideoTrack::Shared::presentFrame(
} }
const auto trackLeft = position - time.trackTime; const auto trackLeft = position - time.trackTime;
const auto adjustedBySpeed = trackLeft / playbackSpeed; const auto adjustedBySpeed = trackLeft / playbackSpeed;
const auto roundedAdjustedBySpeed = SafeRound(adjustedBySpeed); const auto roundedAdjustedBySpeed = base::SafeRound(adjustedBySpeed);
frame->display = time.worldTime frame->display = time.worldTime
+ addedWorldTimeDelay + addedWorldTimeDelay
+ crl::time(roundedAdjustedBySpeed); + crl::time(roundedAdjustedBySpeed);

View file

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

View file

@ -441,7 +441,7 @@ void OverlayWidget::RendererGL::paintControl(
Assert(meta.icon == &icon); Assert(meta.icon == &icon);
const auto &bg = st::mediaviewControlBg->c; 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 offset = kControlsOffset + (meta.index * kControlValues) / 4;
const auto fgOffset = offset + 2; const auto fgOffset = offset + 2;
const auto bgRect = transformRect(outer); const auto bgRect = transformRect(outer);

View file

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

View file

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

View file

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

View file

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

View file

@ -544,7 +544,9 @@ MTPVector<MTPJSONObjectValue> SessionPrivate::prepareInitParams() {
sliced -= 24 * 3600; sliced -= 24 * 3600;
} }
const auto sign = (sliced < 0) ? -1 : 1; 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>( return MTP_vector<MTPJSONObjectValue>(
1, 1,
MTP_jsonObjectValue( MTP_jsonObjectValue(

View file

@ -229,7 +229,7 @@ struct SimpleFieldState {
QString() QString()
).toDouble(); ).toDouble();
return QString::number( 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 } else if (config.type == FieldType::CardNumber
|| config.type == FieldType::CardCVC) { || config.type == FieldType::CardCVC) {
return QString(parsed).replace( return QString(parsed).replace(

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -329,6 +329,10 @@ void UpdateImageDetails(PreparedFile &file, int previewWidth) {
: image->data; : image->data;
Assert(!preview.isNull()); Assert(!preview.isNull());
file.shownDimensions = PrepareShownDimensions(preview); 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( const auto toWidth = std::min(
previewWidth, previewWidth,
style::ConvertScale(preview.width()) 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. // Try to fill the line with exact number of dash segments.
// UPD Doesn't work so well because it changes when clicking. // UPD Doesn't work so well because it changes when clicking.
//const auto length = till - from; //const auto length = till - from;
//const auto offSegmentsCount = int(std::round( //const auto offSegmentsCount = int(base::SafeRound(
// (length - st->dashOn) / (st->dashOn + st->dashOff))); // (length - st->dashOn) / (st->dashOn + st->dashOff)));
//const auto onSegmentsCount = offSegmentsCount + 1; //const auto onSegmentsCount = offSegmentsCount + 1;
//const auto idealLength = offSegmentsCount * st->dashOff //const auto idealLength = offSegmentsCount * st->dashOff

View file

@ -263,7 +263,7 @@ void AlbumPreview::updateSize() {
} else if (!_sendWay.groupFiles()) { } else if (!_sendWay.groupFiles()) {
return _photosHeight; return _photosHeight;
} else { } else {
return int(std::round(_thumbsHeightAnimation.value( return int(base::SafeRound(_thumbsHeightAnimation.value(
_thumbsHeight))); _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 scaleWidth = to.width() / float64(width);
const auto scaleHeight = to.height() / float64(height); const auto scaleHeight = to.height() / float64(height);
const auto Round = [](float64 value) { const auto Round = [](float64 value) {
return int(std::round(value)); return int(base::SafeRound(value));
}; };
const auto [from, fillBlack] = [&] { const auto [from, fillBlack] = [&] {
if (previewWidth < width && previewHeight < height) { if (previewWidth < width && previewHeight < height) {
@ -474,7 +474,7 @@ void AlbumThumbnail::suggestMove(float64 delta, Fn<void()> callback) {
} }
QRect AlbumThumbnail::countRealGeometry() const { QRect AlbumThumbnail::countRealGeometry() const {
const auto addLeft = int(std::round( const auto addLeft = int(base::SafeRound(
_suggestedMoveAnimation.value(_suggestedMove) * _lastShrinkValue)); _suggestedMoveAnimation.value(_suggestedMove) * _lastShrinkValue));
const auto current = _layout.geometry; const auto current = _layout.geometry;
const auto realTopLeft = current.topLeft() const auto realTopLeft = current.topLeft()

View file

@ -63,7 +63,7 @@ rpl::producer<bool> GroupCallScheduledLeft::late() const {
void GroupCallScheduledLeft::update() { void GroupCallScheduledLeft::update() {
const auto now = crl::now(); const auto now = crl::now();
const auto duration = (_datePrecise - 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); const auto late = (duration < 0) && (left > 0);
_late = late; _late = late;
constexpr auto kDay = 24 * 60 * 60; constexpr auto kDay = 24 * 60 * 60;

View file

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

View file

@ -176,7 +176,7 @@ QPixmap CheckCaches::frame(
auto &frames = framesForStyle(st, displayInactive); auto &frames = framesForStyle(st, displayInactive);
const auto frameCount = int(frames.list.size()); 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); Assert(frameIndex >= 0 && frameIndex < frameCount);
if (!frames.list[frameIndex]) { if (!frames.list[frameIndex]) {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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