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
|
#pragma once
#include "rect2d.hpp"
#include "../std/list.hpp"
#include "../std/map.hpp"
#include "../std/function.hpp"
#include "../std/queue.hpp"
namespace m2
{
template <typename pair_t>
struct first_less
{
bool operator()(pair_t const & first, pair_t const & second)
{
return first.first < second.first;
}
};
/// The simplest row-by-row packer.
/// When there is no free room all the packing
/// rect is cleared and the process is started again.
class Packer
{
public:
typedef function<void()> overflowFn;
typedef priority_queue<pair<size_t, overflowFn>, vector<pair<size_t, overflowFn> >, first_less<pair<size_t, overflowFn> > > overflowFns;
typedef uint32_t handle_t;
typedef std::pair<bool, m2::RectU> find_result_t;
private:
unsigned m_currentX;
unsigned m_currentY;
unsigned m_yStep;
unsigned m_width;
unsigned m_height;
overflowFns m_overflowFns;
handle_t m_currentHandle;
typedef map<handle_t, m2::RectU> rects_t;
rects_t m_rects;
void callOverflowFns();
uint32_t m_maxHandle;
uint32_t m_invalidHandle;
public:
Packer();
/// create a packer on a rectangular area of (0, 0, width, height) dimensions
Packer(unsigned width, unsigned height, uint32_t maxHandle = 0xFFFF - 1);
/// reset the state of the packer
void reset();
/// add overflow handler.
/// @param priority handlers with higher priority value are called first.
void addOverflowFn(overflowFn fn, int priority);
/// pack the rect with dimensions width X height on a free area.
/// when there is no free area - find it somehow(depending on a packer implementation,
/// the simplest one will just clear the whole rect and start the packing process again).
handle_t pack(unsigned width, unsigned height);
/// Does we have room to pack another rectangle?
bool hasRoom(unsigned width, unsigned height) const;
/// Does we have room to pack a sequence of rectangles?
bool hasRoom(m2::PointU const * sizes, size_t cnt) const;
/// is the handle present on the texture.
bool isPacked(handle_t handle);
/// find the packed area by the handle.
find_result_t find(handle_t handle) const;
/// remove the handle from the list of active handles.
void remove(handle_t handle);
/// get an invalid handle
uint32_t invalidHandle() const;
};
}
|