~aleteoryx/muditaos

muditaos/module-gui/gui/core/Context.hpp -rw-r--r-- 3.4 KiB
a405cad6Aleteoryx trim readme 6 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/blob/master/LICENSE.md

/*
 * Context.hpp
 *
 *  Created on: 6 maj 2019
 *      Author: robert
 */

#ifndef GUI_CORE_CONTEXT_HPP_
#define GUI_CORE_CONTEXT_HPP_

#include "BoundingBox.hpp"

#include "module-gui/gui/Common.hpp"

#include <cstdint>
#include <deque>
#include <iostream>
#include <memory>
#include <string>

namespace gui
{
    class Context
    {
        static constexpr std::uint8_t clearColor = 15;

      public:
        Context() = default;
        Context(std::uint16_t width, std::uint16_t height);

        /**
         * @brief Creates new context using provided coordinates. If there is no common part Context filled with
         * clearColor is returned. The size of the returned context is defined by parameters, so it may represent
         * area outside the original context.
         */
        Context get(std::int16_t gx, std::int16_t gy, std::uint16_t width, std::uint16_t height) const;
        /**
         * @brief Pastes provided context into current one. Overlapping content will be inserted into current context.
         */
        void insert(std::int16_t ix, std::int16_t iy, const Context &context);
        /**
         * @brief Pastes provided context into current one. Overlapping content will be inserted into current context.
         */
        void insertArea(std::int16_t ix,
                        std::int16_t iy,
                        std::int16_t iareaX,
                        std::int16_t iareaY,
                        std::int16_t iareaW,
                        std::int16_t iareaH,
                        const Context &context);

        /**
         * @brief Calculate regions of difference between contexts. Each bounding box covers the whole width of the
         * context. They are disjoint and sorted by y coordinate. The contexts has to have the same sizes.
         */
        static std::deque<BoundingBox> linesDiffs(const gui::Context &ctx1, const gui::Context &ctx2);

        /**
         * @brief Fills whole context with specified colour;
         */
        void fill(std::uint8_t colour);
        /**
         * @brief returns pointer to context's data;
         */
        inline const std::uint8_t *getData() const
        {
            return data.get();
        }
        inline std::uint8_t *getData()
        {
            return data.get();
        }
        inline std::uint16_t getW() const
        {
            return w;
        }
        inline std::uint16_t getH() const
        {
            return h;
        }
        inline BoundingBox getBoundingBox() const
        {
            return {0, 0, w, h};
        }

        inline std::uint8_t getPixel(const Point point, uint8_t defaultColor = clearColor) const
        {
            return hasPixel(point) ? data[point.y * w + point.x] : defaultColor;
        }

        inline bool hasPixel(const Point point) const noexcept
        {
            return (point.x >= 0 && static_cast<std::uint32_t>(point.x) < w) &&
                   (point.y >= 0 && static_cast<std::uint32_t>(point.y) < h);
        }

        friend std::ostream &operator<<(std::ostream &out, const Context &c);

        std::string toAsciiScaled(std::uint16_t scale = 15) const;

      private:
        std::uint16_t w = 0;
        std::uint16_t h = 0;
        std::unique_ptr<uint8_t[]> data;
    };

} /* namespace gui */

#endif /* GUI_CORE_CONTEXT_HPP_ */