diff options
author | Tobias Grimm <tobias@e-tobi.loc> | 2008-12-02 21:00:33 +0100 |
---|---|---|
committer | Tobias Grimm <tobias@e-tobi.loc> | 2008-12-02 21:00:33 +0100 |
commit | b451fdb5a36c0f749d63d53165cdf4e84a8f476a (patch) | |
tree | aa3b6548ea52ef133028098c8fbaebbe47ed8a5d /display.c | |
download | vdr-plugin-osdteletext-b451fdb5a36c0f749d63d53165cdf4e84a8f476a.tar.gz vdr-plugin-osdteletext-b451fdb5a36c0f749d63d53165cdf4e84a8f476a.tar.bz2 |
Initial commit of version 0.5.1v0.5.1release/v0.5.1
Diffstat (limited to 'display.c')
-rw-r--r-- | display.c | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/display.c b/display.c new file mode 100644 index 0000000..c9ac59f --- /dev/null +++ b/display.c @@ -0,0 +1,240 @@ +/*************************************************************************** + * * + * display.c - Actual implementation of OSD display variants and * + * Display:: namespace that encapsulates a single cDisplay. * + * * + * 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. * + * * + * Changelog: * + * 2005-03 initial version (c) Udo Richter * + * * + ***************************************************************************/ + +#include <strings.h> +#include <vdr/config.h> +#include "setup.h" +#include "display.h" +#include "txtfont.h" + +// Static variables of Display:: namespace +Display::Mode Display::mode=Display::Full; +cDisplay *Display::display=NULL; + + +void Display::SetMode(Display::Mode NewMode) { + // (re-)set display mode. + + if (display!=NULL && NewMode==mode) return; + // No change, nothing to do + + // OSD origin, centered on VDR OSD + int x0=Setup.OSDLeft+(Setup.OSDWidth-ttSetup.OSDwidth)*ttSetup.OSDHAlign/100; + int y0=Setup.OSDTop +(Setup.OSDHeight-ttSetup.OSDheight)*ttSetup.OSDVAlign/100; + + switch (NewMode) { + case Display::Full: + // Need to re-initialize *display: + Delete(); + // Try 4BPP display first: + display=new cDisplay4BPP(x0,y0,ttSetup.OSDwidth,ttSetup.OSDheight); + if (!display->Valid()) { + // Failed, possibly out of memory + delete display; + // Try 2BPP display + display=new cDisplay2BPP(x0,y0,ttSetup.OSDwidth,ttSetup.OSDheight); + } + break; + case Display::HalfUpper: + // Shortcut to switch from HalfUpper to HalfLower: + if (mode==Display::HalfLower) { + // keep instance. + ((cDisplay4BPPHalf*)display)->SetUpper(true); + break; + } + // Need to re-initialize *display: + Delete(); + display=new cDisplay4BPPHalf(x0,y0,ttSetup.OSDwidth,ttSetup.OSDheight,true); + break; + case Display::HalfLower: + // Shortcut to switch from HalfUpper to HalfLower: + if (mode==Display::HalfUpper) { + // keep instance. + ((cDisplay4BPPHalf*)display)->SetUpper(false); + break; + } + // Need to re-initialize *display: + Delete(); + display=new cDisplay4BPPHalf(x0,y0,ttSetup.OSDwidth,ttSetup.OSDheight,false); + break; + } + mode=NewMode; + // If display is invalid, clean up immediately: + if (!display->Valid()) Delete(); + // Pass through OSD black transparency + SetBackgroundColor((tColor)ttSetup.configuredClrBackground); +} + +void Display::ShowUpperHalf() { + // Enforce upper half of screen to be visible + if (GetZoom()==cDisplay::Zoom_Lower) + SetZoom(cDisplay::Zoom_Upper); + if (mode==HalfLower) + SetMode(HalfUpper); +} + + + + + + +cDisplay2BPP::cDisplay2BPP(int x0, int y0, int width, int height) + : cDisplay(width,height) { + // 2BPP display with color mapping + + osd = cOsdProvider::NewOsd(x0, y0); + if (!osd) return; + + width=(width+3)&~3; + // Width has to end on byte boundary, so round up + + tArea Areas[] = { { 0, 0, width - 1, height - 1, 2 } }; + if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) != oeOk) { + delete osd; + osd=NULL; + return; + } + osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); + + InitPalette(); + + InitScaler(); + + CleanDisplay(); +} + +tColor cDisplay2BPP::GetColorRGB(enumTeletextColor ttc, int Area) { + switch (ttc) { + case ttcBlack: return Background; + case ttcRed: return clrRed; + case ttcGreen: return clrYellow; + case ttcYellow: return clrYellow; + case ttcBlue: return Background; + case ttcMagenta: return clrRed; + case ttcCyan: return clrCyan; + case ttcWhite: return clrCyan; + case ttcTransparent: return Background; + default: return Background; + } +} + +tColor cDisplay2BPP::GetColorRGBAlternate(enumTeletextColor ttc, int Area) { + switch (ttc) { + case ttcBlack: return clrCyan; + case ttcRed: return clrYellow; + case ttcGreen: return clrRed; + case ttcYellow: return clrRed; + case ttcBlue: return clrCyan; + case ttcMagenta: return clrYellow; + case ttcCyan: return Background; + case ttcWhite: return Background; + case ttcTransparent: return clrCyan; + default: return Background; + } +} + + + + + +cDisplay4BPP::cDisplay4BPP(int x0, int y0, int width, int height) + : cDisplay(width,height) { + // 4BPP display for memory-modded DVB cards and other OSD providers + + osd = cOsdProvider::NewOsd(x0, y0); + if (!osd) return; + + width=(width+1)&~1; + // Width has to end on byte boundary, so round up + + tArea Areas[] = { { 0, 0, width - 1, height - 1, 4 } }; + if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) != oeOk) { + delete osd; + osd=NULL; + return; + } + osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); + + InitPalette(); + + InitScaler(); + + CleanDisplay(); +} + + +cDisplay4BPPHalf::cDisplay4BPPHalf(int x0, int y0, int width, int height, bool upper) + : cDisplay(width,height) { + + OsdX0=x0; + OsdY0=y0; + Upper=upper; + osd=NULL; + + // Redirect all real init work to method + InitOSD(); +} + +void cDisplay4BPPHalf::InitOSD() { + if (osd) delete osd; + osd = cOsdProvider::NewOsd(OsdX0, OsdY0); + if (!osd) return; + + int width=(Width+1)&~1; + // Width has to end on byte boundary, so round up + + tArea Areas[] = { { 0, 0, width - 1, Height - 1, 4 } }; + // Try full-size area first + + while (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) != oeOk) { + // Out of memory, so shrink + if (Upper) { + // Move up lower border + Areas[0].y2=Areas[0].y2-1; + } else { + // Move down upper border + Areas[0].y1=Areas[0].y1+1; + } + if (Areas[0].y1>Areas[0].y2) { + // Area is empty, fail miserably + delete osd; + osd=NULL; + return; + } + } + // Add some backup + // CanHandleAreas is not accurate enough + if (Upper) { + Areas[0].y2=Areas[0].y2-10; + } else { + Areas[0].y1=Areas[0].y1+10; + } + + osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); + + InitPalette(); + + InitScaler(); + + CleanDisplay(); + + // In case we switched on the fly, do a full redraw + Dirty=true; + DirtyAll=true; + Flush(); +} + + + |