-
Notifications
You must be signed in to change notification settings - Fork 1
/
cairowidget.cpp
91 lines (68 loc) · 2.01 KB
/
cairowidget.cpp
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
#include "cairo/cairo.h"
#include "FL/fl_draw.H"
#include <cstdint>
#include <execution>
#include "shuffler.hpp"
#include "cairowidget.hpp"
struct CairoWidget::S
{
static inline std::size_t size_;
static inline unsigned char* data_;
};
//////////////////////////////////////////////////////////////////////////////
CairoWidget::CairoWidget(int const x, int const y, int const w, int const h,
const char* const l) :
Fl_Widget(x, y, w, h, l),
df_{[](auto, auto, auto) noexcept {}},
if_{[](auto const cr, auto, auto) noexcept
{
cairo_set_line_width(cr, 1.);
cairo_translate(cr, .5, .5);
}
}
{
}
//////////////////////////////////////////////////////////////////////////////
CairoWidget::~CairoWidget() { cairo_destroy(cr_); }
//////////////////////////////////////////////////////////////////////////////
void CairoWidget::draw()
{
auto d(S::data_);
auto const w(this->w()), h(this->h());
{
auto cr(cr_);
if ((w != w_) || (h != h_) || (d != d_))
{
w_ = w; h_ = h;
//
auto const stride(cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, w));
{
auto const size(h * std::size_t(stride));
if (pixels_ = size / 4; S::size_ < size)
{
delete [] d; S::data_ = d = new unsigned char[S::size_ = size];
}
}
d_ = d; // multiple instances
//
cairo_destroy(cr);
auto const srf(cairo_image_surface_create_for_data(
d, CAIRO_FORMAT_RGB24, w, h, stride));
cr_ = cr = cairo_create(srf);
cairo_surface_destroy(srf);
//
if_(cr, w, h);
}
//
cairo_save(cr);
df_(cr, w, h);
cairo_restore(cr);
}
//
auto const src(reinterpret_cast<std::uint32_t*>(d));
// ARGB (native), RGB are at indices (2, 1, 0) -> RGBx conversion
// le: (2, 1, 0) -> (0, 1, 2); be: (2, 1, 0) -> (3, 2, 1)
std::transform(std::execution::unseq, src, src + pixels_, src,
(std::uint32_t(&)(std::uint32_t))(shuffler::shuffle<2, 1, 0>));
fl_draw_image(d, x(), y(), w, h, 4);
}