mirror of
https://github.com/vdr-projects/vdr.git
synced 2025-03-01 10:50:46 +00:00
VDR developer version 2.3.1 is now available at ftp://ftp.tvdr.de/vdr/Developer/vdr-2.3.1.tar.bz2 A 'diff' against the previous version is available at ftp://ftp.tvdr.de/vdr/Developer/vdr-2.2.0-2.3.1.diff MD5 checksums: 391c2ed60e2f7d24563fe3ed5854bc4f vdr-2.3.1.tar.bz2 983fd4bad7d19cd98301d54173107129 vdr-2.2.0-2.3.1.diff WARNING: ======== This is a *developer* version. Even though *I* use it in my productive environment, I strongly recommend that you only use it under controlled conditions and for testing and debugging. *** PLEASE BE VERY CAREFUL WHEN USING THIS DEVELOPER VERSION, ESPECIALLY *** IF YOU ENABLE THE NEW SVDRP PEERING! KEEP BACKUPS OF ALL YOUR TIMERS *** AND OBSERVE VERY CLOSELY WHETHER EVERYTHING WORKS AS EXPECTED. THIS *** VERSION INTRODUCES SOME MAJOR CHANGES IN HANDLING GLOBAL LISTS AND *** LOCKING, SO ANYTHING CAN HAPPEN! YOU HAVE BEEN WARNED! The main focus of this developer version is on the new locking mechanism for global lists, and the ability to handle remote timers. Any plugins that access the global lists of timers, channels, schedules or recordings, will need to be adjusted (see below for details). Please do initial tests with plain vanilla VDR and just the output plugin you need. Known bugs/problems: - After deleting the last recording in a sub folder, the cursor may not be positioned correctly. - Instant recordings and pausing live video don't (yet) use the default SVDRP host for recording. From the HISTORY file: - The new function cOsd::MaxPixmapSize() can be called to determine the maximum size a cPixmap may have on the current OSD. The 'osddemo' example has been modified accordingly. Plugin authors may want to use this function in case they use pixmaps that are larger than the full OSD size. The default implementation sets this limit to 2048x2048 pixel. - The Setup/CAM menu now displays which device an individual CAM is currently assigned to (suggested by Frank Neumann). - Added detection of 24fps (thanks to Thomas Reufer). - Added a note about the VDR User Counter and VDR's facebook page to the README file. - The dvbhddevice plugin is no longer part of the VDR source archive. You can get the latest version of this plugin from the author's repository at https://bitbucket.org/powARman/dvbhddevice. - The dvbsddevice and rcu plugins are no longer part of the VDR source archive. You can get the latest versions of these plugins from ftp://ftp.tvdr.de/vdr/Plugins. - Added a section about Output Devices to the INSTALL file. - Fixed setting the source value of newly created channels, in case the NIT is received from a different, but very close satellite position (reported by Daniel Ribeiro). The code for handling different NITs has been removed from nit.c, because according to the DVB standard table id 0x40 carries only the NIT of the actual network. - Added some comment to cPixmap about the relation between OSD, ViewPort and DrawPort (suggested by Thomas Reufer). - Improved syncing on sections when parsing the NIT and SDT. - Fixed scaling subtitles (their areas could sometimes extend outside the actual OSD). - Reduced the priority of the "video directory scanner" thread (suggested by Thomas Reufer) and checking cIoThrottle::Engaged() when it is running. - The script that gets called for recordings is now also called right before a recording is edited, with the first parameter being "editing" (suggested by Dieter Ferdinand). - The new setup option "OSD/Default sort mode for recordings" can be used to define how recordings shall be sorted by default (either by time or by name, with "by time" being the default). If a particular sort mode has been selected for a folder by pressing '0', the default no longer applies to that folder. Repeating timers no longer write a ".sort" file into a recordings folder to have the recordings sorted by time. - The command line option -D now accepts the value '-' (as in -D-), which prevents VDR from using any DVB devices (suggested by Dietmar Spingler). - The -V and -h options now list the plugins in alphabetical order (suggested by Dietmar Spingler). - Fixed a compiler warning in font.c. - Commented out the line #define DEPRECATED_VIDEOSYSTEM in device.h. If a plugin doesn't compile with this version of VDR, you can uncomment this line as a quick workaround. In the long run the plugin will need to be adapted. - The function cOsd::GetBitmap() is now 'protected'. If a plugin doesn't compile with this version of VDR, you can uncomment the line //#define DEPRECATED_GETBITMAP in osd.h as a quick workaround. In the long run the plugin will need to be adapted. - The -u option now also accepts a numerical user id (suggested by Derek Kelly). - The SVDRP port now accepts multiple concurrent connections. You can now keep an SVDRP connection open as long as you wish, without preventing others from connecting. Note, though, that SVDRP connections still get closed automatically if there has been no activity for 300 seconds (configurable via "Setup/Miscellaneous/SVDRP timeout (s)"). - The SVDRP log messages have been unified and now always contain the IP and port number of the remote host. - SVDRP connections are now handled in a separate "SVDRP server handler" thread, which makes them more responsive. Note that there is only one thread that handles all concurrent SVDRP connections. That way each SVDRP command is guaranteed to be processed separately, without interfering with any other SVDRP commands that might be issued at the same time. Plugins that implement SVDRP commands may need to take care of proper locking if the commands access global data. - VDR now sends out a broadcast to port 6419/udp, which was assigned to 'svdrp-disc' by the IANA. VDRs listening on that port will automatically initiate an SVDRP connection to the broadcasting VDR, and in turn send out a broadcast to make other VDRs connect to them. That way all VDRs within the local network will have permanent "peer-to-peer" SVDRP connections between each other. The configuration in the svdrphosts.conf file is taken into account when considering whether or not to respond to an SVDRP discover broadcast. - The new SVDRP command PING is used by automatically established peer-to-peer connections to keep them alive. - The new function GetSVDRPServerNames() can be used to get a list of all VDRs this VDR is connected to via SVDRP. - The new function ExecSVDRPCommand() can be used to execute an SVDRP command on one of the servers this VDR is connected to, and retrieve the result. The helper functions SVDRPCode() and SVDRPValue() can be used to easily access the codes and values returned by ExecSVDRPCommand(). - The cTimer class now has a new member named 'remote', which holds the name of the remote server this timer will record on. If this is NULL, it is a local timer. - Timers from other VDRs that are connected to this VDR via SVDRP are now automatically fetched and stored in the global Timers list. In order for this to work, all of the channels used by timers on the remote VDR must also be defined on the local VDR (however, not necessarily in the same sequence). Automatic channel syncing will be implemented later. - The main menu of the LCARS skin now displays a small rectangle on the left side of a timer if this is a remote timer. The color of that rectangle changes if the timer is currently recording on the remote VDR. - Accessing the global Timers list now has to be protected by proper locking, because SVDRP commands are now executed in a separate thread. The introduction of this locking mechanism required the following changes: + The new classes cStateLock and cStateKey are used to implement locking with quick detection of state changes. + cConfig::cConfig() now has a parameter that indicates whether this list requires locking. + The global lists of Timers, Channels, Schedules and Recordings are no longer static variables. They are now pointers that need to be retrieved through a call to cTimers::GetTimersRead/Write(), cChannels::GetChannelsRead/Write(), cSchedules::GetSchedulesRead/Write() and cRecordings::GetRecordingsRead/Write(), respectively. + References from/to link channels are now removed in cChannels::Del() rather than cChannel::~cChannel(), to make sure the caller holds a proper lock. + cChannel::HasTimer() has been removed. This information is now retrieved via cSchedule::HasTimer(). + Several member functions of cChannel, cTimer, cMarks and cRecording have been made 'const', and some of them are now available as both 'const' and 'non-const' versions. + The cChannel::Set...() functions are now 'bool' and return true if they have actually changed any of the channels's members. + cChannels::SetModified() has been renamed to cChannels::SetModifiedByUser(). + cChannels::Modified() has been renamed to cChannels::ModifiedByUser(), and now has a 'State' parameter that allows the caller to see whether a channel has been modified since the last call to this function with the same State variable. + The macros CHANNELSMOD_NONE/_AUTO/_USER have been removed. + cMarks now requires locking via cStateKey. + cSortedTimers now requires a pointer to the list of timers. + cEvent::HasTimer() no longer scans the list of timers to check whether an event is referenced by a timer, but rather keeps score of how many timers reference it. This was necessary in order to avoid having to lock the list of timers from within a cEvent. + The new class cListGarbageCollector is used to temporary store any objects deleted from cLists that require locking. This allows pointers to such objects to be dereferenced even if the objects are no longer part of the list. + cListBase::Contains() can be used to check whether a particular object is still contained in that list. + Outdated events are no longer "phased out", but rather deleted right away and thus taken care of by the new "garbage collector" of the list. + Deleted cRecording objects are no longer kept in a list of "vanished" recordings, but are rather taken care of by the new "garbage collector" of the list. + cSchedules::ClearAll() has been removed. The functionality is now implemented directly in cSVDRPServer::CmdCLRE(). + tEventID has been changed to u_int16_t in order to make room for the new member numTimers in cEvent. + cSchedule now has a member Modified(), which can be used with a State variable to quickly determine whether this schedule has been modified since the last call to this function with the same State variable. + cSchedulesLock has been removed. Locking the list of schedules is now done via the cList's new locking mechanism. + The 'OnlyRunningStatus' parameters in cEpgHandler::BeginSegmentTransfer() and cEpgHandler::EndSegmentTransfer() are now obsolete. They are still present in the interface for backward compatibility, but may be removed in a future version. Their value is always 'false'. + The constant tcMod is no longer used in cStatus::TimerChange(). The definition is still there for backward compatibility. Plugins that access the global lists of Timers, Channels, Recordings or Schedules will need to be adapted as follows: + Instead of directly accessing the global variables Timers, Channels or Recordings, they need to set up a cStateKey variable and call the proper getter function, as in cStateKey StateKey; if (const cTimers *Timers = cTimers::GetTimersRead(StateKey)) { // access the timers StateKey.Remove(); } and cStateKey StateKey; if (cTimers *Timers = cTimers::GetTimersWrite(StateKey)) { // access the timers StateKey.Remove(); } See timers.h, thread.h and tools.h for details on this new locking mechanism. + There are convenience macros for easily accessing these lists without having to explicitly set up a cStateKey and calling its Remove() function. These macros have the form LOCK_*_READ/WRITE (with '*' being TIMERS, CHANNELS, SCHEDULES or RECORDINGS). Simply put such a macro before the point where you need to access the respective list, and there will be a pointer named Timers, Channels, Schedules or Recordings, respectively, which is valid until the end of the current block. + If a plugin needs to access several of the global lists in parallel, locking must always be done in the sequence Timers, Channels, Recordings, Schedules. This is necessary to make sure that different threads that need to lock several lists at the same time don't end up in a deadlock. + Some pointer variables may need to be made 'const'. The compiler will tell you about these. - cSectionSyncer has been improved to better handle missed sections. - Added a missing initialization of 'seen' in cChannel's copy constructor. - Background modifications of channels, timers and events are now displayed immediately in the corresponding menus. - cEIT now checks the version of the tables before doing any processing, which saves a lot of locking and processing. - If a timer is newly created with the Red button in the Schedule menu, and the timer is presented to the user in the "Edit timer" menu because it will start immediately, it now *must* be confirmed with "Ok" to set the timer. Otherwise the timer will not be created. - Recordings and deleted recordings are now scanned in a single thread. - The new SVDRP command POLL is used by automatically established peer-to-peer connections to trigger fetching remote timers. - You can now set DumpSVDRPDataTransfer in svdrp.c to true to have all SVDRP communication printed to the console for debugging. - Added a missing 'const' to cReceiver::Receive(), to protect the given Data from being modified. - The SVDRP commands that deal with timers (DELT, LSTT, MODT, NEWT, NEXT and UPDT) as well as any log messages that refer to timers, now use a unique id for each timer, which remains valid as long as this instance of VDR is running. This means that timers are no longer continuously numbered from 1 to N in LSTT. There may be gaps in the sequence, in case timers have been deleted. - The Timers menu now displays the name of the remote VDR in front of the timer's file name, if this is a remote timer. - The new options "Setup/Miscellaneous/SVDRP peering", ".../SVDRP host name" and ".../SVDRP default host" can be used to configure automatic peering between VDRs in the same network. Peering is disabled by default and can be enabled by setting "SVDRP peering" to "yes". - The function cTimer::ToText() no longer returns a newline character at the end of the string. The newline is now added by the caller as necessary. This was changed because cTimer::ToText() is now also needed in a context where the terminating newline can't be used. Consequently, cChannel::ToText() and cMark::ToText() have been modified accordingly. - All timer related response strings from SVDRP commands now use the channel ID instead of channel numbers. - The "Edit timer" menu now has a new parameter "Record on", which can be used to select the VDR on which this timer shall record. Timers can be freely moved between connected VDRs by simply selecting the desired machine in this field. - The SVDRP command DELT no longer checks whether the timer that shall be deleted is currently recording. - The character 0x0D is now stripped from EPG texts (reported by Janne Pänkälä). - The EPG scanner no longer moves the dish if there is a positioner. - The 'newplugin' script now creates the 'po' subdirectory for translations (thanks to Thomas Reufer). - Skins can now implement cSkinDisplayMenu::MenuOrientation() to display horizontal menus (thanks to Stefan Braun). - Fixed a possible stack overflow in cListBase::Sort() (thanks to Oliver Endriss). - Changed the description of the --chartab option in the INSTALL file to refer to "DVB SI table strings" instead of "EPG data". - The width and height of the OSD are now limited to the actual maximum dimensions of the output device, taking into account the top and left offset. - The new setup option "Recording/Record key handling" can be used to define what happens if the Record key on the remote control is pressed during live tv (suggested by Dietmar Spingler). - Empty adaptation field TS packets are now skipped when recording (thanks to Christopher Reimer, based on the "AFFcleaner" by Stefan Pöschel).
1057 lines
58 KiB
C++
1057 lines
58 KiB
C++
/*
|
|
* osd.h: Abstract On Screen Display layer
|
|
*
|
|
* See the main source file 'vdr.c' for copyright information and
|
|
* how to reach the author.
|
|
*
|
|
* $Id: osd.h 4.4 2015/04/19 12:18:25 kls Exp $
|
|
*/
|
|
|
|
#ifndef __OSD_H
|
|
#define __OSD_H
|
|
|
|
#include <limits.h>
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include "config.h"
|
|
#include "font.h"
|
|
#include "thread.h"
|
|
#include "tools.h"
|
|
|
|
#define OSD_LEVEL_DEFAULT 0
|
|
#define OSD_LEVEL_SUBTITLES 10
|
|
|
|
#define MAXNUMCOLORS 256
|
|
#define ALPHA_TRANSPARENT 0x00
|
|
#define ALPHA_OPAQUE 0xFF
|
|
#define IS_OPAQUE(c) ((c >> 24) == ALPHA_OPAQUE)
|
|
#define TEXT_ALIGN_BORDER 10 // fraction of the font height used for sizing border
|
|
|
|
enum {
|
|
//AARRGGBB
|
|
clrTransparent = 0x00000000,
|
|
clrGray50 = 0x7F000000, // 50% gray
|
|
clrBlack = 0xFF000000,
|
|
clrRed = 0xFFFC1414,
|
|
clrGreen = 0xFF24FC24,
|
|
clrYellow = 0xFFFCC024,
|
|
clrMagenta = 0xFFB000FC,
|
|
clrBlue = 0xFF0000FC,
|
|
clrCyan = 0xFF00FCFC,
|
|
clrWhite = 0xFFFCFCFC,
|
|
};
|
|
|
|
enum eOsdError { oeOk, // see also OsdErrorTexts in osd.c
|
|
oeTooManyAreas,
|
|
oeTooManyColors,
|
|
oeBppNotSupported,
|
|
oeAreasOverlap,
|
|
oeWrongAlignment,
|
|
oeOutOfMemory,
|
|
oeWrongAreaSize,
|
|
oeUnknown,
|
|
};
|
|
|
|
typedef uint32_t tColor; // see also font.h
|
|
typedef uint8_t tIndex;
|
|
|
|
inline tColor ArgbToColor(uint8_t A, uint8_t R, uint8_t G, uint8_t B)
|
|
{
|
|
return (tColor(A) << 24) | (tColor(R) << 16) | (tColor(G) << 8) | B;
|
|
}
|
|
|
|
inline tColor RgbToColor(uint8_t R, uint8_t G, uint8_t B)
|
|
{
|
|
return (tColor(R) << 16) | (tColor(G) << 8) | B;
|
|
}
|
|
|
|
inline tColor RgbToColor(double R, double G, double B)
|
|
{
|
|
return RgbToColor(uint8_t(0xFF * R), uint8_t(0xFF * G), uint8_t(0xFF * B));
|
|
}
|
|
|
|
tColor RgbShade(tColor Color, double Factor);
|
|
///< Returns a brighter (Factor > 0) or darker (Factor < 0) version
|
|
///< of the given Color.
|
|
///< If Factor is 0.0, the return value is the unchanged Color,
|
|
///< If Factor is 1.0, white is returned.
|
|
///< If Factor is -1.0, black is returned.
|
|
///< The alpha value of Color is returned unchanged.
|
|
|
|
tColor HsvToColor(double H, double S, double V);
|
|
///< Converts the given Hue (0..360), Saturation (0..1) and Value (0..1)
|
|
///< to an RGB tColor value. The alpha value of the result is 0x00, so
|
|
///< the caller may need to set it accordingly.
|
|
|
|
tColor AlphaBlend(tColor ColorFg, tColor ColorBg, uint8_t AlphaLayer = ALPHA_OPAQUE);
|
|
|
|
class cPalette {
|
|
private:
|
|
tColor color[MAXNUMCOLORS];
|
|
int bpp;
|
|
int maxColors, numColors;
|
|
bool modified;
|
|
double antiAliasGranularity;
|
|
protected:
|
|
typedef tIndex tIndexes[MAXNUMCOLORS];
|
|
public:
|
|
cPalette(int Bpp = 8);
|
|
///< Initializes the palette with the given color depth.
|
|
virtual ~cPalette();
|
|
void SetAntiAliasGranularity(uint FixedColors, uint BlendColors);
|
|
///< Allows the system to optimize utilization of the limited color
|
|
///< palette entries when generating blended colors for anti-aliasing.
|
|
///< FixedColors is the maximum number of colors used, and BlendColors
|
|
///< is the maximum number of foreground/background color combinations
|
|
///< used with anti-aliasing. If this function is not called with
|
|
///< useful values, the palette may be filled up with many shades of
|
|
///< a single color combination, and may not be able to serve all
|
|
///< requested colors. By default the palette assumes there will be
|
|
///< 10 fixed colors and 10 color combinations.
|
|
int Bpp(void) const { return bpp; }
|
|
void Reset(void);
|
|
///< Resets the palette, making it contain no colors.
|
|
int Index(tColor Color);
|
|
///< Returns the index of the given Color (the first color has index 0).
|
|
///< If Color is not yet contained in this palette, it will be added if
|
|
///< there is a free slot. If the color can't be added to this palette,
|
|
///< the closest existing color will be returned.
|
|
tColor Color(int Index) const { return Index < maxColors ? color[Index] : 0; }
|
|
///< Returns the color at the given Index. If Index is outside the valid
|
|
///< range, 0 will be returned.
|
|
void SetBpp(int Bpp);
|
|
///< Sets the color depth of this palette to the given value.
|
|
///< The palette contents will be reset, so that it contains no colors.
|
|
void SetColor(int Index, tColor Color);
|
|
///< Sets the palette entry at Index to Color. If Index is larger than
|
|
///< the number of currently used entries in this palette, the entries
|
|
///< in between will have undefined values.
|
|
const tColor *Colors(int &NumColors) const;
|
|
///< Returns a pointer to the complete color table and stores the
|
|
///< number of valid entries in NumColors. If no colors have been
|
|
///< stored yet, NumColors will be set to 0 and the function will
|
|
///< return NULL.
|
|
void Take(const cPalette &Palette, tIndexes *Indexes = NULL, tColor ColorFg = 0, tColor ColorBg = 0);
|
|
///< Takes the colors from the given Palette and adds them to this palette,
|
|
///< using existing entries if possible. If Indexes is given, it will be
|
|
///< filled with the index values that each color of Palette has in this
|
|
///< palette. If either of ColorFg or ColorBg is not zero, the first color
|
|
///< in Palette will be taken as ColorBg, and the second color will become
|
|
///< ColorFg.
|
|
void Replace(const cPalette &Palette);
|
|
///< Replaces the colors of this palette with the colors from the given
|
|
///< palette.
|
|
tColor Blend(tColor ColorFg, tColor ColorBg, uint8_t Level) const;
|
|
///< Determines a color that consists of a linear blend between ColorFg
|
|
///< and ColorBg. If Level is 0, the result is ColorBg, if it is 255,
|
|
///< the result is ColorFg. If SetAntiAliasGranularity() has been called previously,
|
|
///< Level will be mapped to a limited range of levels that allow to make best
|
|
///< use of the palette entries.
|
|
int ClosestColor(tColor Color, int MaxDiff = INT_MAX) const;
|
|
///< Returns the index of a color in this palette that is closest to the given
|
|
///< Color. MaxDiff can be used to control the maximum allowed color difference.
|
|
///< If no color with a maximum difference of MaxDiff can be found, -1 will
|
|
///< be returned. With the default value of INT_MAX, there will always be
|
|
///< a valid color index returned, but the color may be completely different.
|
|
};
|
|
|
|
enum eTextAlignment { taCenter = 0x00,
|
|
taLeft = 0x01,
|
|
taRight = 0x02,
|
|
taTop = 0x04,
|
|
taBottom = 0x08,
|
|
taBorder = 0x10, // keeps some distance from the left or right alignment edge
|
|
taDefault = taTop | taLeft
|
|
};
|
|
|
|
class cFont;
|
|
|
|
class cBitmap : public cPalette {
|
|
private:
|
|
tIndex *bitmap;
|
|
int x0, y0;
|
|
int width, height;
|
|
int dirtyX1, dirtyY1, dirtyX2, dirtyY2;
|
|
public:
|
|
cBitmap(int Width, int Height, int Bpp, int X0 = 0, int Y0 = 0);
|
|
///< Creates a bitmap with the given Width, Height and color depth (Bpp).
|
|
///< X0 and Y0 define the offset at which this bitmap will be located on the OSD.
|
|
///< All coordinates given in the other functions will be relative to
|
|
///< this offset (unless specified otherwise).
|
|
cBitmap(const char *FileName);
|
|
///< Creates a bitmap and loads an XPM image from the given file.
|
|
cBitmap(const char *const Xpm[]);
|
|
///< Creates a bitmap from the given XPM data.
|
|
virtual ~cBitmap();
|
|
int X0(void) const { return x0; }
|
|
int Y0(void) const { return y0; }
|
|
int Width(void) const { return width; }
|
|
int Height(void) const { return height; }
|
|
void SetSize(int Width, int Height);
|
|
///< Sets the size of this bitmap to the given values. Any previous
|
|
///< contents of the bitmap will be lost. If Width and Height are the same
|
|
///< as the current values, nothing will happen and the bitmap remains
|
|
///< unchanged.
|
|
void SetOffset(int X0, int Y0) { x0 = X0; y0 = Y0; }
|
|
///< Sets the offset of this bitmap to the given values.
|
|
bool Contains(int x, int y) const;
|
|
///< Returns true if this bitmap contains the point (x, y).
|
|
bool Covers(int x1, int y1, int x2, int y2) const;
|
|
///< Returns true if the rectangle defined by the given coordinates
|
|
///< completely covers this bitmap.
|
|
bool Intersects(int x1, int y1, int x2, int y2) const;
|
|
///< Returns true if the rectangle defined by the given coordinates
|
|
///< intersects with this bitmap.
|
|
bool Dirty(int &x1, int &y1, int &x2, int &y2);
|
|
///< Tells whether there is a dirty area and returns the bounding
|
|
///< rectangle of that area (relative to the bitmaps origin).
|
|
void Clean(void);
|
|
///< Marks the dirty area as clean.
|
|
bool LoadXpm(const char *FileName);
|
|
///< Calls SetXpm() with the data from the file FileName.
|
|
///< Returns true if the operation was successful.
|
|
bool SetXpm(const char *const Xpm[], bool IgnoreNone = false);
|
|
///< Sets this bitmap to the given XPM data. Any previous bitmap or
|
|
///< palette data will be overwritten with the new data.
|
|
///< If IgnoreNone is true, a "none" color entry will be ignored.
|
|
///< Only set IgnoreNone to true if you know that there is a "none"
|
|
///< color entry in the XPM data and that this entry is not used!
|
|
///< If SetXpm() is called with IgnoreNone set to false and the XPM
|
|
///< data contains an unused "none" entry, it will be automatically
|
|
///< called again with IgnoreNone set to true.
|
|
///< Returns true if the operation was successful.
|
|
void SetIndex(int x, int y, tIndex Index);
|
|
///< Sets the index at the given coordinates to Index.
|
|
///< Coordinates are relative to the bitmap's origin.
|
|
void Fill(tIndex Index);
|
|
///< Fills the bitmap data with the given Index.
|
|
void DrawPixel(int x, int y, tColor Color);
|
|
///< Sets the pixel at the given coordinates to the given Color, which is
|
|
///< a full 32 bit ARGB value.
|
|
///< If the coordinates are outside the bitmap area, no pixel will be set.
|
|
void DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg = 0, tColor ColorBg = 0, bool ReplacePalette = false, bool Overlay = false);
|
|
///< Sets the pixels in this bitmap with the data from the given
|
|
///< Bitmap, putting the upper left corner of the Bitmap at (x, y).
|
|
///< If ColorFg or ColorBg is given, the first palette entry of the Bitmap
|
|
///< will be mapped to ColorBg and the second palette entry will be mapped to
|
|
///< ColorFg (palette indexes are defined so that 0 is the background and
|
|
///< 1 is the foreground color). ReplacePalette controls whether the target
|
|
///< area shall have its palette replaced with the one from Bitmap.
|
|
///< If Overlay is true, any pixel in Bitmap that has color index 0 will
|
|
///< not overwrite the corresponding pixel in the target area.
|
|
void DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width = 0, int Height = 0, int Alignment = taDefault);
|
|
///< Draws the given string at coordinates (x, y) with the given foreground
|
|
///< and background color and font. If Width and Height are given, the text
|
|
///< will be drawn into a rectangle with the given size and the given
|
|
///< Alignment (default is top-left). If ColorBg is clrTransparent, no
|
|
///< background pixels will be drawn, which allows drawing "transparent" text.
|
|
void DrawRectangle(int x1, int y1, int x2, int y2, tColor Color);
|
|
///< Draws a filled rectangle defined by the upper left (x1, y1) and lower right
|
|
///< (x2, y2) corners with the given Color. If the rectangle covers the entire
|
|
///< bitmap area, the color palette will be reset, so that new colors can be
|
|
///< used for drawing.
|
|
void DrawEllipse(int x1, int y1, int x2, int y2, tColor Color, int Quadrants = 0);
|
|
///< Draws a filled ellipse defined by the upper left (x1, y1) and lower right
|
|
///< (x2, y2) corners with the given Color. Quadrants controls which parts of
|
|
///< the ellipse are actually drawn:
|
|
///< 0 draws the entire ellipse
|
|
///< 1..4 draws only the first, second, third or fourth quadrant, respectively
|
|
///< 5..8 draws the right, top, left or bottom half, respectively
|
|
///< -1..-4 draws the inverted part of the given quadrant
|
|
///< If Quadrants is not 0, the coordinates are those of the actual area, not
|
|
///< the full circle!
|
|
void DrawSlope(int x1, int y1, int x2, int y2, tColor Color, int Type);
|
|
///< Draws a "slope" into the rectangle defined by the upper left (x1, y1) and
|
|
///< lower right (x2, y2) corners with the given Color. Type controls the
|
|
///< direction of the slope and which side of it will be drawn:
|
|
///< 0: horizontal, rising, lower
|
|
///< 1: horizontal, rising, upper
|
|
///< 2: horizontal, falling, lower
|
|
///< 3: horizontal, falling, upper
|
|
///< 4: vertical, rising, lower
|
|
///< 5: vertical, rising, upper
|
|
///< 6: vertical, falling, lower
|
|
///< 7: vertical, falling, upper
|
|
const tIndex *Data(int x, int y) const;
|
|
///< Returns the address of the index byte at the given coordinates.
|
|
tColor GetColor(int x, int y) const { return Color(*Data(x, y)); }
|
|
///< Returns the color at the given coordinates.
|
|
void ReduceBpp(const cPalette &Palette);
|
|
///< Reduces the color depth of the bitmap to that of the given Palette.
|
|
///< If Palette's color depth is not smaller than the bitmap's current
|
|
///< color depth, or if it is not one of 4bpp or 2bpp, nothing happens. After
|
|
///< reducing the color depth the current palette is replaced with
|
|
///< the given one.
|
|
void ShrinkBpp(int NewBpp);
|
|
///< Shrinks the color depth of the bitmap to NewBpp by keeping only
|
|
///< the 2^NewBpp most frequently used colors as defined in the current palette.
|
|
///< If NewBpp is not smaller than the bitmap's current color depth,
|
|
///< or if it is not one of 4bpp or 2bpp, nothing happens.
|
|
cBitmap *Scaled(double FactorX, double FactorY, bool AntiAlias = false) const;
|
|
///< Creates a copy of this bitmap, scaled by the given factors.
|
|
///< If AntiAlias is true and either of the factors is greater than 1.0,
|
|
///< anti-aliasing is applied. This will also set the color depth of the
|
|
///< returned bitmap to 8bpp.
|
|
///< The caller must delete the returned bitmap once it is no longer used.
|
|
};
|
|
|
|
struct tArea {
|
|
int x1, y1, x2, y2;
|
|
int bpp;
|
|
int Width(void) const { return x2 - x1 + 1; }
|
|
int Height(void) const { return y2 - y1 + 1; }
|
|
bool Intersects(const tArea &Area) const { return !(x2 < Area.x1 || x1 > Area.x2 || y2 < Area.y1 || y1 > Area.y2); }
|
|
};
|
|
|
|
class cPoint {
|
|
private:
|
|
int x;
|
|
int y;
|
|
public:
|
|
cPoint(void) { x = y = 0; }
|
|
cPoint(int X, int Y) { x = X; y = Y; }
|
|
cPoint(const cPoint &Point) { x = Point.X(); y = Point.Y(); }
|
|
bool operator==(const cPoint &Point) const { return x == Point.X() && y == Point.Y(); }
|
|
bool operator!=(const cPoint &Point) const { return !(*this == Point); }
|
|
cPoint operator-(void) const { return cPoint(-x, -y); }
|
|
cPoint operator-(const cPoint &Point) const { return cPoint(x - Point.X(), y - Point.Y()); }
|
|
int X(void) const { return x; }
|
|
int Y(void) const { return y; }
|
|
void SetX(int X) { x = X; }
|
|
void SetY(int Y) { y = Y; }
|
|
void Set(int X, int Y) { x = X; y = Y; }
|
|
void Set(const cPoint &Point) { x = Point.X(); y = Point.Y(); }
|
|
void Shift(int Dx, int Dy) { x += Dx; y += Dy; }
|
|
void Shift(const cPoint &Dp) { x += Dp.X(); y += Dp.Y(); }
|
|
cPoint Shifted(int Dx, int Dy) const { cPoint p(*this); p.Shift(Dx, Dy); return p; }
|
|
cPoint Shifted(const cPoint &Dp) const { cPoint p(*this); p.Shift(Dp); return p; }
|
|
};
|
|
|
|
class cSize {
|
|
private:
|
|
int width;
|
|
int height;
|
|
public:
|
|
cSize(void) { width = height = 0; }
|
|
cSize(int Width, int Height) { width = Width; height = Height; }
|
|
cSize(const cSize &Size) { width = Size.Width(); height = Size.Height(); }
|
|
bool operator==(const cSize &Size) const { return width == Size.Width() && height == Size.Height(); }
|
|
bool operator!=(const cSize &Size) const { return !(*this == Size); }
|
|
bool operator<(const cSize &Size) const { return width < Size.Width() && height < Size.Height(); }
|
|
int Width(void) const { return width; }
|
|
int Height(void) const { return height; }
|
|
void SetWidth(int Width) { width = Width; }
|
|
void SetHeight(int Height) { height = Height; }
|
|
void Set(int Width, int Height) { width = Width; height = Height; }
|
|
void Set(const cSize &Size) { width = Size.Width(); height = Size.Height(); }
|
|
bool Contains(const cPoint &Point) const { return 0 <= Point.X() && 0 <= Point.Y() && Point.X() < width && Point.Y() < height; }
|
|
void Grow(int Dw, int Dh) { width += 2 * Dw; height += 2 * Dh; }
|
|
cSize Grown(int Dw, int Dh) const { cSize s(*this); s.Grow(Dw, Dh); return s; }
|
|
};
|
|
|
|
class cRect {
|
|
private:
|
|
cPoint point;
|
|
cSize size;
|
|
public:
|
|
static const cRect Null;
|
|
cRect(void): point(0, 0), size(0, 0) {}
|
|
cRect(int X, int Y, int Width, int Height): point(X, Y), size(Width, Height) {}
|
|
cRect(const cPoint &Point, const cSize &Size): point(Point), size(Size) {}
|
|
cRect(const cSize &Size): point(0, 0), size(Size) {}
|
|
cRect(const cRect &Rect): point(Rect.Point()), size(Rect.Size()) {}
|
|
bool operator==(const cRect &Rect) const { return point == Rect.Point() && size == Rect.Size(); }
|
|
bool operator!=(const cRect &Rect) const { return !(*this == Rect); }
|
|
int X(void) const { return point.X(); }
|
|
int Y(void) const { return point.Y(); }
|
|
int Width(void) const { return size.Width(); }
|
|
int Height(void) const { return size.Height(); }
|
|
int Left(void) const { return X(); }
|
|
int Top(void) const { return Y(); }
|
|
int Right(void) const { return X() + Width() - 1; }
|
|
int Bottom(void) const { return Y() + Height() - 1; }
|
|
const cPoint &Point(void) const { return point; }
|
|
const cSize &Size(void) const { return size; }
|
|
void Set(int X, int Y, int Width, int Height) { point.Set(X, Y); size.Set(Width, Height); }
|
|
void Set(cPoint Point, cSize Size) { point.Set(Point); size.Set(Size); }
|
|
void SetPoint(int X, int Y) { point.Set(X, Y); }
|
|
void SetPoint(const cPoint &Point) { point.Set(Point); }
|
|
void SetSize(int Width, int Height) { size.Set(Width, Height); }
|
|
void SetSize(const cSize &Size) { size.Set(Size); }
|
|
void SetX(int X) { point.SetX(X); }
|
|
void SetY(int Y) { point.SetY(Y); }
|
|
void SetWidth(int Width) { size.SetWidth(Width); }
|
|
void SetHeight(int Height) { size.SetHeight(Height); }
|
|
void SetLeft(int Left) { SetWidth(Width() + X() - Left); SetX(Left); }
|
|
void SetTop(int Top) { SetHeight(Height() + Y() - Top); SetY(Top); }
|
|
void SetRight(int Right) { SetWidth(Right - X() + 1); }
|
|
void SetBottom(int Bottom) { SetHeight(Bottom - Y() + 1); }
|
|
void Shift(int Dx, int Dy) { point.Shift(Dx, Dy); }
|
|
void Shift(const cPoint &Dp) { point.Shift(Dp); }
|
|
cRect Shifted(int Dx, int Dy) const { cRect r(*this); r.Shift(Dx, Dy); return r; }
|
|
cRect Shifted(const cPoint &Dp) const { cRect r(*this); r.Shift(Dp); return r; }
|
|
void Grow(int Dx, int Dy);
|
|
///< Grows the rectangle by the given number of pixels in either direction.
|
|
///< A negative value will shrink the rectangle.
|
|
cRect Grown(int Dw, int Dh) const { cRect r(*this); r.Grow(Dw, Dh); return r; }
|
|
bool Contains(const cPoint &Point) const;
|
|
///< Returns true if this rectangle contains Point.
|
|
bool Contains(const cRect &Rect) const;
|
|
///< Returns true if this rectangle completely contains Rect.
|
|
bool Intersects(const cRect &Rect) const;
|
|
///< Returns true if this rectangle intersects with Rect.
|
|
cRect Intersected(const cRect &Rect) const;
|
|
///< Returns the intersection of this rectangle and the given Rect.
|
|
void Combine(const cRect &Rect);
|
|
///< Combines this rectangle with the given Rect.
|
|
cRect Combined(const cRect &Rect) const { cRect r(*this); r.Combine(Rect); return r; }
|
|
///< Returns the surrounding rectangle that contains this rectangle and the
|
|
///< given Rect.
|
|
void Combine(const cPoint &Point);
|
|
///< Combines this rectangle with the given Point.
|
|
cRect Combined(const cPoint &Point) const { cRect r(*this); r.Combine(Point); return r; }
|
|
///< Returns the surrounding rectangle that contains this rectangle and the
|
|
///< given Point.
|
|
bool IsEmpty(void) const { return Width() <= 0 || Height() <= 0; }
|
|
///< Returns true if this rectangle is empty.
|
|
};
|
|
|
|
class cImage {
|
|
private:
|
|
cSize size;
|
|
tColor *data;
|
|
public:
|
|
cImage(void);
|
|
cImage(const cImage &Image);
|
|
cImage(const cSize &Size, const tColor *Data = NULL);
|
|
///< Creates an image with the given Size and allocates the necessary memory
|
|
///< to copy the pixels pointed to by Data, which is a sequence of
|
|
///< (Size.Width() * Size.Height()) tColor values.
|
|
///< If Data is NULL, the allocated memory is not initialized.
|
|
///< The alpha value of the Image's pixels is taken into account, so it has to be
|
|
///< greater than 0 for the image to be visible.
|
|
virtual ~cImage();
|
|
const cSize &Size(void) const { return size; }
|
|
int Width(void) const { return size.Width(); }
|
|
int Height(void) const { return size.Height(); }
|
|
const tColor *Data(void) const { return data; }
|
|
tColor GetPixel(const cPoint &Point) const { return data[size.Width() * Point.Y() + Point.X()]; }
|
|
///< Returns the pixel value at the given Point.
|
|
///< For performance reasons there is no range check here, so the caller
|
|
///< must make sure that the Point is within the images size.
|
|
void SetPixel(const cPoint &Point, tColor Color) { data[size.Width() * Point.Y() + Point.X()] = Color; }
|
|
///< Sets the pixel at the given Point to Color.
|
|
///< For performance reasons there is no range check here, so the caller
|
|
///< must make sure that the Point is within the images size.
|
|
void Clear(void);
|
|
///< Clears the image data by setting all pixels to be fully transparent.
|
|
void Fill(tColor Color);
|
|
///< Fills the image data with the given Color.
|
|
};
|
|
|
|
#define MAXPIXMAPLAYERS 8
|
|
|
|
class cPixmap {
|
|
friend class cOsd;
|
|
friend class cPixmapMutexLock;
|
|
private:
|
|
static cMutex mutex;
|
|
int layer;
|
|
int alpha;
|
|
bool tile;
|
|
cRect viewPort;
|
|
cRect drawPort;
|
|
cRect dirtyViewPort;
|
|
cRect dirtyDrawPort;
|
|
protected:
|
|
virtual ~cPixmap() {}
|
|
void MarkViewPortDirty(const cRect &Rect);
|
|
///< Marks the given rectangle of the view port of this pixmap as dirty.
|
|
///< Rect is combined with the existing dirtyViewPort rectangle.
|
|
///< The coordinates of Rect are given in absolute OSD values.
|
|
void MarkViewPortDirty(const cPoint &Point);
|
|
///< Marks the given point of the view port of this pixmap as dirty.
|
|
///< Point is combined with the existing dirtyViewPort rectangle.
|
|
///< The coordinates of Point are given in absolute OSD values.
|
|
void MarkDrawPortDirty(const cRect &Rect);
|
|
///< Marks the given rectangle of the draw port of this pixmap as dirty.
|
|
///< Rect is combined with the existing dirtyDrawPort rectangle.
|
|
///< The coordinates of Rect are relative to the pixmap's draw port.
|
|
///< If Rect extends into the currently visible view port of this pixmap,
|
|
///< MarkViewPortDirty() is called with the appropriate value.
|
|
void MarkDrawPortDirty(const cPoint &Point);
|
|
///< Marks the given point of the draw port of this pixmap as dirty.
|
|
///< Point is combined with the existing dirtyDrawPort rectangle.
|
|
///< The coordinates of Point are relative to the pixmap's draw port.
|
|
///< If Point is within the currently visible view port of this pixmap,
|
|
///< MarkViewPortDirty() is called with the appropriate value.
|
|
void SetClean(void);
|
|
///< Resets the "dirty" rectangles of this pixmap.
|
|
virtual void DrawPixmap(const cPixmap *Pixmap, const cRect &Dirty);
|
|
///< Draws the Dirty part of the given Pixmap into this pixmap. If the
|
|
///< Pixmap's layer is 0, it is copied, otherwise it is rendered into this
|
|
///< pixmap. This function is used only to implement the tile handling
|
|
///< in the final rendering to the OSD.
|
|
public:
|
|
cPixmap(void);
|
|
cPixmap(int Layer, const cRect &ViewPort, const cRect &DrawPort = cRect::Null);
|
|
///< Creates a pixmap in the given Layer. When rendering the final OSD, pixmaps
|
|
///< are handled in ascending order of their individual layer. This is
|
|
///< important if pixmaps overlap each other. The one with the highest layer is
|
|
///< rendered last. The actual value of Layer doesn't matter, it is only used
|
|
///< for defining the rendering sequence. If Layer is less than zero, this
|
|
///< pixmap will not be rendered into the final OSD (it can be activated by a
|
|
///< later call to SetLayer()). The value 0 is reserved for the background
|
|
///< pixmap and shall not be used otherwise (with the sole exception of
|
|
///< temporarily using layer 0 to have a text with transparent background
|
|
///< rendered with alpha blending into that pixmap; see also DrawPixel()).
|
|
///< If there are several pixmaps with the same value of Layer, their rendering
|
|
///< sequence within that layer is undefined.
|
|
///< In order to allow devices that can handle only a limited number of layers,
|
|
///< the Layer parameter must be less than 8 (MAXPIXMAPLAYERS).
|
|
///< ViewPort defines the rectangle in which this pixmap will be rendered on
|
|
///< the OSD. The coordinate (0, 0) corresponds to the upper left corner of the
|
|
///< OSD. If no DrawPort is given, it defaults to the same size as the
|
|
///< ViewPort, with its upper left corner set to (0, 0). The DrawPort's origin
|
|
///< is relative to the ViewPort's origin.
|
|
///< All drawing operations will be executed relative to the origin of the
|
|
///< DrawPort rectangle, and will be clipped to the size of this rectangle.
|
|
///< The DrawPort may have a different size than the ViewPort. If it is smaller
|
|
///< than the ViewPort, the rest of the ViewPort is treated as fully transparent
|
|
///< (unless this is a tiled pixmap, in which case the DrawPort is repeated
|
|
///< horizontally and vertically to fill the entire ViewPort). If the DrawPort
|
|
///< is larger than the ViewPort, only that portion of the DrawPort that
|
|
///< intersects with the ViewPort will be visible on the OSD.
|
|
///< The drawing area of a newly created cPixmap is not initialized and may
|
|
///< contain random data.
|
|
///< See cOsd::MaxPixmapSize() for information on the maximum size of pixmaps
|
|
///< supported by the system.
|
|
static void Lock(void) { mutex.Lock(); }
|
|
///< All public member functions of cPixmap set locks as necessary to make sure
|
|
///< they are thread-safe (unless noted otherwise). If several cPixmap member
|
|
///< functions need to be called in a row, the caller must surround these calls
|
|
///< with proper Lock()/Unlock() calls. See the LOCK_PIXMAPS macro for a
|
|
///< convenient way of doing this.
|
|
static void Unlock(void) { mutex.Unlock(); }
|
|
int Layer(void) const { return layer; }
|
|
int Alpha(void) const { return alpha; }
|
|
bool Tile(void) const { return tile; }
|
|
const cRect &ViewPort(void) const { return viewPort; }
|
|
///< Returns the pixmap's view port, which is relative to the OSD's origin.
|
|
///< Since this function returns a reference to a data member, the caller must
|
|
///< use Lock()/Unlock() to make sure the data doesn't change while it is used.
|
|
const cRect &DrawPort(void) const { return drawPort; }
|
|
///< Returns the pixmap's draw port, which is relative to the view port.
|
|
///< Since this function returns a reference to a data member, the caller must
|
|
///< use Lock()/Unlock() to make sure the data doesn't change while it is used.
|
|
const cRect &DirtyViewPort(void) const { return dirtyViewPort; }
|
|
///< Returns the "dirty" rectangle this pixmap causes on the OSD. This is the
|
|
///< surrounding rectangle around all pixels that have been modified since the
|
|
///< last time this pixmap has been rendered to the OSD. The rectangle is
|
|
///< relative to the OSD's origin.
|
|
///< Since this function returns a reference to a data member, the caller must
|
|
///< use Lock()/Unlock() to make sure the data doesn't change while it is used.
|
|
const cRect &DirtyDrawPort(void) const { return dirtyDrawPort; }
|
|
///< Returns the "dirty" rectangle in the draw port of this this pixmap. This is
|
|
///< the surrounding rectangle around all pixels that have been modified since the
|
|
///< last time this pixmap has been rendered to the OSD. The rectangle is
|
|
///< relative to the draw port's origin.
|
|
///< Since this function returns a reference to a data member, the caller must
|
|
///< use Lock()/Unlock() to make sure the data doesn't change while it is used.
|
|
virtual void SetLayer(int Layer);
|
|
///< Sets the layer of this pixmap to the given value.
|
|
///< If the new layer is greater than zero, the pixmap will be visible.
|
|
///< If it is less than zero, it will be invisible.
|
|
///< A value of 0 will be silently ignored.
|
|
///< If a derived class reimplements this function, it needs to call the base
|
|
///< class function.
|
|
virtual void SetAlpha(int Alpha);
|
|
///< Sets the alpha value of this pixmap to the given value.
|
|
///< Alpha is limited to the range 0 (fully transparent) to 255 (fully opaque).
|
|
///< If a derived class reimplements this function, it needs to call the base
|
|
///< class function.
|
|
virtual void SetTile(bool Tile);
|
|
///< Sets the tile property of this pixmap to the given value. If Tile is true,
|
|
///< the pixmaps data will be repeated horizontally and vertically if necessary
|
|
///< to fill the entire view port.
|
|
///< If a derived class reimplements this function, it needs to call the base
|
|
///< class function.
|
|
virtual void SetViewPort(const cRect &Rect);
|
|
///< Sets the pixmap's view port to the given Rect.
|
|
///< If a derived class reimplements this function, it needs to call the base
|
|
///< class function.
|
|
virtual void SetDrawPortPoint(const cPoint &Point, bool Dirty = true);
|
|
///< Sets the pixmap's draw port to the given Point.
|
|
///< Only the origin point of the draw port can be modified, its size is fixed.
|
|
///< By default, setting a new draw port point results in marking the relevant
|
|
///< part of the view port as "dirty". If Dirty is set to false, the view port
|
|
///< will not be marked as dirty. This is mainly used to implement the Pan()
|
|
///< function.
|
|
///< If a derived class reimplements this function, it needs to call the base
|
|
///< class function.
|
|
virtual void Clear(void) = 0;
|
|
///< Clears the pixmap's draw port by setting all pixels to be fully transparent.
|
|
///< A derived class must call Lock()/Unlock().
|
|
virtual void Fill(tColor Color) = 0;
|
|
///< Fills the pixmap's draw port with the given Color.
|
|
///< A derived class must call Lock()/Unlock().
|
|
virtual void DrawImage(const cPoint &Point, const cImage &Image) = 0;
|
|
///< Draws the given Image into this pixmap at the given Point.
|
|
virtual void DrawImage(const cPoint &Point, int ImageHandle) = 0;
|
|
///< Draws the image referenced by the given ImageHandle into this pixmap at
|
|
///< the given Point. ImageHandle must be a value that has previously been
|
|
///< returned by a call to cOsdProvider::StoreImage(). If ImageHandle
|
|
///< has an invalid value, nothing happens.
|
|
virtual void DrawPixel(const cPoint &Point, tColor Color) = 0;
|
|
///< Sets the pixel at the given Point to the given Color, which is
|
|
///< a full 32 bit ARGB value. If the alpha value of Color is not 0xFF
|
|
///< (fully opaque), and this is the background pixmap (layer 0), the pixel is
|
|
///< alpha blended with the existing color at the given position in this pixmap.
|
|
virtual void DrawBitmap(const cPoint &Point, const cBitmap &Bitmap, tColor ColorFg = 0, tColor ColorBg = 0, bool Overlay = false) = 0;
|
|
///< Sets the pixels in the OSD with the data from the given
|
|
///< Bitmap, putting the upper left corner of the Bitmap at Point.
|
|
///< If ColorFg or ColorBg is given, the first palette entry of the Bitmap
|
|
///< will be mapped to ColorBg and the second palette entry will be mapped to
|
|
///< ColorFg (palette indexes are defined so that 0 is the background and
|
|
///< 1 is the foreground color).
|
|
///< If Overlay is true, any pixel in Bitmap that has color index 0 will
|
|
///< not overwrite the corresponding pixel in the target area.
|
|
///< This function is mainly for compatibility with skins or plugins that
|
|
///< draw bitmaps onto the OSD.
|
|
virtual void DrawText(const cPoint &Point, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width = 0, int Height = 0, int Alignment = taDefault) = 0;
|
|
///< Draws the given string at Point with the given foreground
|
|
///< and background color and font. If Width and Height are given, the text
|
|
///< will be drawn into a rectangle with the given size and the given
|
|
///< Alignment (default is top-left). If ColorBg is clrTransparent, no
|
|
///< background pixels will be drawn, which allows drawing "transparent" text.
|
|
virtual void DrawRectangle(const cRect &Rect, tColor Color) = 0;
|
|
///< Draws a filled rectangle with the given Color.
|
|
virtual void DrawEllipse(const cRect &Rect, tColor Color, int Quadrants = 0) = 0;
|
|
///< Draws a filled ellipse with the given Color that fits into the given
|
|
///< rectangle. Quadrants controls which parts of the ellipse are actually drawn:
|
|
///< 0 draws the entire ellipse
|
|
///< 1..4 draws only the first, second, third or fourth quadrant, respectively
|
|
///< 5..8 draws the right, top, left or bottom half, respectively
|
|
///< -1..-4 draws the inverted part of the given quadrant
|
|
///< If Quadrants is not 0, the coordinates are those of the actual area, not
|
|
///< the full circle!
|
|
virtual void DrawSlope(const cRect &Rect, tColor Color, int Type) = 0;
|
|
///< Draws a "slope" with the given Color into the given rectangle.
|
|
///< Type controls the direction of the slope and which side of it will be drawn:
|
|
///< 0: horizontal, rising, lower
|
|
///< 1: horizontal, rising, upper
|
|
///< 2: horizontal, falling, lower
|
|
///< 3: horizontal, falling, upper
|
|
///< 4: vertical, rising, lower
|
|
///< 5: vertical, rising, upper
|
|
///< 6: vertical, falling, lower
|
|
///< 7: vertical, falling, upper
|
|
virtual void Render(const cPixmap *Pixmap, const cRect &Source, const cPoint &Dest) = 0;
|
|
///< Renders the part of the given Pixmap covered by Source into this pixmap at
|
|
///< location Dest. The Source rectangle is relative to the given Pixmap's draw port.
|
|
///< The Pixmap's alpha value is to be used when rendering.
|
|
virtual void Copy(const cPixmap *Pixmap, const cRect &Source, const cPoint &Dest) = 0;
|
|
///< Copies the part of the given Pixmap covered by Source into this pixmap at
|
|
///< location Dest. The Source rectangle is relative to the given Pixmap's draw port.
|
|
///< The data from Pixmap is copied as is, no alpha handling of any kind takes
|
|
///< place.
|
|
virtual void Scroll(const cPoint &Dest, const cRect &Source = cRect::Null) = 0;
|
|
///< Scrolls the data in the pixmap's draw port to the given Dest point.
|
|
///< If Source is given, only the data within that rectangle is scrolled.
|
|
///< Source and Dest are relative to this pixmap's draw port.
|
|
virtual void Pan(const cPoint &Dest, const cRect &Source = cRect::Null) = 0;
|
|
///< Does the same as Scroll(), but also shifts the draw port accordingly,
|
|
///< so that the view port doesn't get dirty if the scrolled rectangle
|
|
///< covers the entire view port. This may be of advantage if, e.g.,
|
|
///< there is a draw port that holds, say, 11 lines of text, while the
|
|
///< view port displays only 10 lines. By Pan()'ing the draw port up one
|
|
///< line, a new bottom line can be written into the draw port (without
|
|
///< being seen through the view port), and later the draw port can be
|
|
///< shifted smoothly, resulting in a smooth scrolling.
|
|
///< It is the caller's responsibility to make sure that Source and Dest
|
|
///< are given in such a way that the view port will not get dirty. No
|
|
///< check is done whether this condition actually holds true.
|
|
};
|
|
|
|
class cPixmapMutexLock : public cMutexLock {
|
|
public:
|
|
cPixmapMutexLock(void): cMutexLock(&cPixmap::mutex) {}
|
|
};
|
|
|
|
#define LOCK_PIXMAPS cPixmapMutexLock PixmapMutexLock
|
|
|
|
// cPixmapMemory is an implementation of cPixmap that uses an array of tColor
|
|
// values to store the pixmap.
|
|
|
|
class cPixmapMemory : public cPixmap {
|
|
private:
|
|
tColor *data;
|
|
bool panning;
|
|
public:
|
|
cPixmapMemory(void);
|
|
cPixmapMemory(int Layer, const cRect &ViewPort, const cRect &DrawPort = cRect::Null);
|
|
virtual ~cPixmapMemory();
|
|
const uint8_t *Data(void) { return (uint8_t *)data; }
|
|
virtual void Clear(void);
|
|
virtual void Fill(tColor Color);
|
|
virtual void DrawImage(const cPoint &Point, const cImage &Image);
|
|
virtual void DrawImage(const cPoint &Point, int ImageHandle);
|
|
virtual void DrawPixel(const cPoint &Point, tColor Color);
|
|
virtual void DrawBitmap(const cPoint &Point, const cBitmap &Bitmap, tColor ColorFg = 0, tColor ColorBg = 0, bool Overlay = false);
|
|
virtual void DrawText(const cPoint &Point, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width = 0, int Height = 0, int Alignment = taDefault);
|
|
virtual void DrawRectangle(const cRect &Rect, tColor Color);
|
|
virtual void DrawEllipse(const cRect &Rect, tColor Color, int Quadrants = 0);
|
|
virtual void DrawSlope(const cRect &Rect, tColor Color, int Type);
|
|
virtual void Render(const cPixmap *Pixmap, const cRect &Source, const cPoint &Dest);
|
|
virtual void Copy(const cPixmap *Pixmap, const cRect &Source, const cPoint &Dest);
|
|
virtual void Scroll(const cPoint &Dest, const cRect &Source = cRect::Null);
|
|
virtual void Pan(const cPoint &Dest, const cRect &Source = cRect::Null);
|
|
};
|
|
|
|
#define MAXOSDAREAS 16
|
|
|
|
/// The cOsd class is the interface to the "On Screen Display".
|
|
/// An actual output device needs to derive from this class and implement
|
|
/// the functionality necessary to display the OSD on the TV screen.
|
|
/// If the actual OSD supports "True Color", it can either let VDR do
|
|
/// all the rendering by calling RenderPixmaps() ("raw mode"), or it can
|
|
/// reimplement all necessary cPixmap functions and do the rendering
|
|
/// itself ("high level mode").
|
|
/// If an OSD provides a "high level mode", it shall also provide a "raw mode"
|
|
/// in order to verify proper operation. The plugin that implements the OSD
|
|
/// shall offer a configuration switch in its setup.
|
|
|
|
class cOsd {
|
|
friend class cOsdProvider;
|
|
private:
|
|
static int osdLeft, osdTop, osdWidth, osdHeight;
|
|
static cVector<cOsd *> Osds;
|
|
static cSize maxPixmapSize;
|
|
static cMutex mutex;
|
|
bool isTrueColor;
|
|
cBitmap *savedBitmap;
|
|
cBitmap *bitmaps[MAXOSDAREAS];
|
|
int numBitmaps;
|
|
cPixmapMemory *savedPixmap;
|
|
cVector<cPixmap *> pixmaps;
|
|
int left, top, width, height;
|
|
uint level;
|
|
bool active;
|
|
protected:
|
|
cOsd(int Left, int Top, uint Level);
|
|
///< Initializes the OSD with the given coordinates.
|
|
///< By default it is assumed that the full area will be able to display
|
|
///< full 32 bit graphics (ARGB with eight bit for each color and the alpha
|
|
///< value, respectively). However, the actual hardware in use may not be
|
|
///< able to display such a high resolution OSD, so there is an option to
|
|
///< divide the full OSD area into several sub-areas with lower color depths
|
|
///< and individual palettes. The sub-areas need not necessarily cover the
|
|
///< entire OSD area, but only the OSD area actually covered by sub-areas
|
|
///< will be available for drawing.
|
|
///< At least one area must be defined in order to set the actual width and
|
|
///< height of the OSD. Also, the caller must first try to use an area that
|
|
///< consists of only one sub-area that covers the entire drawing space,
|
|
///< and should require only the minimum necessary color depth. This is
|
|
///< because a derived cOsd class may or may not be able to handle more
|
|
///< than one area.
|
|
///< There can be any number of cOsd objects at the same time, but only
|
|
///< one of them will be active at any given time. The active OSD is the
|
|
///< one with the lowest value of Level. If there are several cOsd objects
|
|
///< with the same Level, the one that was created first will be active.
|
|
bool Active(void) { return active; }
|
|
virtual void SetActive(bool On) { active = On; }
|
|
///< Sets this OSD to be the active one.
|
|
///< A derived class must call cOsd::SetActive(On).
|
|
cPixmap *AddPixmap(cPixmap *Pixmap);
|
|
///< Adds the given Pixmap to the list of currently active pixmaps in this OSD.
|
|
///< Returns Pixmap if the operation was successful, or NULL if for some reason
|
|
///< the pixmap could not be added to the list.
|
|
///< A derived class that implements its own cPixmap class must call AddPixmap()
|
|
///< in order to add a newly created pixmap to the OSD's list of pixmaps.
|
|
cPixmap *RenderPixmaps(void);
|
|
///< Renders the dirty part of all pixmaps into a resulting pixmap that
|
|
///< shall be displayed on the OSD. The returned pixmap's view port is
|
|
///< set to the location of the rectangle on the OSD that needs to be
|
|
///< refreshed; its draw port's origin is at (0, 0), and it has the same
|
|
///< size as the view port.
|
|
///< Only pixmaps with a non-negative layer value are rendered.
|
|
///< If there are several non-overlapping dirty rectangles from different pixmaps,
|
|
///< they are returned separately in order to avoid re-rendering large parts
|
|
///< of the OSD that haven't changed at all. The caller must therefore call
|
|
///< RenderPixmaps() repeatedly until it returns NULL, and display the returned
|
|
///< parts of the OSD at their appropriate locations. During this entire
|
|
///< operation the caller must hold a lock on the cPixmap mutex (for instance
|
|
///< by putting a LOCK_PIXMAPS into the scope of the operation).
|
|
///< If there are no dirty pixmaps, or if this is not a true color OSD,
|
|
///< this function returns NULL.
|
|
///< The caller must call DestroyPixmap() for the returned pixmap after use.
|
|
//#define DEPRECATED_GETBITMAP
|
|
#ifdef DEPRECATED_GETBITMAP
|
|
public:
|
|
#endif
|
|
cBitmap *GetBitmap(int Area);
|
|
///< Returns a pointer to the bitmap for the given Area, or NULL if no
|
|
///< such bitmap exists.
|
|
///< If this is a true color OSD, a pointer to a dummy bitmap with 8bpp
|
|
///< is returned. This is done so that skins that call this function
|
|
///< in order to preset the bitmap's palette won't crash.
|
|
///< Use of this function outside of derived classes is deprecated and it
|
|
///< may be made 'protected' in a future version.
|
|
public:
|
|
virtual ~cOsd();
|
|
///< Shuts down the OSD.
|
|
static int OsdLeft(void) { return osdLeft ? osdLeft : Setup.OSDLeft; }
|
|
static int OsdTop(void) { return osdTop ? osdTop : Setup.OSDTop; }
|
|
static int OsdWidth(void) { return osdWidth ? osdWidth : Setup.OSDWidth; }
|
|
static int OsdHeight(void) { return osdHeight ? osdHeight : Setup.OSDHeight; }
|
|
static void SetOsdPosition(int Left, int Top, int Width, int Height);
|
|
///< Sets the position and size of the OSD to the given values.
|
|
///< This may be useful for plugins that determine the scaling of the
|
|
///< video image and need to scale the OSD accordingly to fit on the
|
|
///< screen.
|
|
static int IsOpen(void) { return Osds.Size() && Osds[0]->level == OSD_LEVEL_DEFAULT; }
|
|
///< Returns true if there is currently a level 0 OSD open.
|
|
bool IsTrueColor(void) const { return isTrueColor; }
|
|
///< Returns 'true' if this is a true color OSD (providing full 32 bit color
|
|
///< depth).
|
|
int Left(void) { return left; }
|
|
int Top(void) { return top; }
|
|
int Width(void) { return width; }
|
|
int Height(void) { return height; }
|
|
void SetAntiAliasGranularity(uint FixedColors, uint BlendColors);
|
|
///< Allows the system to optimize utilization of the limited color
|
|
///< palette entries when generating blended colors for anti-aliasing.
|
|
///< FixedColors is the maximum number of colors used, and BlendColors
|
|
///< is the maximum number of foreground/background color combinations
|
|
///< used with anti-aliasing. If this function is not called with
|
|
///< useful values, the palette may be filled up with many shades of
|
|
///< a single color combination, and may not be able to serve all
|
|
///< requested colors. By default the palette assumes there will be
|
|
///< 10 fixed colors and 10 color combinations.
|
|
///< If this is a true color OSD, this function does nothing.
|
|
virtual const cSize &MaxPixmapSize(void) const;
|
|
///< Returns the maximum possible size of a pixmap this OSD can create.
|
|
virtual cPixmap *CreatePixmap(int Layer, const cRect &ViewPort, const cRect &DrawPort = cRect::Null);
|
|
///< Creates a new true color pixmap on this OSD (see cPixmap for details).
|
|
///< The caller must not delete the returned object, it will be deleted when
|
|
///< the OSD is deleted. DestroyPixmap() can be called if a pixmap shall be
|
|
///< destroyed before the OSD is deleted.
|
|
///< If this is not a true color OSD, or if the pixmap could not be created
|
|
///< due to limited resources, this function returns NULL.
|
|
virtual void DestroyPixmap(cPixmap *Pixmap);
|
|
///< Destroys the given Pixmap, which has previously been created by a call to
|
|
///< CreatePixmap(). When the OSD is deleted, all pixmaps are destroyed
|
|
///< automatically. So this function only needs to be used if a pixmap shall
|
|
///< be destroyed while the OSD is still being used.
|
|
virtual void DrawImage(const cPoint &Point, const cImage &Image);
|
|
///< Draws the given Image on this OSD at the given Point.
|
|
///< If this is not a true color OSD, this function does nothing.
|
|
virtual void DrawImage(const cPoint &Point, int ImageHandle);
|
|
///< Draws the image referenced by the given ImageHandle on this OSD at
|
|
///< the given Point. ImageHandle must be a value that has previously been
|
|
///< returned by a call to cOsdProvider::StoreImage(). If ImageHandle
|
|
///< has an invalid value, nothing happens.
|
|
///< If this is not a true color OSD, this function does nothing.
|
|
virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas);
|
|
///< Checks whether the OSD can display the given set of sub-areas.
|
|
///< The return value indicates whether a call to SetAreas() with this
|
|
///< set of areas will succeed. CanHandleAreas() may be called with an
|
|
///< OSD that is already in use with other areas and will not interfere
|
|
///< with the current operation of the OSD.
|
|
///< A derived class must first call the base class CanHandleAreas()
|
|
///< to check the basic conditions, like not overlapping etc.
|
|
virtual eOsdError SetAreas(const tArea *Areas, int NumAreas);
|
|
///< Sets the sub-areas to the given areas.
|
|
///< The return value indicates whether the operation was successful.
|
|
///< If an error is reported, nothing will have changed and the previous
|
|
///< OSD (if any) will still be displayed as before.
|
|
///< If the OSD has been divided into several sub-areas, all areas that
|
|
///< are part of the rectangle that surrounds a given drawing operation
|
|
///< will be drawn into, with the proper offsets.
|
|
///< A new call overwrites any previous settings
|
|
///< To set up a true color OSD, exactly one area must be requested, with
|
|
///< its coordinates set to the full area the OSD shall cover, and the
|
|
///< bpp value set to 32.
|
|
virtual void SaveRegion(int x1, int y1, int x2, int y2);
|
|
///< Saves the region defined by the given coordinates for later restoration
|
|
///< through RestoreRegion(). Only one saved region can be active at any
|
|
///< given time.
|
|
virtual void RestoreRegion(void);
|
|
///< Restores the region previously saved by a call to SaveRegion().
|
|
///< If SaveRegion() has not been called before, nothing will happen.
|
|
virtual eOsdError SetPalette(const cPalette &Palette, int Area);
|
|
///< Sets the Palette for the given Area (the first area is numbered 0).
|
|
///< If this is a true color OSD, nothing happens and oeOk is returned.
|
|
virtual void DrawPixel(int x, int y, tColor Color);
|
|
///< Sets the pixel at the given coordinates to the given Color, which is
|
|
///< a full 32 bit ARGB value.
|
|
///< If the OSD area has been divided into separate sub-areas, and the
|
|
///< given coordinates don't fall into any of these sub-areas, no pixel will
|
|
///< be set.
|
|
virtual void DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg = 0, tColor ColorBg = 0, bool ReplacePalette = false, bool Overlay = false);
|
|
///< Sets the pixels in the OSD with the data from the given
|
|
///< Bitmap, putting the upper left corner of the Bitmap at (x, y).
|
|
///< If ColorFg or ColorBg is given, the first palette entry of the Bitmap
|
|
///< will be mapped to ColorBg and the second palette entry will be mapped to
|
|
///< ColorFg (palette indexes are defined so that 0 is the background and
|
|
///< 1 is the foreground color). ReplacePalette controls whether the target
|
|
///< area shall have its palette replaced with the one from Bitmap.
|
|
///< If Overlay is true, any pixel in Bitmap that has color index 0 will
|
|
///< not overwrite the corresponding pixel in the target area.
|
|
///< If this is a true color OSD, ReplacePalette has no meaning.
|
|
virtual void DrawScaledBitmap(int x, int y, const cBitmap &Bitmap, double FactorX, double FactorY, bool AntiAlias = false);
|
|
///< Sets the pixels in the OSD with the data from the given Bitmap, putting
|
|
///< the upper left corner of the Bitmap at (x, y) and scaled by the given
|
|
///< factors. If AntiAlias is true and either of the factors is greater than
|
|
///< 1.0, anti-aliasing is applied.
|
|
virtual void DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width = 0, int Height = 0, int Alignment = taDefault);
|
|
///< Draws the given string at coordinates (x, y) with the given foreground
|
|
///< and background color and font. If Width and Height are given, the text
|
|
///< will be drawn into a rectangle with the given size and the given
|
|
///< Alignment (default is top-left). If ColorBg is clrTransparent, no
|
|
///< background pixels will be drawn, which allows drawing "transparent" text.
|
|
virtual void DrawRectangle(int x1, int y1, int x2, int y2, tColor Color);
|
|
///< Draws a filled rectangle defined by the upper left (x1, y1) and lower right
|
|
///< (x2, y2) corners with the given Color.
|
|
virtual void DrawEllipse(int x1, int y1, int x2, int y2, tColor Color, int Quadrants = 0);
|
|
///< Draws a filled ellipse defined by the upper left (x1, y1) and lower right
|
|
///< (x2, y2) corners with the given Color. Quadrants controls which parts of
|
|
///< the ellipse are actually drawn:
|
|
///< 0 draws the entire ellipse
|
|
///< 1..4 draws only the first, second, third or fourth quadrant, respectively
|
|
///< 5..8 draws the right, top, left or bottom half, respectively
|
|
///< -1..-4 draws the inverted part of the given quadrant
|
|
///< If Quadrants is not 0, the coordinates are those of the actual area, not
|
|
///< the full circle!
|
|
virtual void DrawSlope(int x1, int y1, int x2, int y2, tColor Color, int Type);
|
|
///< Draws a "slope" into the rectangle defined by the upper left (x1, y1) and
|
|
///< lower right (x2, y2) corners with the given Color. Type controls the
|
|
///< direction of the slope and which side of it will be drawn:
|
|
///< 0: horizontal, rising, lower
|
|
///< 1: horizontal, rising, upper
|
|
///< 2: horizontal, falling, lower
|
|
///< 3: horizontal, falling, upper
|
|
///< 4: vertical, rising, lower
|
|
///< 5: vertical, rising, upper
|
|
///< 6: vertical, falling, lower
|
|
///< 7: vertical, falling, upper
|
|
virtual void Flush(void);
|
|
///< Actually commits all data to the OSD hardware.
|
|
///< Flush() should return as soon as possible.
|
|
///< For a true color OSD using the default implementation with in memory
|
|
///< pixmaps, the Flush() function should basically do something like this:
|
|
///<
|
|
///< LOCK_PIXMAPS;
|
|
///< while (cPixmapMemory *pm = dynamic_cast<cPixmapMemory *>(RenderPixmaps())) {
|
|
///< int w = pm->ViewPort().Width();
|
|
///< int h = pm->ViewPort().Height();
|
|
///< int d = w * sizeof(tColor);
|
|
///< MyOsdDrawPixmap(Left() + pm->ViewPort().X(), Top() + pm->ViewPort().Y(), pm->Data(), w, h, h * d);
|
|
///< DestroyPixmap(pm);
|
|
///< }
|
|
///<
|
|
///< If a plugin uses a derived cPixmap implementation, it needs to use that
|
|
///< type instead of cPixmapMemory.
|
|
};
|
|
|
|
#define MAXOSDIMAGES 64
|
|
|
|
class cOsdProvider {
|
|
friend class cPixmapMemory;
|
|
private:
|
|
static cOsdProvider *osdProvider;
|
|
static int oldWidth;
|
|
static int oldHeight;
|
|
static double oldAspect;
|
|
static cImage *images[MAXOSDIMAGES];
|
|
static int osdState;
|
|
protected:
|
|
virtual cOsd *CreateOsd(int Left, int Top, uint Level) = 0;
|
|
///< Returns a pointer to a newly created cOsd object, which will be located
|
|
///< at the given coordinates.
|
|
virtual bool ProvidesTrueColor(void) { return false; }
|
|
///< Returns true if this OSD provider is able to handle a true color OSD.
|
|
virtual int StoreImageData(const cImage &Image);
|
|
///< Copies the given Image and returns a handle for later reference.
|
|
///< A derived class can implement its own image storing mechanism by
|
|
///< reimplementing this function as well as DropImageData().
|
|
///< The base class implementation simply copies the image data to allow
|
|
///< plugins to always use this interface, no matter if the actual device
|
|
///< provides support for storing image data or not. The handles returned
|
|
///< by the default implementation are positive integers. A derived class
|
|
///< might want to use negative integers as handles, so that it can fall
|
|
///< back to using the base class image storing mechanism if, e.g., it runs
|
|
///< out of memory.
|
|
virtual void DropImageData(int ImageHandle);
|
|
///< Drops the image data referenced by ImageHandle.
|
|
static const cImage *GetImageData(int ImageHandle);
|
|
///< Gets the image data referenced by ImageHandle.
|
|
public:
|
|
cOsdProvider(void);
|
|
//XXX maybe parameter to make this one "sticky"??? (frame-buffer etc.)
|
|
virtual ~cOsdProvider();
|
|
static cOsd *NewOsd(int Left, int Top, uint Level = OSD_LEVEL_DEFAULT);
|
|
///< Returns a pointer to a newly created cOsd object, which will be located
|
|
///< at the given coordinates. When the cOsd object is no longer needed, the
|
|
///< caller must delete it. If the OSD is already in use, or there is no OSD
|
|
///< provider, a dummy OSD is returned so that the caller may always use the
|
|
///< returned pointer without having to check it every time it is accessed.
|
|
static void UpdateOsdSize(bool Force = false);
|
|
///< Inquires the actual size of the video display and adjusts the OSD and
|
|
///< font sizes accordingly. If Force is true, all settings are recalculated,
|
|
///< even if the video resolution hasn't changed since the last call to
|
|
///< this function.
|
|
static bool OsdSizeChanged(int &State);
|
|
///< Checks if the OSD size has changed and a currently displayed OSD needs to
|
|
///< be redrawn. An internal reference value is incremented on every size change
|
|
///< and is compared against State when calling the method.
|
|
///< OsdSizeChanged() can be called with an uninitialized State to just get
|
|
///< the current value of State.
|
|
static bool SupportsTrueColor(void);
|
|
///< Returns true if the current OSD provider is able to handle a true color OSD.
|
|
static int StoreImage(const cImage &Image);
|
|
///< Stores the given Image for later use with DrawImage() on an OSD or
|
|
///< pixmap. The returned number is a handle that must be used when
|
|
///< referencing this image in a call to DrawImage() or DropImage().
|
|
///< The image data is copied, so any later changes to Image will have
|
|
///< no effect on the stored image.
|
|
///< A derived class may be able to copy frequently used images to some
|
|
///< space where they can be retrieved faster than using a cImage in each call.
|
|
///< If this is not a true color OSD, or if the image data can't be stored for
|
|
///< any reason, this function returns 0 and nothing is stored.
|
|
static void DropImage(int ImageHandle);
|
|
///< Drops the image referenced by the given ImageHandle. If ImageHandle
|
|
///< has an invalid value, nothing happens.
|
|
static void Shutdown(void);
|
|
///< Shuts down the OSD provider facility by deleting the current OSD provider.
|
|
};
|
|
|
|
class cTextScroller {
|
|
private:
|
|
cOsd *osd;
|
|
int left, top, width, height;
|
|
const cFont *font;
|
|
tColor colorFg, colorBg;
|
|
int offset, shown;
|
|
cTextWrapper textWrapper;
|
|
void DrawText(void);
|
|
public:
|
|
cTextScroller(void);
|
|
cTextScroller(cOsd *Osd, int Left, int Top, int Width, int Height, const char *Text, const cFont *Font, tColor ColorFg, tColor ColorBg);
|
|
void Set(cOsd *Osd, int Left, int Top, int Width, int Height, const char *Text, const cFont *Font, tColor ColorFg, tColor ColorBg);
|
|
void Reset(void);
|
|
int Left(void) { return left; }
|
|
int Top(void) { return top; }
|
|
int Width(void) { return width; }
|
|
int Height(void) { return height; }
|
|
int Total(void) { return textWrapper.Lines(); }
|
|
int Offset(void) { return offset; }
|
|
int Shown(void) { return shown; }
|
|
bool CanScroll(void) { return CanScrollUp() || CanScrollDown(); }
|
|
bool CanScrollUp(void) { return offset > 0; }
|
|
bool CanScrollDown(void) { return offset + shown < Total(); }
|
|
void Scroll(bool Up, bool Page);
|
|
};
|
|
|
|
#endif //__OSD_H
|