1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
|
/*************************************************************** -*- c++ -*-
* Copyright (c) 2005 by Udo Richter *
* Copyright (c) 2021 by Peter Bieringer (extenions) *
* *
* txtrender.h - Teletext display abstraction and teletext code *
* renderer *
* *
* 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. *
* *
***************************************************************************/
#ifndef OSDTELETEXT_TXTRENDER_H_
#define OSDTELETEXT_TXTRENDER_H_
#include <stdio.h>
#include <vdr/tools.h>
// Teletext character sets
enum enumCharsets {
CHARSET_LATIN_G0 = 0x0000, // native latin (partially todo)
CHARSET_LATIN_G0_CZ_SK = 0x0100, // Czech/Slovak (todo)
CHARSET_LATIN_G0_EN = 0x0200, // English
CHARSET_LATIN_G0_EE = 0x0300, // Estonian (todo)
CHARSET_LATIN_G0_FR = 0x0400, // French
CHARSET_LATIN_G0_DE = 0x0500, // German
CHARSET_LATIN_G0_IT = 0x0600, // Italian
CHARSET_LATIN_G0_LV_LT = 0x0700, // Lettish/Lithuanian (todo)
CHARSET_LATIN_G0_PL = 0x0800, // Polish (todo)
CHARSET_LATIN_G0_PT_ES = 0x0900, // Portuguese/Spanish
CHARSET_LATIN_G0_RO = 0x0A00, // Romanian (todo)
CHARSET_LATIN_G0_SR_HR_SL = 0x0B00, // Serbian/Croatian/Slovenian (todo)
CHARSET_LATIN_G0_SV_FI = 0x0C00, // Swedish/Finnish
CHARSET_LATIN_G0_TR = 0x0D00, // Turkish (todo)
CHARSET_LATIN_G2 = 0x0E00, // Latin G2 supplementary set (todo)
CHARSET_CYRILLIC_G0_SR_HR = 0x0F00, // Serbian/Croatian (todo)
CHARSET_CYRILLIC_G0_RU_BG = 0x1000, // Russian/Bulgarian (todo)
CHARSET_CYRILLIC_G0_UK = 0x1100, // Ukrainian (todo)
CHARSET_CYRILLIC_G2 = 0x1200, // Cyrillic G2 Supplementary (todo)
CHARSET_GREEK_G0 = 0x1300, // Greek G0 (todo)
CHARSET_GREEK_G2 = 0x1400, // Greeek G2 (todo)
CHARSET_ARABIC_G0 = 0x1500, // Arabic G0 (todo)
CHARSET_ARABIC_G2 = 0x1600, // Arabic G2 (todo)
CHARSET_HEBREW_G0 = 0x1700, // Hebrew G0 (todo)
CHARSET_GRAPHICS_G1 = 0x1800, // G1 graphics set
CHARSET_GRAPHICS_G1_SEP = 0x1900, // G1 graphics set, separated
CHARSET_GRAPHICS_G3 = 0x1A00, // G3 graphics set (todo)
CHARSET_INVALID = 0x1F00 // no charset defined
};
// Macro to get the lowest non-0 bit position from a bit mask
// Should evaluate to const on a const mask
#define LowestSet2Bit(mask) ((mask)&0x0001?0:1)
#define LowestSet4Bit(mask) ((mask)&0x0003?LowestSet2Bit(mask):LowestSet2Bit((mask)>>2)+2)
#define LowestSet8Bit(mask) ((mask)&0x000f?LowestSet4Bit(mask):LowestSet4Bit((mask)>>4)+4)
#define LowestSet16Bit(mask) ((mask)&0x00ff?LowestSet8Bit(mask):LowestSet8Bit((mask)>>8)+8)
#define LowestSet32Bit(mask) ((mask)&0xffff?LowestSet16Bit(mask):LowestSet16Bit((mask)>>16)+16)
// Character modifcation double height:
enum enumDblHeight {
dblh_Normal=0x00000000, // normal height
dblh_Top =0x04000000, // upper half character
dblh_Bottom=0x08000000 // lower half character
};
// Character modifcation double width:
enum enumDblWidth {
dblw_Normal=0x00000000, // normal width
dblw_Left =0x10000000, // left half character
dblw_Right =0x20000000 // right half character
};
// Teletext colors
enum enumTeletextColor {
// level 1:
ttcBlack=0,
ttcRed=1,
ttcGreen=2,
ttcYellow=3,
ttcBlue=4,
ttcMagenta=5,
ttcCyan=6,
ttcWhite=7,
// level 2.5:
ttcTransparent=8,
ttcHalfRed=9,
ttcHalfGreen=10,
ttcHalfYellow=11,
ttcHalfBlue=12,
ttcHalfMagenta=13,
ttcHalfCyan=14,
ttcGrey=15,
// unnamed, level 2.5:
ttcColor16=16, ttcColor17=17, ttcColor18=18, ttcColor19=19,
ttcColor20=20, ttcColor21=21, ttcColor22=22, ttcColor23=23,
ttcColor24=24, ttcColor25=25, ttcColor26=26, ttcColor27=27,
ttcColor28=28, ttcColor29=29, ttcColor30=30, ttcColor31=31,
ttcFirst=0, ttcLast=31
};
inline enumTeletextColor& operator++(enumTeletextColor& c) { return c=enumTeletextColor(int(c)+1); }
inline enumTeletextColor operator++(enumTeletextColor& c, int) { enumTeletextColor tmp(c); ++c; return tmp; }
class cTeletextChar {
// Wrapper class that represents a teletext character,
// including colors and effects. Should optimize back
// to 4 byte unsigned int on compile.
protected:
unsigned int c;
static const unsigned int CHAR = 0x000000FF;
// character code
static const unsigned int CHARSET = 0x00001F00;
// character set code, see below
static const unsigned int BOXOUT = 0x00004000;
// 'boxed' mode hidden area
static const unsigned int DIRTY = 0x00008000;
// 'dirty' bit - internal marker only
static const unsigned int FGCOLOR = 0x001F0000;
// 5-bit foreground color code, 3 bit used for now
static const unsigned int BGCOLOR = 0x03E00000;
// 5-bit background color code, 3 bit used for now
static const unsigned int DBLHEIGHT = 0x0C000000;
// show double height
static const unsigned int DBLWIDTH = 0x30000000;
// show double width (todo)
static const unsigned int CONCEAL = 0x40000000;
// character concealed
static const unsigned int BLINK = 0x80000000;
// blinking character
cTeletextChar(unsigned int cc) { c=cc; }
public:
cTeletextChar() { c=0; }
// inline helper functions:
// For each parameter encoded into the 32-bit int, there is
// a Get...() to read, a Set...() to write, and a To...() to
// return a modified copy
inline unsigned int GetC() { return c;};
inline unsigned char GetChar()
{ return c&CHAR; }
inline void SetChar(unsigned char chr)
{ c=(c&~CHAR)|chr; }
inline cTeletextChar ToChar(unsigned char chr)
{ return cTeletextChar((c&~CHAR)|chr); }
inline enumCharsets GetCharset()
{ return (enumCharsets)(c&CHARSET); }
inline void SetCharset(enumCharsets charset)
{ c=(c&~CHARSET)|charset; }
inline cTeletextChar ToCharset(enumCharsets charset)
{ return cTeletextChar((c&~CHARSET)|charset); }
inline enumTeletextColor GetFGColor()
{ return (enumTeletextColor)((c&FGCOLOR) >> LowestSet32Bit(FGCOLOR)); }
inline void SetFGColor(enumTeletextColor fgc)
{ c=(c&~FGCOLOR) | (fgc << LowestSet32Bit(FGCOLOR)); }
inline cTeletextChar ToFGColor(enumTeletextColor fgc)
{ return cTeletextChar((c&~FGCOLOR) | (fgc << LowestSet32Bit(FGCOLOR))); }
inline enumTeletextColor GetBGColor()
{ return (enumTeletextColor)((c&BGCOLOR) >> LowestSet32Bit(BGCOLOR)); }
inline void SetBGColor(enumTeletextColor bgc)
{ c=(c&~BGCOLOR) | (bgc << LowestSet32Bit(BGCOLOR)); }
inline cTeletextChar ToBGColor(enumTeletextColor bgc)
{ return cTeletextChar((c&~BGCOLOR) | (bgc << LowestSet32Bit(BGCOLOR))); }
inline bool GetBoxedOut()
{ return c&BOXOUT; }
inline void SetBoxedOut(bool BoxedOut)
{ c=(BoxedOut)?(c|BOXOUT):(c&~BOXOUT); }
inline cTeletextChar ToBoxedOut(bool BoxedOut)
{ return cTeletextChar((BoxedOut)?(c|BOXOUT):(c&~BOXOUT)); }
inline bool GetDirty()
{ return c&DIRTY; }
inline void SetDirty(bool Dirty)
{ c=(Dirty)?(c|DIRTY):(c&~DIRTY); }
inline cTeletextChar ToDirty(bool Dirty)
{ return cTeletextChar((Dirty)?(c|DIRTY):(c&~DIRTY)); }
inline enumDblHeight GetDblHeight()
{ return (enumDblHeight)(c&DBLHEIGHT); }
inline void SetDblHeight(enumDblHeight dh)
{ c=(c&~(DBLHEIGHT)) | dh; }
inline cTeletextChar ToDblHeight(enumDblHeight dh)
{ return cTeletextChar((c&~(DBLHEIGHT)) | dh); }
inline enumDblWidth GetDblWidth()
{ return (enumDblWidth)(c&DBLWIDTH); }
inline void SetDblWidth(enumDblWidth dw)
{ c=(c&~(DBLWIDTH)) | dw; }
inline cTeletextChar ToDblWidth(enumDblWidth dw)
{ return cTeletextChar((c&~(DBLWIDTH)) | dw); }
inline bool GetConceal()
{ return c&CONCEAL; }
inline void SetConceal(bool Conceal)
{ c=(Conceal)?(c|CONCEAL):(c&~CONCEAL); }
inline cTeletextChar ToConceal(bool Conceal)
{ return cTeletextChar((Conceal)?(c|CONCEAL):(c&~CONCEAL)); }
inline bool GetBlink()
{ return c&BLINK; }
inline void SetBlink(bool Blink)
{ c=(Blink)?(c|BLINK):(c&~BLINK); }
inline cTeletextChar ToBlink(bool Blink)
{ return cTeletextChar((Blink)?(c|BLINK):(c&~BLINK)); }
bool operator==(cTeletextChar &chr) { return c==chr.c; }
bool operator!=(cTeletextChar &chr) { return c!=chr.c; }
};
class cRenderPage {
// Abstraction of a 40x25 teletext character page
// with all special attributes and colors
// Additionally tracks changes by maintaining a
// 'dirty' flag on each character
protected:
cTeletextChar Page[40][27];
int Flags;
// 0x80 C4 - Erase page
// 0x40 C5 - News flash
// 0x20 C6 - Subtitle
// 0x10 C7 - Suppress Header
// 0x08 C8 - Update
// 0x04 C9 - Interrupt Sequence
// 0x02 C10 - Inhibit Display
// 0x01 C11 - Magazine Serial mode
int Lang;
// 3-bit language number from header
bool Dirty; // At least one character is dirty
bool DirtyAll; // Consider all characters dirty, regardless of flag
// Font Code pages
int FirstG0CodePage; // 7-bit number, lower 3 bits ignored
int SecondG0CodePage; // 7-bit number
public:
cRenderPage();
#define CHECK_XY_LIMIT(x,y) ((x < 0) || (x >= 40) || (y < 0) || (y >= 27))
cTeletextChar GetChar(int x, int y) {
// Read character content from page
if (CHECK_XY_LIMIT(x,y)) {
esyslog("osdteletext: WARN: out of bounds access to teletext page (GetChar x=%d y=%d)", x, y);
return cTeletextChar();
}
return Page[x][y].ToDirty(false);
}
bool IsDirty() {
// global dirty status
return Dirty;
}
bool IsDirty(int x, int y) {
// local dirty status
if (CHECK_XY_LIMIT(x,y)) {
esyslog("osdteletext: WARN: out of bounds access to teletext page (IsDirty x=%d y=%d)", x, y);
return false;
}
return Page[x][y].GetDirty() | DirtyAll;
}
void MakeDirty(int x, int y) {
// force one character dirty
if (CHECK_XY_LIMIT(x,y)) {
esyslog("osdteletext: WARN: out of bounds access to teletext page (MakeDirty x=%d y=%d)", x, y);
return;
}
Page[x][y].SetDirty(true);
Dirty=true;
}
void SetChar(int x, int y, cTeletextChar c) {
// Set character at given location
if (CHECK_XY_LIMIT(x,y)) {
esyslog("osdteletext: WARN: out of bounds access to teletext page (SetChar x=%d y=%d c=%x)", x, y, c.GetC());
return;
}
if (GetChar(x,y) != c) {
Page[x][y]=c.ToDirty(true);
Dirty=true;
}
}
void ReadTeletextHeader(unsigned char *Header);
// Read header from teletext page
// Header must be a 12 bytes buffer
void RenderTeletextCode(unsigned char *PageCode);
// Interprete teletext code referenced by PageCode
// and draw the whole page content into this object
// PageCode must be a buffer containing TelePageData structure (see storage.h)
};
#endif
|