Pixelbuffer view() and scrolling text effect
This commit is contained in:
parent
14c8280fc0
commit
d03600fd54
@ -17,7 +17,8 @@ add_executable(tests
|
||||
button.cpp
|
||||
rand.cpp
|
||||
fixedpoint.cpp
|
||||
pixelbuffer.cpp)
|
||||
pixelbuffer.cpp
|
||||
pixelbuffer_effects.cpp)
|
||||
|
||||
target_link_libraries(tests
|
||||
PUBLIC
|
||||
|
||||
@ -248,3 +248,17 @@ TEST_CASE("Pixelbuffer cuts off fonts when required.", TEST_WIDGET)
|
||||
|
||||
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:
|
||||
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