genode/repos/demo/src/app/scout/refracted_icon.h

123 lines
3.3 KiB
C++

/*
* \brief Interface of refracted icon
* \date 2005-10-24
* \author Norman Feske <norman.feske@genode-labs.com>
*/
/*
* Copyright (C) 2005-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _REFRACTED_ICON_H_
#define _REFRACTED_ICON_H_
#include <scout_gfx/random.h>
#include "widgets.h"
namespace Scout { template <typename PT, typename DT> class Refracted_icon; }
/**
* \param PT pixel type (must be Pixel_rgba compatible)
* \param DT distortion map entry type
*/
template <typename PT, typename DT>
class Scout::Refracted_icon : public Element
{
private:
bool _detailed = true; /* level of detail */
PT *_backbuf = nullptr; /* pixel back buffer */
int _filter_backbuf = 0; /* backbuf filtering flag */
DT *_distmap = nullptr; /* distortion table */
int _distmap_w = 0, _distmap_h = 0; /* size of distmap */
PT *_fg = nullptr; /* foreground pixels */
unsigned char *_fg_alpha = nullptr; /* foreground alpha values */
public:
void detailed(bool detailed) { _detailed = detailed; }
/**
* Define pixel back buffer for the icon. This buffer is used for the
* draw operation. It should have the same number of pixels as the
* distortion map.
*/
void backbuf(PT *backbuf, int filter_backbuf = 0)
{
_backbuf = backbuf;
_filter_backbuf = filter_backbuf;
}
/**
* Scratch refraction map
*/
void scratch(int jitter)
{
PT ref_color = _fg[0];
for (int j = 0; j < _distmap_h; j++) for (int i = 0; i < _distmap_w; i++) {
int fg_offset = (j>>1)*(_distmap_w>>1) + (i>>1);
int dr = _fg[fg_offset].r() - ref_color.r();
int dg = _fg[fg_offset].g() - ref_color.g();
int db = _fg[fg_offset].b() - ref_color.b();
if (dr < 0) dr = -dr;
if (dg < 0) dg = -dg;
if (db < 0) db = -db;
static const int limit = 20;
if (dr > limit || dg > limit || db > limit) continue;
int dx, dy;
do {
using Scout::random;
dx = jitter ? ((random()%jitter) - (jitter>>1)) : 0;
dy = jitter ? ((random()%jitter) - (jitter>>1)) : 0;
} while ((dx < -i) || (dx > _distmap_w - 2 - i)
|| (dy < -j) || (dy > _distmap_h - 2 - j));
_distmap[j*_distmap_w + i] += dy*_distmap_w + dx;
}
}
/**
* Define distortion map for the icon
*/
void distmap(DT *distmap, int distmap_w, int distmap_h)
{
_distmap = distmap;
_distmap_w = distmap_w;
_distmap_h = distmap_h;
}
/**
* Define foreground pixels
*/
void foreground(PT *fg, unsigned char *fg_alpha)
{
_fg = fg;
_fg_alpha = fg_alpha;
}
void draw(Canvas_base &canvas, Point abs_position) override
{
Scout::Refracted_icon_painter::Distmap<short>
distmap(_distmap, Area(_distmap_w, _distmap_h));
Texture<PT> tmp(_backbuf, 0, Area(_distmap_w, _distmap_h));
Texture<PT> fg(_fg, _fg_alpha, Area(_distmap_w/2, _distmap_h/2));
canvas.draw_refracted_icon(_position + abs_position, distmap, tmp, fg,
_detailed, _filter_backbuf);
}
};
#endif /* _REFRACTED_H_ */