Compare commits
2 Commits
14c8280fc0
...
8e96588829
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e96588829 | ||
|
|
d03600fd54 |
@ -9,6 +9,8 @@
|
|||||||
#define PERIPHERALS_UTILITY_HPP_
|
#define PERIPHERALS_UTILITY_HPP_
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace Peripherals
|
namespace Peripherals
|
||||||
{
|
{
|
||||||
@ -54,6 +56,17 @@ T ByteToTypeLE(const std::uint8_t a[N])
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr T zeroInitialized()
|
||||||
|
{
|
||||||
|
static_assert(std::is_trivially_default_constructible<T>::value, "Struct is not trivially default constructible.");
|
||||||
|
|
||||||
|
T t;
|
||||||
|
std::memset(&t, 0, sizeof(T));
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
}// namespace Peripherals
|
}// namespace Peripherals
|
||||||
|
|
||||||
#endif /* PERIPHERALS_UTILITY_HPP_ */
|
#endif /* PERIPHERALS_UTILITY_HPP_ */
|
||||||
|
|||||||
@ -17,7 +17,8 @@ add_executable(tests
|
|||||||
button.cpp
|
button.cpp
|
||||||
rand.cpp
|
rand.cpp
|
||||||
fixedpoint.cpp
|
fixedpoint.cpp
|
||||||
pixelbuffer.cpp)
|
pixelbuffer.cpp
|
||||||
|
pixelbuffer_effects.cpp)
|
||||||
|
|
||||||
target_link_libraries(tests
|
target_link_libraries(tests
|
||||||
PUBLIC
|
PUBLIC
|
||||||
|
|||||||
@ -248,3 +248,17 @@ TEST_CASE("Pixelbuffer cuts off fonts when required.", TEST_WIDGET)
|
|||||||
|
|
||||||
REQUIRE(pb.data() == etalon);
|
REQUIRE(pb.data() == etalon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Pixelbuffer::View provides the correct offsets.", TEST_WIDGET)
|
||||||
|
{
|
||||||
|
PixelBuffer pb;
|
||||||
|
const auto view = pb.view<2, 2>({1, 1});
|
||||||
|
|
||||||
|
const auto* ptr_pb = &pb.at(2, 2);
|
||||||
|
const auto* ptr_view = &view.at(1, 1);
|
||||||
|
|
||||||
|
REQUIRE(ptr_pb == ptr_view);
|
||||||
|
|
||||||
|
REQUIRE(decltype(view)::width == 2);
|
||||||
|
REQUIRE(decltype(view)::height == 2);
|
||||||
|
}
|
||||||
|
|||||||
15
Tests/pixelbuffer_effects.cpp
Normal file
15
Tests/pixelbuffer_effects.cpp
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// Created by erki on 22.05.21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "utility_fonts_5x7.hpp"
|
||||||
|
#include "utility_pixelbuffer.hpp"
|
||||||
|
#include "utility_pixelbuffer_effects.hpp"
|
||||||
|
|
||||||
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
|
#define TEST_WIDGET "[utility],[pixelbuffer_effects]"
|
||||||
|
|
||||||
|
using PixelBuffer = Utility::PixelBuffer<10, 15>;
|
||||||
|
using compare_array = std::array<std::uint8_t, 10 * 15>;
|
||||||
|
using Font = Utility::Font5x7;
|
||||||
@ -226,6 +226,63 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<std::size_t VW, std::size_t VH, typename TP>
|
||||||
|
struct View
|
||||||
|
{
|
||||||
|
constexpr static std::size_t width = VW;
|
||||||
|
constexpr static std::size_t height = VH;
|
||||||
|
using parent_type = std::decay_t<TP>;
|
||||||
|
using value = typename parent_type::value;
|
||||||
|
using coordinates = typename parent_type::coordinates;
|
||||||
|
|
||||||
|
static_assert(width <= parent_type::width, "Parent type width is smaller than view's width.");
|
||||||
|
static_assert(height <= parent_type::height, "Parent type height is smaller than view's height.");
|
||||||
|
|
||||||
|
coordinates offset;
|
||||||
|
parent_type& parent;
|
||||||
|
|
||||||
|
View() = delete;
|
||||||
|
explicit View(const coordinates& offset, parent_type& buffer)
|
||||||
|
: offset(offset), parent(buffer)
|
||||||
|
{}
|
||||||
|
|
||||||
|
constexpr value& at(const std::size_t& x, const std::size_t& y)
|
||||||
|
{
|
||||||
|
return parent.at(parent.x_(offset) + x, parent.y_(offset) + y);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const value& at(const std::size_t& x, const std::size_t& y) const
|
||||||
|
{
|
||||||
|
return parent.at(parent.x_(offset) + x, parent.y_(offset) + y);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr value& at(const coordinates& c)
|
||||||
|
{
|
||||||
|
return parent.at(parent.x_(offset) + parent.x_(c), parent.y_(offset) + parent.y_(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const value& at(const coordinates& c) const
|
||||||
|
{
|
||||||
|
return parent.at(parent.x_(offset) + parent.x_(c), parent.y_(offset) + parent.y_(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t VW_, std::size_t VH_>
|
||||||
|
auto view(const coordinates& offset)
|
||||||
|
{
|
||||||
|
return View<VW_, VH_, parent_type>(offset, parent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<std::size_t VW, std::size_t VH, typename TP>
|
||||||
|
friend struct View;
|
||||||
|
|
||||||
|
template<std::size_t VW, std::size_t VH>
|
||||||
|
auto view(const coordinates& offset) -> View<VW, VH, decltype(*this)>
|
||||||
|
{
|
||||||
|
using rtype = View<VW, VH, decltype(*this)>;
|
||||||
|
return rtype(offset, *this);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
container data_;
|
container data_;
|
||||||
|
|
||||||
|
|||||||
118
Utility/Inc/utility_pixelbuffer_effects.hpp
Normal file
118
Utility/Inc/utility_pixelbuffer_effects.hpp
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
//
|
||||||
|
// Created by erki on 16.05.21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SKULLC_UTILITY_PIXELBUFFER_EFFECTS_HPP
|
||||||
|
#define SKULLC_UTILITY_PIXELBUFFER_EFFECTS_HPP
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string_view>
|
||||||
|
#include <tuple>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace Utility
|
||||||
|
{
|
||||||
|
namespace Effects
|
||||||
|
{
|
||||||
|
|
||||||
|
template<std::size_t W, std::size_t H, typename TP, typename F>
|
||||||
|
struct TextScroll
|
||||||
|
{
|
||||||
|
static constexpr std::size_t width = W;
|
||||||
|
static constexpr std::size_t height = H;
|
||||||
|
using parent_type = std::decay_t<TP>;
|
||||||
|
using font = std::decay_t<F>;
|
||||||
|
|
||||||
|
static constexpr std::size_t chars_per_view = width / (font::width + 1);
|
||||||
|
|
||||||
|
parent_type& parent;
|
||||||
|
std::string_view string;
|
||||||
|
typename parent_type::value color;
|
||||||
|
typename parent_type::value background;
|
||||||
|
|
||||||
|
TextScroll() = delete;
|
||||||
|
TextScroll(parent_type& parent, const typename parent_type::value& color, const typename parent_type::value& background)
|
||||||
|
: parent(parent), color(color), background(background)
|
||||||
|
{}
|
||||||
|
|
||||||
|
TextScroll(const TextScroll&) = delete;
|
||||||
|
TextScroll(TextScroll&&) = delete;
|
||||||
|
TextScroll& operator=(const TextScroll&) = delete;
|
||||||
|
TextScroll& operator=(TextScroll&&) = delete;
|
||||||
|
|
||||||
|
void setText(const std::string_view& text)
|
||||||
|
{
|
||||||
|
string = text;
|
||||||
|
current_begin = text.cbegin();
|
||||||
|
toBuffer_(current_begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void scrollCharacter(const std::size_t& step = 1)
|
||||||
|
{
|
||||||
|
if (string.size() <= chars_per_view)
|
||||||
|
return;
|
||||||
|
|
||||||
|
current_begin++;
|
||||||
|
if (current_begin == string.cend())
|
||||||
|
current_begin = string.cbegin();
|
||||||
|
|
||||||
|
toBuffer_(current_begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto view()
|
||||||
|
{
|
||||||
|
return parent.template view<width, height>({0, 0});
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string_view::const_iterator current_begin;
|
||||||
|
|
||||||
|
void toBuffer_(std::string_view::const_iterator begin)
|
||||||
|
{
|
||||||
|
std::uint32_t x = 0;
|
||||||
|
const std::uint32_t y = 0;
|
||||||
|
|
||||||
|
auto iterate_begin = [&begin, this]() {
|
||||||
|
begin++;
|
||||||
|
if (string.size() > chars_per_view && begin == string.cend())
|
||||||
|
begin = string.cbegin();
|
||||||
|
};
|
||||||
|
|
||||||
|
auto is_over = [this](const std::size_t& ci, const std::string_view::const_iterator& it) -> bool {
|
||||||
|
if (string.size() <= chars_per_view)
|
||||||
|
return it != string.cend();
|
||||||
|
else
|
||||||
|
return ci < chars_per_view;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (std::size_t ci = 0; is_over(ci, begin); ci++, iterate_begin())
|
||||||
|
{
|
||||||
|
const auto [c_start, c_stop] = font::getCharacterBytes(*begin);
|
||||||
|
|
||||||
|
for (auto it = c_start; it != c_stop; it++, x++)
|
||||||
|
{
|
||||||
|
const std::uint8_t& column_byte = *it;
|
||||||
|
|
||||||
|
if (x >= width)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (std::uint32_t i = 0; i < font::height && i + y < height; i++)
|
||||||
|
{
|
||||||
|
parent.at(x, y + i) = column_byte & (1 << i) ? color : background;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
x++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<std::size_t W, std::size_t H>
|
||||||
|
class ScreenScroll
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
}// namespace Effects
|
||||||
|
}// namespace Utility
|
||||||
|
|
||||||
|
#endif//SKULLC_UTILITY_PIXELBUFFER_EFFECTS_HPP
|
||||||
Loading…
x
Reference in New Issue
Block a user