* Copyright (c) Huawei Device Co., Ltd. 2024-2025. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef GUI_GRID_HPP
#define GUI_GRID_HPP
#include <bitset>
#include <cstddef>
#include <vector>
#include "position.hpp"
#include "rectangle.hpp"
namespace Gui {
template <size_t Width>
class BinaryGrid : private std::vector<std::bitset<Width>> {
public:
BinaryGrid() = default;
BinaryGrid(BinaryGrid const &other) = default;
BinaryGrid(BinaryGrid &&other) = default;
BinaryGrid &operator=(BinaryGrid const &other) = default;
BinaryGrid &operator=(BinaryGrid &&other) = default;
~BinaryGrid() = default;
explicit constexpr BinaryGrid(size_t height);
[[nodiscard]] bool Test(Position const &position) const;
[[nodiscard]] bool All(Rectangle const &rectangle) const;
[[nodiscard]] bool Any(Rectangle const &rectangle) const;
[[nodiscard]] bool None(Rectangle const &rectangle) const;
void Set(Position const &position, bool value = true);
void Fill(Rectangle const &rectangle, bool value = true);
void Unset(Position const &position);
void Reset(Rectangle const &rectangle);
private:
static std::bitset<Width> GetRowMask(int x, int width);
};
class IntGrid : private std::vector<std::vector<int>> {
public:
IntGrid() = default;
IntGrid(IntGrid const &other) = default;
IntGrid(IntGrid &&other) = default;
IntGrid &operator=(IntGrid const &other) = default;
IntGrid &operator=(IntGrid &&other) = default;
~IntGrid() = default;
IntGrid(size_t width, size_t height, int def = -1);
[[nodiscard]] int Get(Position const &position) const;
void Set(Position const &position, int value);
};
template <size_t Width>
constexpr BinaryGrid<Width>::BinaryGrid(size_t height) : std::vector<std::bitset<Width>>(height, std::bitset<Width>())
{}
template <size_t Width>
bool BinaryGrid<Width>::Test(Position const &position) const
{
return (*this)[position.y - 1].test(position.x - 1);
}
template <size_t Width>
bool BinaryGrid<Width>::All(Rectangle const &rectangle) const
{
std::bitset<Width> row_mask = BinaryGrid::GetRowMask(rectangle.x, rectangle.width);
for (int i = rectangle.y - 1; i < rectangle.y - 1 + rectangle.height; ++i) {
if (!((*this)[i] & row_mask).all()) {
return false;
}
}
return true;
}
template <size_t Width>
bool BinaryGrid<Width>::Any(Rectangle const &rectangle) const
{
std::bitset<Width> row_mask = BinaryGrid::GetRowMask(rectangle.x, rectangle.width);
for (int i = rectangle.y - 1; i < rectangle.y - 1 + rectangle.height; ++i) {
if (((*this)[i] & row_mask).any()) {
return true;
}
}
return false;
}
template <size_t Width>
bool BinaryGrid<Width>::None(Rectangle const &rectangle) const
{
return !this->Any(rectangle);
}
template <size_t Width>
void BinaryGrid<Width>::Set(Position const &position, bool value)
{
(*this)[position.y - 1].set(position.x - 1, value);
}
template <size_t Width>
void BinaryGrid<Width>::Fill(Rectangle const &rectangle, bool value)
{
std::bitset<Width> row_mask = BinaryGrid::GetRowMask(rectangle.x, rectangle.width);
if (value) {
for (int i = rectangle.y - 1; i < rectangle.y - 1 + rectangle.height; ++i) {
(*this)[i] |= row_mask;
}
}
if (!value) {
row_mask.flip();
for (int i = rectangle.y - 1; i < rectangle.y - 1 + rectangle.height; ++i) {
(*this)[i] &= row_mask;
}
}
}
template <size_t Width>
void BinaryGrid<Width>::Unset(Position const &position)
{
this->fill(position, false);
}
template <size_t Width>
void BinaryGrid<Width>::Reset(Rectangle const &rectangle)
{
this->Fill(rectangle, false);
}
template <size_t Width>
std::bitset<Width> BinaryGrid<Width>::GetRowMask(int x, int width)
{
return ((0b1 << width) - 0b1) << (x - 1);
}
}
#endif