rockbox/apps/plugins/lib/grey_parm.c
Michael Sevakis 371c86bf3f Adapt OSD in plugin lib to be greylib compatible.
Requires addition of viewports and alternate framebuffers to greylib
which are essentially similar to the core implementation except that
the framebuffer can be any size and relationship to a viewport. Drawing
is always fully clipped to the intersecting area.

Adapt oscilloscope.c to the API change. FFT will use the new features
(later update).

Get rid of silly and wrong lcd_bmp_part use in OSD. Remove it from
plugin API (must be made incompatible now).

Change-Id: Iafa5e2174148fb8ad11db6b9d4add0dcabc5c563
2012-12-18 19:16:26 -05:00

261 lines
7.2 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* New greyscale framework
* Parameter handling
*
* This is a generic framework to display 129 shades of grey on low-depth
* bitmap LCDs (Archos b&w, Iriver & Ipod 4-grey) within plugins.
*
* Copyright (C) 2008 Jens Arnold
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "plugin.h"
#include "grey.h"
/* Default greylib viewport struct */
struct viewport _grey_default_vp;
/* Set position of the top left corner of the greyscale overlay
Note that depending on the target LCD, either x or y gets rounded
to the nearest multiple of 4 or 8 */
void grey_set_position(int x, int y)
{
#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
_grey_info.bx = (x + 4) >> 3;
x = 8 * _grey_info.bx;
#else /* vertical packing or vertical interleaved */
#if (LCD_DEPTH == 1) || (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
_grey_info.by = (y + 4) >> 3;
y = 8 * _grey_info.by;
#elif LCD_DEPTH == 2
_grey_info.by = (y + 2) >> 2;
y = 4 * _grey_info.by;
#endif
#endif /* LCD_PIXELFORMAT */
_grey_info.x = x;
_grey_info.y = y;
if (_grey_info.flags & _GREY_RUNNING)
{
#ifdef SIMULATOR
rb->sim_lcd_ex_update_rect(_grey_info.x, _grey_info.y,
_grey_info.width,
_grey_info.height);
grey_deferred_lcd_update();
#else
_grey_info.flags |= _GREY_DEFERRED_UPDATE;
#endif
}
}
/* Set the draw mode for subsequent drawing operations */
void grey_set_drawmode(int mode)
{
_grey_info.vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID);
}
/* Return the current draw mode */
int grey_get_drawmode(void)
{
return _grey_info.vp->drawmode;
}
/* Set the foreground shade for subsequent drawing operations */
void grey_set_foreground(unsigned brightness)
{
_GREY_FG_BRIGHTNESS(_grey_info.vp) = brightness;
}
/* Return the current foreground shade */
unsigned grey_get_foreground(void)
{
return _GREY_FG_BRIGHTNESS(_grey_info.vp);
}
/* Set the background shade for subsequent drawing operations */
void grey_set_background(unsigned brightness)
{
_GREY_BG_BRIGHTNESS(_grey_info.vp) = brightness;
}
/* Return the current background shade */
unsigned grey_get_background(void)
{
return _GREY_BG_BRIGHTNESS(_grey_info.vp);
}
/* Set draw mode, foreground and background shades at once */
void grey_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness)
{
grey_set_drawmode(mode);
grey_set_foreground(fg_brightness);
grey_set_background(bg_brightness);
}
/* Set font for the text output routines */
void grey_setfont(int newfont)
{
_grey_info.vp->font = newfont;
}
/* Get width and height of a text when printed with the current font */
int grey_getstringsize(const unsigned char *str, int *w, int *h)
{
return rb->font_getstringsize(str, w, h, _grey_info.vp->font);
}
/* Helper to establish visible area between viewport and framebuffer */
static void grey_update_clip_rect(void)
{
if (!(_grey_info.flags & GREY_BUFFERED))
return; /* no chunky buffer */
struct viewport *vp = _grey_info.vp;
if (!vp || !_grey_info.curbuffer)
return;
/* Get overall intersection of framebuffer and viewport in viewport
coordinates so that later clipping of drawing is kept as simple as
possible. If l <= r and/or b <= t after intersecting, draw routines
will see this as an empty area. */
_grey_info.clip_l = _grey_info.cb_x - vp->x;
_grey_info.clip_t = _grey_info.cb_y - vp->y;
_grey_info.clip_r = _grey_info.clip_l + _grey_info.cb_width;
_grey_info.clip_b = _grey_info.clip_t + _grey_info.cb_height;
if (_grey_info.clip_l < 0)
_grey_info.clip_l = 0;
if (_grey_info.clip_t < 0)
_grey_info.clip_t = 0;
if (_grey_info.clip_r > vp->width)
_grey_info.clip_r = vp->width;
if (_grey_info.clip_b > vp->height)
_grey_info.clip_b = vp->height;
}
/* Set current grey viewport for draw routines */
void grey_set_viewport(struct viewport *vp)
{
if (vp == NULL)
vp = &_grey_default_vp;
if (_grey_info.vp != vp)
{
_grey_info.vp = vp;
grey_update_clip_rect();
}
}
/* Set viewport to default settings */
void grey_viewport_set_fullscreen(struct viewport *vp,
const enum screen_type screen)
{
if (vp == NULL)
vp = &_grey_default_vp;
vp->x = 0;
vp->y = 0;
vp->width = _grey_info.width;
vp->height = _grey_info.height;
_GREY_FG_BRIGHTNESS(vp) = 0;
_GREY_BG_BRIGHTNESS(vp) = 255;
vp->drawmode = DRMODE_SOLID;
vp->font = FONT_SYSFIXED;
if (vp == _grey_info.vp)
grey_update_clip_rect(); /* is current one in use */
(void)screen;
}
void grey_viewport_set_pos(struct viewport *vp,
int x, int y, int width, int height)
{
if (vp == NULL || vp == &_grey_default_vp)
return; /* Cannot be moved or resized */
if (width < 0)
width = 0; /* 'tis okay */
if (height < 0)
height = 0;
vp->x = x;
vp->y = y;
vp->width = width;
vp->height = height;
if (vp == _grey_info.vp)
grey_update_clip_rect(); /* is current one in use */
}
/* Set current grey chunky buffer for draw routines */
void grey_set_framebuffer(unsigned char *buffer)
{
if (!(_grey_info.flags & GREY_BUFFERED))
return; /* no chunky buffer */
if (buffer == NULL)
buffer = _grey_info.buffer; /* Default */
if (buffer != _grey_info.curbuffer)
{
_grey_info.curbuffer = buffer;
if (buffer == _grey_info.buffer)
{
/* Setting to default fb resets dimensions */
grey_framebuffer_set_pos(0, 0, 0, 0);
}
}
}
/* Specify the dimensions of the current framebuffer */
void grey_framebuffer_set_pos(int x, int y, int width, int height)
{
if (!(_grey_info.flags & GREY_BUFFERED))
return; /* no chunky buffer */
if (_grey_info.curbuffer == _grey_info.buffer)
{
/* This cannot be moved or resized */
x = 0;
y = 0;
width = _grey_info.width;
height = _grey_info.height;
}
else if (width <= 0 || height <= 0)
return;
if (x == _grey_info.cb_x && y == _grey_info.cb_y &&
width == _grey_info.cb_width && height == _grey_info.cb_height)
return; /* No change */
_grey_info.cb_x = x;
_grey_info.cb_y = y;
_grey_info.cb_width = width;
_grey_info.cb_height = height;
grey_update_clip_rect();
}