genode/repos/demo/src/app/scout/widgets.cc
Norman Feske ca971bbfd8 Move repositories to 'repos/' subdirectory
This patch changes the top-level directory layout as a preparatory
step for improving the tools for managing 3rd-party source codes.
The rationale is described in the issue referenced below.

Issue #1082
2014-05-14 16:08:00 +02:00

207 lines
4.9 KiB
C++

/*
* \brief GUI elements
* \date 2005-10-24
* \author Norman Feske <norman.feske@genode-labs.com>
*/
/*
* Copyright (C) 2005-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <scout/misc_math.h>
#include "widgets.h"
using namespace Scout;
/*************
** Docview **
*************/
void Docview::format_fixed_width(int w)
{
_min_size = Area(0, 0);
if (_cont) {
_cont->format_fixed_width(w - 2*_padx - _right_pad);
_min_size = Area(w, _voffset + _cont->min_size().h());
}
if (_bg)
_bg->geometry(Rect(Point(0, 0), _min_size));
}
void Docview::draw(Canvas_base &canvas, Point abs_position)
{
if (_bg) _bg->draw(canvas, _position + abs_position);
if (_cont) _cont->draw(canvas, _position + abs_position);
}
Element *Docview::find(Point position)
{
if (!Element::find(position)) return 0;
Element *res = _cont ? _cont->find(position - _position) : 0;
return res ? res : this;
}
void Docview::geometry(Rect rect)
{
Element::geometry(rect);
if (_cont)
_cont->geometry(Rect(Point(_padx, _voffset),
Area(_cont->min_size().w(), rect.h() - _voffset)));
}
/***********************
** Horizontal shadow **
***********************/
template <typename PT, int INTENSITY>
void Horizontal_shadow<PT, INTENSITY>::draw(Canvas_base &canvas, Point abs_position)
{
canvas.draw_horizontal_shadow(Rect(abs_position + _position, _size), INTENSITY);
}
/**********
** Icon **
**********/
template <typename PT, int W, int H>
Icon<PT, W, H>::Icon()
{
memset(_pixel, 0, sizeof(_pixel));
memset(_alpha, 0, sizeof(_alpha));
memset(_shadow, 0, sizeof(_shadow));
_icon_alpha = 255;
}
template <typename PT, int W, int H>
void Icon<PT, W, H>::rgba(unsigned char *src, int vshift, int shadow)
{
/* convert rgba values to pixel type and alpha channel */
for (int j = 0; j < H; j++)
for (int i = 0; i < W; i++, src += 4) {
_pixel[j][i].rgba(src[0], src[1], src[2]);
_alpha[j][i] = src[3];
}
/* handle special case of no shadow */
if (shadow == 0) return;
/* generate shadow shape from blurred alpha channel */
for (int j = 1; j < H - 4; j++)
for (int i = 1; i < W - 2; i++) {
int v = 0;
for (int k = -1; k <= 1; k++)
for (int l = -1; l <=1; l++)
v += _alpha[(j + k + H)%H][(i + l + W)%W];
_shadow[j + 3][i] = v>>shadow;
}
/* shift vertically */
if (vshift > 0)
for (int j = H - 1; j >= vshift; j--)
for (int i = 0; i < W; i++) {
_pixel[j][i] = _pixel[j - vshift][i];
_alpha[j][i] = _alpha[j - vshift][i];
}
/* apply shadow to pixels */
PT shcol(0, 0, 0);
for (int j = 0; j < H; j++)
for (int i = 0; i < W; i++) {
_pixel[j][i] = PT::mix(shcol, _pixel[j][i], _alpha[j][i]);
_alpha[j][i] = min(255, _alpha[j][i] + _shadow[j][i]);
}
}
static inline void blur(unsigned char *src, unsigned char *dst, int w, int h)
{
const int kernel = 3;
int scale = (kernel*2 + 1)*(kernel*2 + 1);
scale = (scale*210)>>8;
for (int j = kernel; j < h - kernel; j++)
for (int i = kernel; i < w - kernel; i++) {
int v = 0;
for (int k = -kernel; k <= kernel; k++)
for (int l = -kernel; l <= kernel; l++)
v += src[w*(j + k) + (i + l)];
dst[w*j + i] = min(v/scale, 255);
}
}
template <typename PT, int W, int H>
void Icon<PT, W, H>::glow(unsigned char *src, Color c)
{
/* extract shape from alpha channel of rgba source image */
for (int j = 0; j < H; j++)
for (int i = 0; i < W; i++, src += 4)
_alpha[j][i] = src[3] ? 255 : 0;
for (int i = 0; i < 2; i++) {
blur(_alpha[0], _shadow[0], W, H);
blur(_shadow[0], _alpha[0], W, H);
}
/* assign pixels and alpha */
PT s(c.r, c.g, c.b);
for (int j = 0; j < H; j++)
for (int i = 0; i < W; i++, src += 4)
_pixel[j][i] = s;
}
template <typename PT, int W, int H>
void Icon<PT, W, H>::draw(Canvas_base &canvas, Point abs_position)
{
Texture<PT> texture(_pixel[0], _alpha[0], Area(W, H));
canvas.draw_icon(Rect(abs_position + _position, _size), texture, _icon_alpha);
}
template <typename PT, int W, int H>
Element *Icon<PT, W, H>::find(Point position)
{
if (!Element::find(position)) return 0;
position = position - _position;
/* check icon boundaries (the height is flexible) */
if ((position.x() < 0) || (position.x() >= W)
|| (position.y() < 0) || (position.y() >= (int)_size.h())) return 0;
/* upper part of the icon */
if (position.y() <= H/2) return _alpha[position.y()][position.x()] ? this : 0;
/* lower part of the icon */
if (position.y() > (int)_size.h() - H/2)
return _alpha[position.y() - _size.h() + H][position.x()] ? this : 0;
/* middle part of the icon */
if (_alpha[H/2][position.x()]) return this;
return 0;
}
template class Horizontal_shadow<Genode::Pixel_rgb565, 40>;
template class Horizontal_shadow<Genode::Pixel_rgb565, 160>;
template class Icon<Genode::Pixel_rgb565, 16, 16>;
template class Icon<Genode::Pixel_rgb565, 32, 32>;
template class Icon<Genode::Pixel_rgb565, 64, 64>;