/* * \brief Interface of refracted icon * \date 2005-10-24 * \author Norman Feske */ /* * 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 #include "widgets.h" namespace Scout { template class Refracted_icon; } /** * \param PT pixel type (must be Pixel_rgba compatible) * \param DT distortion map entry type */ template 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)); DT &entry = _distmap[j*_distmap_w + i]; entry = (DT)(entry + 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 distmap(_distmap, Area(_distmap_w, _distmap_h)); Texture tmp(_backbuf, 0, Area(_distmap_w, _distmap_h)); Texture 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_ */