1 #include "lua/internal.hpp"
2 #include "library/framebuffer.hpp"
3 #include "library/minmax.hpp"
7 int _dx
[8] = {-1,-1, 0, 1, 1, 1, 0,-1};
8 int _dy
[8] = { 0, 1, 1, 1, 0,-1,-1,-1};
9 int _dxn
[8] = { 0, 0, 1, 1, 0, 0,-1,-1};
10 int _dyn
[8] = { 1, 1, 0, 0,-1,-1, 0, 0};
11 int _dxp
[8] = { 0, 1, 1, 0, 0,-1,-1, 0};
12 int _dyp
[8] = { 1, 0, 0,-1,-1, 0, 0, 1};
13 struct render_object_arrow
: public render_object
15 render_object_arrow(int32_t _x
, int32_t _y
, uint32_t _length
, uint32_t _width
,
16 uint32_t _headwidth
, uint32_t _headthickness
, int _direction
, bool _fill
,
17 premultiplied_color _color
) throw()
18 : x(_x
), y(_y
), length(_length
), width(_width
), headwidth(_headwidth
),
19 headthickness(_headthickness
), direction(_direction
), fill(_fill
), color(_color
) {}
20 ~render_object_arrow() throw() {}
21 template<bool X
> void op(struct framebuffer
<X
>& scr
) throw()
23 color
.set_palette(scr
);
24 uint32_t originx
= scr
.get_origin_x();
25 uint32_t originy
= scr
.get_origin_y();
26 auto orange
= offsetrange();
27 for(int32_t o
= orange
.first
; o
< orange
.second
; o
++) {
29 bpx
= x
+ originx
+ ((o
< 0) ? _dxn
[direction
& 7] : _dxp
[direction
& 7]) * o
;
30 bpy
= y
+ originy
+ ((o
< 0) ? _dyn
[direction
& 7] : _dyp
[direction
& 7]) * o
;
31 int dx
= _dx
[direction
& 7];
32 int dy
= _dy
[direction
& 7];
33 auto drange
= drawrange(o
);
34 for(unsigned d
= drange
.first
; d
< drange
.second
; d
++) {
35 int32_t xc
= bpx
+ dx
* d
;
36 int32_t yc
= bpy
+ dy
* d
;
37 if(xc
< 0 || xc
>= scr
.get_width())
39 if(yc
< 0 || yc
>= scr
.get_height())
41 color
.apply(scr
.rowptr(yc
)[xc
]);
45 void operator()(struct framebuffer
<true>& scr
) throw() { op(scr
); }
46 void operator()(struct framebuffer
<false>& scr
) throw() { op(scr
); }
47 void clone(render_queue
& q
) const throw(std::bad_alloc
) { q
.clone_helper(this); }
49 std::pair
<int32_t, int32_t> offsetrange()
51 int32_t cmin
= -static_cast<int32_t>(width
/ 2);
52 int32_t cmax
= static_cast<int32_t>((width
+ 1) / 2);
53 int32_t hmin
= -static_cast<int32_t>(headwidth
/ 2);
54 int32_t hmax
= static_cast<int32_t>((headwidth
+ 1) / 2);
55 return std::make_pair(min(cmin
, hmin
), max(cmax
, hmax
));
57 std::pair
<int32_t, int32_t> drawrange(int32_t offset
)
59 int32_t cmin
= -static_cast<int32_t>(width
/ 2);
60 int32_t cmax
= static_cast<int32_t>((width
+ 1) / 2);
61 int32_t hmin
= -static_cast<int32_t>(headwidth
/ 2);
62 int32_t hmax
= static_cast<int32_t>((headwidth
+ 1) / 2);
63 bool in_center
= (offset
>= cmin
&& offset
< cmax
);
64 bool in_head
= (offset
>= hmin
&& offset
< hmax
);
65 int32_t minc
= std::abs(offset
); //Works for head&tail.
67 if(in_center
) maxc
= max(maxc
, static_cast<int32_t>(length
));
71 int32_t fedge
= hmax
- minc
;
72 maxc
= max(maxc
, minc
+ fedge
/ 2 + 1);
74 maxc
= max(maxc
, hmax
);
76 maxc
= max(maxc
, static_cast<int32_t>(minc
+ headthickness
));
78 return std::make_pair(minc
, maxc
);
85 uint32_t headthickness
;
88 premultiplied_color color
;
91 function_ptr_luafun
gui_box(lua_func_misc
, "gui.arrow", [](lua_state
& L
, const std::string
& fname
) -> int {
94 int32_t x
= L
.get_numeric_argument
<int32_t>(1, fname
.c_str());
95 int32_t y
= L
.get_numeric_argument
<int32_t>(2, fname
.c_str());
96 uint32_t length
= L
.get_numeric_argument
<int32_t>(3, fname
.c_str());
97 uint32_t headwidth
= L
.get_numeric_argument
<int32_t>(4, fname
.c_str());
98 int direction
= L
.get_numeric_argument
<int>(5, fname
.c_str());
99 int64_t color
= 0xFFFFFFU
;
101 if(L
.type(6) == LUA_TBOOLEAN
&& L
.toboolean(6))
103 L
.get_numeric_argument
<int64_t>(7, color
, fname
.c_str());
105 L
.get_numeric_argument
<uint32_t>(8, width
, fname
.c_str());
106 uint32_t headthickness
= width
;
107 L
.get_numeric_argument
<uint32_t>(9, headthickness
, fname
.c_str());
108 lua_render_ctx
->queue
->create_add
<render_object_arrow
>(x
, y
, length
, width
, headwidth
, headthickness
,
109 direction
, fill
, color
);