blob: 6cb55cab47472654580f322e7c1f91d79e715460 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include <algorithm>
#include <cmath>
#include <limits>
#include <ostream>
#include <string>
#include "impeller/geometry/scalar.h"
namespace impeller {
template <class T>
struct TSize {
using Type = T;
Type width = {};
Type height = {};
constexpr TSize() {}
constexpr TSize(Type width, Type height) : width(width), height(height) {}
template <class U>
explicit constexpr TSize(const TSize<U>& other)
: TSize(static_cast<Type>(other.width), static_cast<Type>(other.height)) {
}
static constexpr TSize MakeWH(Type width, Type height) {
return TSize{width, height};
}
static constexpr TSize Infinite() {
return TSize{std::numeric_limits<Type>::max(),
std::numeric_limits<Type>::max()};
}
constexpr TSize operator*(Scalar scale) const {
return {width * scale, height * scale};
}
constexpr TSize operator/(Scalar scale) const {
return {static_cast<Scalar>(width) / scale,
static_cast<Scalar>(height) / scale};
}
constexpr TSize operator/(const TSize& s) const {
return {width / s.width, height / s.height};
}
constexpr bool operator==(const TSize& s) const {
return s.width == width && s.height == height;
}
constexpr bool operator!=(const TSize& s) const {
return s.width != width || s.height != height;
}
constexpr TSize operator+(const TSize& s) const {
return {width + s.width, height + s.height};
}
constexpr TSize operator-(const TSize& s) const {
return {width - s.width, height - s.height};
}
constexpr TSize Min(const TSize& o) const {
return {
std::min(width, o.width),
std::min(height, o.height),
};
}
constexpr TSize Max(const TSize& o) const {
return {
std::max(width, o.width),
std::max(height, o.height),
};
}
constexpr Type Area() const { return width * height; }
constexpr bool IsPositive() const { return width > 0 && height > 0; }
constexpr bool IsNegative() const { return width < 0 || height < 0; }
constexpr bool IsZero() const { return width == 0 || height == 0; }
constexpr bool IsEmpty() const { return IsNegative() || IsZero(); }
template <class U>
static constexpr TSize Ceil(const TSize<U>& other) {
return TSize{static_cast<Type>(std::ceil(other.width)),
static_cast<Type>(std::ceil(other.height))};
}
constexpr size_t MipCount() const {
if (!IsPositive()) {
return 1u;
}
return std::max(ceil(log2(width)), ceil(log2(height)));
}
};
using Size = TSize<Scalar>;
using ISize = TSize<int64_t>;
static_assert(sizeof(Size) == 2 * sizeof(Scalar));
} // namespace impeller
namespace std {
template <class T>
inline std::ostream& operator<<(std::ostream& out,
const impeller::TSize<T>& s) {
out << "(" << s.width << ", " << s.height << ")";
return out;
}
} // namespace std