#include "ui/base/resource/resource_scale_factor.h"
#include <algorithm>
#include <array>
#include <cmath>
#include <iterator>
#include <limits>
#include <memory>
#include <vector>
#include "base/check.h"
#include "base/check_op.h"
#include "base/containers/contains.h"
namespace ui {
namespace {
std::vector<ResourceScaleFactor>* g_supported_resource_scale_factors = nullptr;
constexpr auto kResourceScaleFactorScales = std::to_array<float>({
1.0f,
1.0f,
2.0f,
3.0f,
});
static_assert(NUM_SCALE_FACTORS == std::size(kResourceScaleFactorScales),
"kResourceScaleFactorScales has incorrect size");
const float kFallbackToSmallerScaleDiff = 0.20f;
}
float GetScaleForResourceScaleFactor(ResourceScaleFactor scale_factor) {
return kResourceScaleFactorScales[scale_factor];
}
void SetSupportedResourceScaleFactors(
const std::vector<ResourceScaleFactor>& scale_factors) {
CHECK(!scale_factors.empty());
if (g_supported_resource_scale_factors != nullptr) {
delete g_supported_resource_scale_factors;
}
g_supported_resource_scale_factors =
new std::vector<ResourceScaleFactor>(scale_factors);
std::sort(g_supported_resource_scale_factors->begin(),
g_supported_resource_scale_factors->end(),
[](ResourceScaleFactor lhs, ResourceScaleFactor rhs) {
return kResourceScaleFactorScales[lhs] <
kResourceScaleFactorScales[rhs];
});
}
const std::vector<ResourceScaleFactor>& GetSupportedResourceScaleFactors() {
CHECK_NE(g_supported_resource_scale_factors, nullptr)
<< "ResourceBundle needs to be initialized.";
return *g_supported_resource_scale_factors;
}
ResourceScaleFactor GetSupportedResourceScaleFactor(float scale) {
CHECK_NE(g_supported_resource_scale_factors, nullptr)
<< "ResourceBundle needs to be initialized.";
ResourceScaleFactor closest_match = k100Percent;
float smallest_diff = std::numeric_limits<float>::max();
for (const auto scale_factor : *g_supported_resource_scale_factors) {
const float diff =
std::abs(kResourceScaleFactorScales[scale_factor] - scale);
if (diff < smallest_diff) {
closest_match = scale_factor;
smallest_diff = diff;
} else {
break;
}
}
CHECK_NE(closest_match, kScaleFactorNone);
return closest_match;
}
ResourceScaleFactor GetSupportedResourceScaleFactorForRescale(float scale) {
CHECK_NE(g_supported_resource_scale_factors, nullptr)
<< "ResourceBundle needs to be initialized.";
for (auto supported_scale : *g_supported_resource_scale_factors) {
if (kResourceScaleFactorScales[supported_scale] +
kFallbackToSmallerScaleDiff >=
scale) {
return supported_scale;
}
}
return GetMaxSupportedResourceScaleFactor();
}
ResourceScaleFactor GetMaxSupportedResourceScaleFactor() {
CHECK_NE(g_supported_resource_scale_factors, nullptr)
<< "ResourceBundle needs to be initialized.";
ResourceScaleFactor max_scale = g_supported_resource_scale_factors->back();
CHECK_NE(max_scale, kScaleFactorNone);
return max_scale;
}
float GetScaleForMaxSupportedResourceScaleFactor() {
return kResourceScaleFactorScales[GetMaxSupportedResourceScaleFactor()];
}
bool IsScaleFactorSupported(ResourceScaleFactor scale_factor) {
CHECK_NE(g_supported_resource_scale_factors, nullptr)
<< "ResourceBundle needs to be initialized.";
return base::Contains(*g_supported_resource_scale_factors, scale_factor);
}
namespace test {
ScopedSetSupportedResourceScaleFactors::ScopedSetSupportedResourceScaleFactors(
const std::vector<ResourceScaleFactor>& new_scale_factors) {
if (g_supported_resource_scale_factors) {
original_scale_factors_ =
std::make_unique<std::vector<ResourceScaleFactor>>(
*g_supported_resource_scale_factors);
}
SetSupportedResourceScaleFactors(new_scale_factors);
}
ScopedSetSupportedResourceScaleFactors::
~ScopedSetSupportedResourceScaleFactors() {
if (original_scale_factors_) {
SetSupportedResourceScaleFactors(*original_scale_factors_);
} else {
delete g_supported_resource_scale_factors;
g_supported_resource_scale_factors = nullptr;
}
}
}
}