diff options
Diffstat (limited to 'txtrender.h')
-rw-r--r-- | txtrender.h | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/txtrender.h b/txtrender.h new file mode 100644 index 0000000..e7da20d --- /dev/null +++ b/txtrender.h @@ -0,0 +1,311 @@ +/*************************************************************************** + * * + * 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. * + * * + * Changelog: * + * 2005-03 initial version (c) Udo Richter * + * * + ***************************************************************************/ + +#ifndef OSDTELETEXT_TXTRENDER_H_ +#define OSDTELETEXT_TXTRENDER_H_ + +#include <stdio.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, // Portugese/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 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][25]; + + 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(); + + cTeletextChar GetChar(int x, int y) { + // Read character content from page + if (x<0 || x>=40 || y<0 || y>=25) { + printf("Warning: out of bounds read access to teletext page\n"); + 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 (x<0 || x>=40 || y<0 || y>=25) { + printf("Warning: out of bounds read access to teletext page\n"); + return false; + } + return Page[x][y].GetDirty() | DirtyAll; + } + + void MakeDirty(int x, int y) { + // force one character dirty + if (x<0 || x>=40 || y<0 || y>=25) { + printf("Warning: out of bounds write access to teletext page\n"); + return; + } + Page[x][y].SetDirty(true); + Dirty=true; + } + + void SetChar(int x, int y, cTeletextChar c) { + // Set character at given location + + if (x<0 || x>=40 || y<0 || y>=25) { + printf("Warning: out of bounds write access to teletext page\n"); + 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 40*24 bytes buffer +}; + + + +#endif |