2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
10 * Most Codeparts are taken from the TuxBox Teletext plugin which is based
11 * upon videotext-0.6.19991029 and written by Thomas Loewe (LazyT),
12 * Roland Meier and DBLuelle. See http://www.tuxtxt.net/ for more information.
13 * Many thanks to the TuxBox Teletext Team for this great work.
18 #include "application/ApplicationComponents.h"
19 #include "application/ApplicationPlayer.h"
20 #include "filesystem/SpecialProtocol.h"
21 #include "input/Key.h"
22 #include "utils/log.h"
23 #include "windowing/GraphicContext.h"
25 #include <harfbuzz/hb-ft.h>
27 using namespace std::chrono_literals
;
29 static inline void SDL_memset4(uint32_t* dst
, uint32_t val
, size_t len
)
31 for (; len
> 0; --len
)
34 #define SDL_memcpy4(dst, src, len) memcpy(dst, src, (len) << 2)
36 static const char *TeletextFont
= "special://xbmc/media/Fonts/teletext.ttf";
38 /* spacing attributes */
39 #define alpha_black 0x00
40 #define alpha_red 0x01
41 #define alpha_green 0x02
42 #define alpha_yellow 0x03
43 #define alpha_blue 0x04
44 #define alpha_magenta 0x05
45 #define alpha_cyan 0x06
46 #define alpha_white 0x07
50 #define start_box 0x0B
51 #define normal_size 0x0C
52 #define double_height 0x0D
53 #define double_width 0x0E
54 #define double_size 0x0F
55 #define mosaic_black 0x10
56 #define mosaic_red 0x11
57 #define mosaic_green 0x12
58 #define mosaic_yellow 0x13
59 #define mosaic_blue 0x14
60 #define mosaic_magenta 0x15
61 #define mosaic_cyan 0x16
62 #define mosaic_white 0x17
64 #define contiguous_mosaic 0x19
65 #define separated_mosaic 0x1A
67 #define black_background 0x1C
68 #define new_background 0x1D
69 #define hold_mosaic 0x1E
70 #define release_mosaic 0x1F
72 #define RowAddress2Row(row) ((row == 40) ? 24 : (row - 40))
74 // G2 Set as defined in ETS 300 706
75 const unsigned short int G2table
[5][6*16] =
77 // Latin G2 Supplementary Set
78 { 0x0020, 0x00A1, 0x00A2, 0x00A3, 0x0024, 0x00A5, 0x0023, 0x00A7, 0x00A4, 0x2018, 0x201C, 0x00AB, 0x2190, 0x2191, 0x2192, 0x2193,
79 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00D7, 0x00B5, 0x00B6, 0x00B7, 0x00F7, 0x2019, 0x201D, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
80 0x0020, 0x0300, 0x0301, 0x02C6, 0x0303, 0x02C9, 0x02D8, 0x02D9, 0x00A8, 0x002E, 0x02DA, 0x00B8, 0x005F, 0x02DD, 0x02DB, 0x02C7,
81 0x2014, 0x00B9, 0x00AE, 0x00A9, 0x2122, 0x266A, 0x20AC, 0x2030, 0x03B1, 0x0020, 0x0020, 0x0020, 0x215B, 0x215C, 0x215D, 0x215E,
82 0x2126, 0x00C6, 0x00D0, 0x00AA, 0x0126, 0x0020, 0x0132, 0x013F, 0x0141, 0x00D8, 0x0152, 0x00BA, 0x00DE, 0x0166, 0x014A, 0x0149,
83 0x0138, 0x00E6, 0x0111, 0x00F0, 0x0127, 0x0131, 0x0133, 0x0140, 0x0142, 0x00F8, 0x0153, 0x00DF, 0x00FE, 0x0167, 0x014B, 0x25A0},
84 // Cyrillic G2 Supplementary Set
85 { 0x0020, 0x00A1, 0x00A2, 0x00A3, 0x0024, 0x00A5, 0x0020, 0x00A7, 0x0020, 0x2018, 0x201C, 0x00AB, 0x2190, 0x2191, 0x2192, 0x2193,
86 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00D7, 0x00B5, 0x00B6, 0x00B7, 0x00F7, 0x2019, 0x201D, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
87 0x0020, 0x0300, 0x0301, 0x02C6, 0x02DC, 0x02C9, 0x02D8, 0x02D9, 0x00A8, 0x002E, 0x02DA, 0x00B8, 0x005F, 0x02DD, 0x02DB, 0x02C7,
88 0x2014, 0x00B9, 0x00AE, 0x00A9, 0x2122, 0x266A, 0x20AC, 0x2030, 0x03B1, 0x0141, 0x0142, 0x00DF, 0x215B, 0x215C, 0x215D, 0x215E,
89 0x0044, 0x0045, 0x0046, 0x0047, 0x0049, 0x004A, 0x004B, 0x004C, 0x004E, 0x0051, 0x0052, 0x0053, 0x0055, 0x0056, 0x0057, 0x005A,
90 0x0064, 0x0065, 0x0066, 0x0067, 0x0069, 0x006A, 0x006B, 0x006C, 0x006E, 0x0071, 0x0072, 0x0073, 0x0075, 0x0076, 0x0077, 0x007A},
91 // Greek G2 Supplementary Set
92 { 0x0020, 0x0061, 0x0062, 0x00A3, 0x0065, 0x0068, 0x0069, 0x00A7, 0x003A, 0x2018, 0x201C, 0x006B, 0x2190, 0x2191, 0x2192, 0x2193,
93 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00D7, 0x006D, 0x006E, 0x0070, 0x00F7, 0x2019, 0x201D, 0x0074, 0x00BC, 0x00BD, 0x00BE, 0x0078,
94 0x0020, 0x0300, 0x0301, 0x02C6, 0x02DC, 0x02C9, 0x02D8, 0x02D9, 0x00A8, 0x002E, 0x02DA, 0x00B8, 0x005F, 0x02DD, 0x02DB, 0x02C7,
95 0x003F, 0x00B9, 0x00AE, 0x00A9, 0x2122, 0x266A, 0x20AC, 0x2030, 0x03B1, 0x038A, 0x038E, 0x038F, 0x215B, 0x215C, 0x215D, 0x215E,
96 0x0043, 0x0044, 0x0046, 0x0047, 0x004A, 0x004C, 0x0051, 0x0052, 0x0053, 0x0055, 0x0056, 0x0057, 0x0059, 0x005A, 0x0386, 0x0389,
97 0x0063, 0x0064, 0x0066, 0x0067, 0x006A, 0x006C, 0x0071, 0x0072, 0x0073, 0x0075, 0x0076, 0x0077, 0x0079, 0x007A, 0x0388, 0x25A0},
99 { 0x0020, 0x0639, 0xFEC9, 0xFE83, 0xFE85, 0xFE87, 0xFE8B, 0xFE89, 0xFB7C, 0xFB7D, 0xFB7A, 0xFB58, 0xFB59, 0xFB56, 0xFB6D, 0xFB8E,
100 0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, 0x0668, 0x0669, 0xFECE, 0xFECD, 0xFEFC, 0xFEEC, 0xFEEA, 0xFEE9,
101 0x00E0, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
102 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x00EB, 0x00EA, 0x00F9, 0x00EE, 0xFECA,
103 0x00E9, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
104 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x00E2, 0x00F4, 0x00FB, 0x00E7, 0x25A0}
107 //const (avoid warnings :<)
108 TextPageAttr_t Text_AtrTable
[] =
110 { TXT_ColorWhite
, TXT_ColorBlack
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_WB */
111 { TXT_ColorWhite
, TXT_ColorBlack
, C_G0P
, 0, 0, 1 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_PassiveDefault */
112 { TXT_ColorWhite
, TXT_ColorRed
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_L250 */
113 { TXT_ColorBlack
, TXT_ColorGreen
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_L251 */
114 { TXT_ColorBlack
, TXT_ColorYellow
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_L252 */
115 { TXT_ColorWhite
, TXT_ColorBlue
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_L253 */
116 { TXT_ColorMagenta
, TXT_ColorBlack
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_TOPMENU0 */
117 { TXT_ColorGreen
, TXT_ColorBlack
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_TOPMENU1 */
118 { TXT_ColorYellow
, TXT_ColorBlack
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_TOPMENU2 */
119 { TXT_ColorCyan
, TXT_ColorBlack
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_TOPMENU3 */
120 { TXT_ColorMenu2
, TXT_ColorMenu3
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MSG0 */
121 { TXT_ColorYellow
, TXT_ColorMenu3
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MSG1 */
122 { TXT_ColorMenu2
, TXT_ColorTransp
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MSG2 */
123 { TXT_ColorWhite
, TXT_ColorMenu3
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MSG3 */
124 { TXT_ColorMenu2
, TXT_ColorMenu1
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MSGDRM0 */
125 { TXT_ColorYellow
, TXT_ColorMenu1
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MSGDRM1 */
126 { TXT_ColorMenu2
, TXT_ColorBlack
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MSGDRM2 */
127 { TXT_ColorWhite
, TXT_ColorMenu1
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MSGDRM3 */
128 { TXT_ColorMenu1
, TXT_ColorBlue
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MENUHIL0 5a Z */
129 { TXT_ColorWhite
, TXT_ColorBlue
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MENUHIL1 58 X */
130 { TXT_ColorMenu2
, TXT_ColorTransp
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MENUHIL2 9b õ */
131 { TXT_ColorMenu2
, TXT_ColorMenu1
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MENU0 ab ´ */
132 { TXT_ColorYellow
, TXT_ColorMenu1
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MENU1 a4 § */
133 { TXT_ColorMenu2
, TXT_ColorTransp
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MENU2 9b õ */
134 { TXT_ColorMenu2
, TXT_ColorMenu3
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MENU3 cb À */
135 { TXT_ColorCyan
, TXT_ColorMenu3
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MENU4 c7 « */
136 { TXT_ColorWhite
, TXT_ColorMenu3
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MENU5 c8 » */
137 { TXT_ColorWhite
, TXT_ColorMenu1
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MENU6 a8 ® */
138 { TXT_ColorYellow
, TXT_ColorMenu1
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_CATCHMENU0 a4 § */
139 { TXT_ColorWhite
, TXT_ColorMenu1
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f} /* ATR_CATCHMENU1 a8 ® */
146 S_FHL
, /* full horizontal line: y-offset */
147 S_FVL
, /* full vertical line: x-offset */
148 S_BOX
, /* rectangle: x-offset, y-offset, width, height */
149 S_TRA
, /* trapez: x0, y0, l0, x1, y1, l1 */
150 S_BTR
, /* trapez in bgcolor: x0, y0, l0, x1, y1, l1 */
152 S_LNK
, /* call other shape: shapenumber */
153 S_CHR
, /* Character from freetype hibyte, lowbyte */
154 S_ADT
, /* Character 2F alternating raster */
155 S_FLH
, /* flip horizontal */
156 S_FLV
/* flip vertical */
159 /* shape coordinates */
162 S_W13
= 5, /* width*1/3 */
163 S_W12
, /* width*1/2 */
164 S_W23
, /* width*2/3 */
167 S_H13
, /* height*1/3 */
168 S_H12
, /* height*1/2 */
169 S_H23
, /* height*2/3 */
175 unsigned char aG3_20
[] = { S_TRA
, 0, S_H23
, 1, 0, S_H11
, S_W12
, S_END
};
176 unsigned char aG3_21
[] = { S_TRA
, 0, S_H23
, 1, 0, S_H11
, S_W11
, S_END
};
177 unsigned char aG3_22
[] = { S_TRA
, 0, S_H12
, 1, 0, S_H11
, S_W12
, S_END
};
178 unsigned char aG3_23
[] = { S_TRA
, 0, S_H12
, 1, 0, S_H11
, S_W11
, S_END
};
179 unsigned char aG3_24
[] = { S_TRA
, 0, 0, 1, 0, S_H11
, S_W12
, S_END
};
180 unsigned char aG3_25
[] = { S_TRA
, 0, 0, 1, 0, S_H11
, S_W11
, S_END
};
181 unsigned char aG3_26
[] = { S_INV
, S_LNK
, 0x66, S_END
};
182 unsigned char aG3_27
[] = { S_INV
, S_LNK
, 0x67, S_END
};
183 unsigned char aG3_28
[] = { S_INV
, S_LNK
, 0x68, S_END
};
184 unsigned char aG3_29
[] = { S_INV
, S_LNK
, 0x69, S_END
};
185 unsigned char aG3_2a
[] = { S_INV
, S_LNK
, 0x6a, S_END
};
186 unsigned char aG3_2b
[] = { S_INV
, S_LNK
, 0x6b, S_END
};
187 unsigned char aG3_2c
[] = { S_INV
, S_LNK
, 0x6c, S_END
};
188 unsigned char aG3_2d
[] = { S_INV
, S_LNK
, 0x6d, S_END
};
189 unsigned char aG3_2e
[] = { S_BOX
, 2, 0, 3, S_H11
, S_END
};
190 unsigned char aG3_2f
[] = { S_ADT
};
191 unsigned char aG3_30
[] = { S_LNK
, 0x20, S_FLH
, S_END
};
192 unsigned char aG3_31
[] = { S_LNK
, 0x21, S_FLH
, S_END
};
193 unsigned char aG3_32
[] = { S_LNK
, 0x22, S_FLH
, S_END
};
194 unsigned char aG3_33
[] = { S_LNK
, 0x23, S_FLH
, S_END
};
195 unsigned char aG3_34
[] = { S_LNK
, 0x24, S_FLH
, S_END
};
196 unsigned char aG3_35
[] = { S_LNK
, 0x25, S_FLH
, S_END
};
197 unsigned char aG3_36
[] = { S_INV
, S_LNK
, 0x76, S_END
};
198 unsigned char aG3_37
[] = { S_INV
, S_LNK
, 0x77, S_END
};
199 unsigned char aG3_38
[] = { S_INV
, S_LNK
, 0x78, S_END
};
200 unsigned char aG3_39
[] = { S_INV
, S_LNK
, 0x79, S_END
};
201 unsigned char aG3_3a
[] = { S_INV
, S_LNK
, 0x7a, S_END
};
202 unsigned char aG3_3b
[] = { S_INV
, S_LNK
, 0x7b, S_END
};
203 unsigned char aG3_3c
[] = { S_INV
, S_LNK
, 0x7c, S_END
};
204 unsigned char aG3_3d
[] = { S_INV
, S_LNK
, 0x7d, S_END
};
205 unsigned char aG3_3e
[] = { S_LNK
, 0x2e, S_FLH
, S_END
};
206 unsigned char aG3_3f
[] = { S_BOX
, 0, 0, S_W11
, S_H11
, S_END
};
207 unsigned char aG3_40
[] = { S_BOX
, 0, S_H13
, S_W11
, S_H13
, S_LNK
, 0x7e, S_END
};
208 unsigned char aG3_41
[] = { S_BOX
, 0, S_H13
, S_W11
, S_H13
, S_LNK
, 0x7e, S_FLV
, S_END
};
209 unsigned char aG3_42
[] = { S_LNK
, 0x50, S_BOX
, S_W12
, S_H13
, S_W12
, S_H13
, S_END
};
210 unsigned char aG3_43
[] = { S_LNK
, 0x50, S_BOX
, 0, S_H13
, S_W12
, S_H13
, S_END
};
211 unsigned char aG3_44
[] = { S_LNK
, 0x48, S_FLV
, S_LNK
, 0x48, S_END
};
212 unsigned char aG3_45
[] = { S_LNK
, 0x44, S_FLH
, S_END
};
213 unsigned char aG3_46
[] = { S_LNK
, 0x47, S_FLV
, S_END
};
214 unsigned char aG3_47
[] = { S_LNK
, 0x48, S_FLH
, S_LNK
, 0x48, S_END
};
215 unsigned char aG3_48
[] = { S_TRA
, 0, 0, S_W23
, 0, S_H23
, 0, S_BTR
, 0, 0, S_W13
, 0, S_H13
, 0, S_END
};
216 unsigned char aG3_49
[] = { S_LNK
, 0x48, S_FLH
, S_END
};
217 unsigned char aG3_4a
[] = { S_LNK
, 0x48, S_FLV
, S_END
};
218 unsigned char aG3_4b
[] = { S_LNK
, 0x48, S_FLH
, S_FLV
, S_END
};
219 unsigned char aG3_4c
[] = { S_LNK
, 0x50, S_BOX
, 0, S_H13
, S_W11
, S_H13
, S_END
};
220 unsigned char aG3_4d
[] = { S_CHR
, 0x25, 0xE6 };
221 unsigned char aG3_4e
[] = { S_CHR
, 0x25, 0xCF };
222 unsigned char aG3_4f
[] = { S_CHR
, 0x25, 0xCB };
223 unsigned char aG3_50
[] = { S_BOX
, S_W12
, 0, 2, S_H11
, S_FLH
, S_BOX
, S_W12
, 0, 2, S_H11
,S_END
};
224 unsigned char aG3_51
[] = { S_BOX
, 0, S_H12
, S_W11
, 2, S_FLV
, S_BOX
, 0, S_H12
, S_W11
, 2,S_END
};
225 unsigned char aG3_52
[] = { S_LNK
, 0x55, S_FLH
, S_FLV
, S_END
};
226 unsigned char aG3_53
[] = { S_LNK
, 0x55, S_FLV
, S_END
};
227 unsigned char aG3_54
[] = { S_LNK
, 0x55, S_FLH
, S_END
};
228 unsigned char aG3_55
[] = { S_LNK
, 0x7e, S_FLV
, S_BOX
, 0, S_H12
, S_W12
, 2, S_FLV
, S_BOX
, 0, S_H12
, S_W12
, 2, S_END
};
229 unsigned char aG3_56
[] = { S_LNK
, 0x57, S_FLH
, S_END
};
230 unsigned char aG3_57
[] = { S_LNK
, 0x55, S_LNK
, 0x50 , S_END
};
231 unsigned char aG3_58
[] = { S_LNK
, 0x59, S_FLV
, S_END
};
232 unsigned char aG3_59
[] = { S_LNK
, 0x7e, S_LNK
, 0x51 , S_END
};
233 unsigned char aG3_5a
[] = { S_LNK
, 0x50, S_LNK
, 0x51 , S_END
};
234 unsigned char aG3_5b
[] = { S_CHR
, 0x21, 0x92};
235 unsigned char aG3_5c
[] = { S_CHR
, 0x21, 0x90};
236 unsigned char aG3_5d
[] = { S_CHR
, 0x21, 0x91};
237 unsigned char aG3_5e
[] = { S_CHR
, 0x21, 0x93};
238 unsigned char aG3_5f
[] = { S_CHR
, 0x00, 0x20};
239 unsigned char aG3_60
[] = { S_INV
, S_LNK
, 0x20, S_END
};
240 unsigned char aG3_61
[] = { S_INV
, S_LNK
, 0x21, S_END
};
241 unsigned char aG3_62
[] = { S_INV
, S_LNK
, 0x22, S_END
};
242 unsigned char aG3_63
[] = { S_INV
, S_LNK
, 0x23, S_END
};
243 unsigned char aG3_64
[] = { S_INV
, S_LNK
, 0x24, S_END
};
244 unsigned char aG3_65
[] = { S_INV
, S_LNK
, 0x25, S_END
};
245 unsigned char aG3_66
[] = { S_LNK
, 0x20, S_FLV
, S_END
};
246 unsigned char aG3_67
[] = { S_LNK
, 0x21, S_FLV
, S_END
};
247 unsigned char aG3_68
[] = { S_LNK
, 0x22, S_FLV
, S_END
};
248 unsigned char aG3_69
[] = { S_LNK
, 0x23, S_FLV
, S_END
};
249 unsigned char aG3_6a
[] = { S_LNK
, 0x24, S_FLV
, S_END
};
250 unsigned char aG3_6b
[] = { S_BOX
, 0, 0, S_W11
, S_H13
, S_TRA
, 0, S_H13
, S_W11
, 0, S_H23
, 1, S_END
};
251 unsigned char aG3_6c
[] = { S_TRA
, 0, 0, 1, 0, S_H12
, S_W12
, S_FLV
, S_TRA
, 0, 0, 1, 0, S_H12
, S_W12
, S_BOX
, 0, S_H12
, S_W12
,1, S_END
};
252 unsigned char aG3_6d
[] = { S_TRA
, 0, 0, S_W12
, S_W12
, S_H12
, 0, S_FLH
, S_TRA
, 0, 0, S_W12
, S_W12
, S_H12
, 0, S_END
};
253 unsigned char aG3_6e
[] = { S_CHR
, 0x00, 0x20};
254 unsigned char aG3_6f
[] = { S_CHR
, 0x00, 0x20};
255 unsigned char aG3_70
[] = { S_INV
, S_LNK
, 0x30, S_END
};
256 unsigned char aG3_71
[] = { S_INV
, S_LNK
, 0x31, S_END
};
257 unsigned char aG3_72
[] = { S_INV
, S_LNK
, 0x32, S_END
};
258 unsigned char aG3_73
[] = { S_INV
, S_LNK
, 0x33, S_END
};
259 unsigned char aG3_74
[] = { S_INV
, S_LNK
, 0x34, S_END
};
260 unsigned char aG3_75
[] = { S_INV
, S_LNK
, 0x35, S_END
};
261 unsigned char aG3_76
[] = { S_LNK
, 0x66, S_FLH
, S_END
};
262 unsigned char aG3_77
[] = { S_LNK
, 0x67, S_FLH
, S_END
};
263 unsigned char aG3_78
[] = { S_LNK
, 0x68, S_FLH
, S_END
};
264 unsigned char aG3_79
[] = { S_LNK
, 0x69, S_FLH
, S_END
};
265 unsigned char aG3_7a
[] = { S_LNK
, 0x6a, S_FLH
, S_END
};
266 unsigned char aG3_7b
[] = { S_LNK
, 0x6b, S_FLH
, S_END
};
267 unsigned char aG3_7c
[] = { S_LNK
, 0x6c, S_FLH
, S_END
};
268 unsigned char aG3_7d
[] = { S_LNK
, 0x6d, S_FLV
, S_END
};
269 unsigned char aG3_7e
[] = { S_BOX
, S_W12
, 0, 2, S_H12
, S_FLH
, S_BOX
, S_W12
, 0, 2, S_H12
, S_END
};// help char, not printed directly (only by S_LNK)
271 unsigned char *aShapes
[] =
273 aG3_20
, aG3_21
, aG3_22
, aG3_23
, aG3_24
, aG3_25
, aG3_26
, aG3_27
, aG3_28
, aG3_29
, aG3_2a
, aG3_2b
, aG3_2c
, aG3_2d
, aG3_2e
, aG3_2f
,
274 aG3_30
, aG3_31
, aG3_32
, aG3_33
, aG3_34
, aG3_35
, aG3_36
, aG3_37
, aG3_38
, aG3_39
, aG3_3a
, aG3_3b
, aG3_3c
, aG3_3d
, aG3_3e
, aG3_3f
,
275 aG3_40
, aG3_41
, aG3_42
, aG3_43
, aG3_44
, aG3_45
, aG3_46
, aG3_47
, aG3_48
, aG3_49
, aG3_4a
, aG3_4b
, aG3_4c
, aG3_4d
, aG3_4e
, aG3_4f
,
276 aG3_50
, aG3_51
, aG3_52
, aG3_53
, aG3_54
, aG3_55
, aG3_56
, aG3_57
, aG3_58
, aG3_59
, aG3_5a
, aG3_5b
, aG3_5c
, aG3_5d
, aG3_5e
, aG3_5f
,
277 aG3_60
, aG3_61
, aG3_62
, aG3_63
, aG3_64
, aG3_65
, aG3_66
, aG3_67
, aG3_68
, aG3_69
, aG3_6a
, aG3_6b
, aG3_6c
, aG3_6d
, aG3_6e
, aG3_6f
,
278 aG3_70
, aG3_71
, aG3_72
, aG3_73
, aG3_74
, aG3_75
, aG3_76
, aG3_77
, aG3_78
, aG3_79
, aG3_7a
, aG3_7b
, aG3_7c
, aG3_7d
, aG3_7e
281 // G0 Table as defined in ETS 300 706
282 // cyrillic G0 Charset (0 = Serbian/Croatian, 1 = Russian/Bulgarian, 2 = Ukrainian)
283 const unsigned short int G0table
[6][6*16] =
285 // Cyrillic G0 Set - Option 1 - Serbian/Croatian
286 { ' ', '!', '\"', '#', '$', '%', '&', '\'', '(' , ')' , '*', '+', ',', '-', '.', '/',
287 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
288 0x0427, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, 0x0425, 0x0418, 0x0408, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E,
289 0x041F, 0x040C, 0x0420, 0x0421, 0x0422, 0x0423, 0x0412, 0x0403, 0x0409, 0x040A, 0x0417, 0x040B, 0x0416, 0x0402, 0x0428, 0x040F,
290 0x0447, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, 0x0445, 0x0438, 0x0458, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E,
291 0x043F, 0x045C, 0x0440, 0x0441, 0x0442, 0x0443, 0x0432, 0x0453, 0x0459, 0x045A, 0x0437, 0x045B, 0x0436, 0x0452, 0x0448, 0x25A0},
292 // Cyrillic G0 Set - Option 2 - Russian/Bulgarian
293 { ' ', '!', '\"', '#', '$', '%', 0x044B, '\'', '(' , ')' , '*', '+', ',', '-', '.', '/',
294 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
295 0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, 0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E,
296 0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, 0x042C, 0x042A, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x042B,
297 0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, 0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E,
298 0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, 0x044C, 0x044A, 0x0437, 0x0448, 0x044D, 0x0449, 0x0447, 0x25A0},
299 // Cyrillic G0 Set - Option 3 - Ukrainian
300 { ' ', '!', '\"', '#', '$', '%', 0x0457, '\'', '(' , ')' , '*', '+', ',', '-', '.', '/',
301 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
302 0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, 0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E,
303 0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, 0x042C, 0x0406, 0x0417, 0x0428, 0x0404, 0x0429, 0x0427, 0x0407,
304 0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, 0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E,
305 0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, 0x044C, 0x0456, 0x0437, 0x0448, 0x0454, 0x0449, 0x0447, 0x25A0},
307 { ' ', '!', '\"', '#', '$', '%', '&', '\'', '(' , ')' , '*', '+', ',', '-', '.', '/',
308 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', 0x00AB, '=', 0x00BB, '?',
309 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
310 0x03A0, 0x03A1, 0x0384, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
311 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
312 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x25A0},
314 { ' ', '!', 0x05F2, 0x00A3, '$', '%', '&', '\'', '(' , ')' , '*', '+', ',', '-', '.', '/',
315 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
316 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
317 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 0x2190, 0x00BD, 0x2192, 0x2191, '#',
318 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
319 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x20AA, 0x2551, 0x00BE, 0x00F7, 0x25A0},
320 // Arabic G0 Set - Thanks to Habib2006(fannansat)
321 { ' ', '!', 0x05F2, 0x00A3, '$', 0x066A, 0xFEF0, 0xFEF2, 0xFD3F, 0xFD3E, '*', '+', ',', '-', '.', '/',
322 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', 0x061B, '>', '=', '<', 0x061F,
323 0xFE94, 0x0621, 0xFE92, 0x0628, 0xFE98, 0x062A, 0xFE8E, 0xFE8D, 0xFE91, 0xFE93, 0xFE97, 0xFE9B, 0xFE9F, 0xFEA3, 0xFEA7, 0xFEA9,
324 0x0630, 0xFEAD, 0xFEAF, 0xFEB3, 0xFEB7, 0xFEBB, 0xFEBF, 0xFEC1, 0xFEC5, 0xFECB, 0xFECF, 0xFE9C, 0xFEA0, 0xFEA4, 0xFEA8, 0x0023,
325 0x0640, 0xFED3, 0xFED7, 0xFEDB, 0xFEDF, 0xFEE3, 0xFEE7, 0xFEEB, 0xFEED, 0xFEEF, 0xFEF3, 0xFE99, 0xFE9D, 0xFEA1, 0xFEA5, 0xFEF4,
326 0xFEF0, 0xFECC, 0xFED0, 0xFED4, 0xFED1, 0xFED8, 0xFED5, 0xFED9, 0xFEE0, 0xFEDD, 0xFEE4, 0xFEE1, 0xFEE8, 0xFEE5, 0xFEFB, 0x25A0}
329 const unsigned short int nationaltable23
[14][2] =
331 { '#', 0x00A4 }, /* 0 */
332 { '#', 0x016F }, /* 1 CS/SK */
333 { 0x00A3, '$' }, /* 2 EN */
334 { '#', 0x00F5 }, /* 3 ET */
335 { 0x00E9, 0x0457 }, /* 4 FR */
336 { '#', '$' }, /* 5 DE */
337 { 0x00A3, '$' }, /* 6 IT */
338 { '#', '$' }, /* 7 LV/LT */
339 { '#', 0x0144 }, /* 8 PL */
340 { 0x00E7, '$' }, /* 9 PT/ES */
341 { '#', 0x00A4 }, /* A RO */
342 { '#', 0x00CB }, /* B SR/HR/SL */
343 { '#', 0x00A4 }, /* C SV/FI/HU */
344 { 0x20A4, 0x011F }, /* D TR */
346 const unsigned short int nationaltable40
[14] =
349 0x010D, /* 1 CS/SK */
355 0x0161, /* 7 LV/LT */
357 0x00A1, /* 9 PT/ES */
359 0x010C, /* B SR/HR/SL */
360 0x00C9, /* C SV/FI/HU */
363 const unsigned short int nationaltable5b
[14][6] =
365 { '[', '\\', ']', '^', '_', '`' }, /* 0 */
366 { 0x0165, 0x017E, 0x00FD, 0x00ED, 0x0159, 0x00E9 }, /* 1 CS/SK */
367 { 0x2190, 0x00BD, 0x2192, 0x2191, '#', 0x00AD }, /* 2 EN */
368 { 0x00C4, 0x00D6, 0x017D, 0x00DC, 0x00D5, 0x0161 }, /* 3 ET */
369 { 0x0451, 0x00EA, 0x00F9, 0x00EE, '#', 0x00E8 }, /* 4 FR */
370 { 0x00C4, 0x00D6, 0x00DC, '^', '_', 0x00B0 }, /* 5 DE */
371 { 0x00B0, 0x00E7, 0x2192, 0x2191, '#', 0x00F9 }, /* 6 IT */
372 { 0x0117, 0x0119, 0x017D, 0x010D, 0x016B, 0x0161 }, /* 7 LV/LT */
373 { 0x017B, 0x015A, 0x0141, 0x0107, 0x00F3, 0x0119 }, /* 8 PL */
374 { 0x00E1, 0x00E9, 0x00ED, 0x00F3, 0x00FA, 0x00BF }, /* 9 PT/ES */
375 { 0x00C2, 0x015E, 0x01CD, 0x01CF, 0x0131, 0x0163 }, /* A RO */
376 { 0x0106, 0x017D, 0x00D0, 0x0160, 0x0451, 0x010D }, /* B SR/HR/SL */
377 { 0x00C4, 0x00D6, 0x00C5, 0x00DC, '_', 0x00E9 }, /* C SV/FI/HU */
378 { 0x015E, 0x00D6, 0x00C7, 0x00DC, 0x011E, 0x0131 }, /* D TR */
380 const unsigned short int nationaltable7b
[14][4] =
382 { '{', '|', '}', '~' }, /* 0 */
383 { 0x00E1, 0x011B, 0x00FA, 0x0161 }, /* 1 CS/SK */
384 { 0x00BC, 0x2551, 0x00BE, 0x00F7 }, /* 2 EN */
385 { 0x00E4, 0x00F6, 0x017E, 0x00FC }, /* 3 ET */
386 { 0x00E2, 0x00F4, 0x00FB, 0x00E7 }, /* 4 FR */
387 { 0x00E4, 0x00F6, 0x00FC, 0x00DF }, /* 5 DE */
388 { 0x00E0, 0x00F3, 0x00E8, 0x00EC }, /* 6 IT */
389 { 0x0105, 0x0173, 0x017E, 0x012F }, /* 7 LV/LT */
390 { 0x017C, 0x015B, 0x0142, 0x017A }, /* 8 PL */
391 { 0x00FC, 0x00F1, 0x00E8, 0x00E0 }, /* 9 PT/ES */
392 { 0x00E2, 0x015F, 0x01CE, 0x00EE }, /* A RO */
393 { 0x0107, 0x017E, 0x0111, 0x0161 }, /* B SR/HR/SL */
394 { 0x00E4, 0x00F6, 0x00E5, 0x00FC }, /* C SV/FI/HU */
395 { 0x015F, 0x00F6, 0x00E7, 0x00FC }, /* D TR */
397 const unsigned short int arrowtable
[] =
399 8592, 8594, 8593, 8595, 'O', 'K', 8592, 8592
402 CTeletextDecoder::CTeletextDecoder()
404 memset(&m_RenderInfo
, 0, sizeof(TextRenderInfo_t
));
406 m_teletextFont
= CSpecialProtocol::TranslatePath(TeletextFont
);
407 m_TextureBuffer
= NULL
;
411 m_RenderInfo
.ShowFlof
= true;
412 m_RenderInfo
.Show39
= false;
413 m_RenderInfo
.Showl25
= true;
414 m_RenderInfo
.Prev_100
= 0x100;
415 m_RenderInfo
.Prev_10
= 0x100;
416 m_RenderInfo
.Next_100
= 0x100;
417 m_RenderInfo
.Next_10
= 0x100;
418 m_RenderInfo
.InputCounter
= 2;
420 unsigned short rd0
[] = {0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0x00<<8, 0x00<<8, 0x00<<8, 0, 0 };
421 unsigned short gn0
[] = {0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0x20<<8, 0x10<<8, 0x20<<8, 0, 0 };
422 unsigned short bl0
[] = {0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0x40<<8, 0x20<<8, 0x40<<8, 0, 0 };
423 unsigned short tr0
[] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
424 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
425 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
426 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
427 0x0000 , 0x0000 , 0x0A0A , 0xFFFF, 0x3030 };
429 memcpy(m_RenderInfo
.rd0
,rd0
,TXT_Color_SIZECOLTABLE
*sizeof(unsigned short));
430 memcpy(m_RenderInfo
.gn0
,gn0
,TXT_Color_SIZECOLTABLE
*sizeof(unsigned short));
431 memcpy(m_RenderInfo
.bl0
,bl0
,TXT_Color_SIZECOLTABLE
*sizeof(unsigned short));
432 memcpy(m_RenderInfo
.tr0
,tr0
,TXT_Color_SIZECOLTABLE
*sizeof(unsigned short));
444 m_updateTexture
= false;
448 CTeletextDecoder::~CTeletextDecoder() = default;
450 bool CTeletextDecoder::HandleAction(const CAction
&action
)
452 if (m_txtCache
== NULL
)
454 CLog::Log(LOGERROR
, "CTeletextDecoder::HandleAction called without teletext cache");
458 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
460 if (action
.GetID() == ACTION_MOVE_UP
)
462 if (m_RenderInfo
.PageCatching
)
463 CatchNextPage(-1, -1);
465 GetNextPageOne(true);
468 else if (action
.GetID() == ACTION_MOVE_DOWN
)
470 if (m_RenderInfo
.PageCatching
)
473 GetNextPageOne(false);
476 else if (action
.GetID() == ACTION_MOVE_RIGHT
)
478 if (m_RenderInfo
.PageCatching
)
480 else if (m_RenderInfo
.Boxed
)
482 m_RenderInfo
.SubtitleDelay
++;
483 // display SubtitleDelay
484 m_RenderInfo
.PosY
= 0;
487 sprintf(ns
,"+%d ", m_RenderInfo
.SubtitleDelay
);
488 RenderCharFB(ns
[0], &Text_AtrTable
[ATR_WB
]);
489 RenderCharFB(ns
[1], &Text_AtrTable
[ATR_WB
]);
490 RenderCharFB(ns
[2], &Text_AtrTable
[ATR_WB
]);
491 RenderCharFB(ns
[4], &Text_AtrTable
[ATR_WB
]);
499 else if (action
.GetID() == ACTION_MOVE_LEFT
)
501 if (m_RenderInfo
.PageCatching
)
502 CatchNextPage(0, -1);
503 else if (m_RenderInfo
.Boxed
)
505 m_RenderInfo
.SubtitleDelay
--;
507 // display subtitledelay
508 m_RenderInfo
.PosY
= 0;
511 sprintf(ns
,"+%d ", m_RenderInfo
.SubtitleDelay
);
512 RenderCharFB(ns
[0], &Text_AtrTable
[ATR_WB
]);
513 RenderCharFB(ns
[1], &Text_AtrTable
[ATR_WB
]);
514 RenderCharFB(ns
[2], &Text_AtrTable
[ATR_WB
]);
515 RenderCharFB(ns
[4], &Text_AtrTable
[ATR_WB
]);
523 else if (action
.GetID() >= REMOTE_0
&& action
.GetID() <= REMOTE_9
)
525 PageInput(action
.GetID() - REMOTE_0
);
528 else if (action
.GetID() == KEY_UNICODE
)
529 { // input from the keyboard
530 if (action
.GetUnicode() >= 48 && action
.GetUnicode() < 58)
532 PageInput(action
.GetUnicode() - 48);
537 else if (action
.GetID() == ACTION_PAGE_UP
)
542 else if (action
.GetID() == ACTION_PAGE_DOWN
)
547 else if (action
.GetID() == ACTION_SELECT_ITEM
)
549 if (m_txtCache
->SubPageTable
[m_txtCache
->Page
] == 0xFF)
552 if (!m_RenderInfo
.PageCatching
)
560 if (m_RenderInfo
.PageCatching
)
562 m_txtCache
->PageUpdate
= true;
563 m_RenderInfo
.PageCatching
= false;
567 if (action
.GetID() == ACTION_SHOW_INFO
)
572 else if (action
.GetID() == ACTION_TELETEXT_RED
)
574 ColorKey(m_RenderInfo
.Prev_100
);
577 else if (action
.GetID() == ACTION_TELETEXT_GREEN
)
579 ColorKey(m_RenderInfo
.Prev_10
);
582 else if (action
.GetID() == ACTION_TELETEXT_YELLOW
)
584 ColorKey(m_RenderInfo
.Next_10
);
587 else if (action
.GetID() == ACTION_TELETEXT_BLUE
)
589 ColorKey(m_RenderInfo
.Next_100
);
596 bool CTeletextDecoder::InitDecoder()
600 auto& components
= CServiceBroker::GetAppComponents();
601 const auto appPlayer
= components
.GetComponent
<CApplicationPlayer
>();
602 m_txtCache
= appPlayer
->GetTeletextCache();
603 if (m_txtCache
== nullptr)
605 CLog::Log(LOGERROR
, "{}: called without teletext cache", __FUNCTION__
);
609 /* init fontlibrary */
610 if ((error
= FT_Init_FreeType(&m_Library
)))
612 CLog::Log(LOGERROR
, "{}: <FT_Init_FreeType: {:#2X}>", __FUNCTION__
, error
);
617 if ((error
= FTC_Manager_New(m_Library
, 7, 2, 0, &MyFaceRequester
, NULL
, &m_Manager
)))
619 FT_Done_FreeType(m_Library
);
622 CLog::Log(LOGERROR
, "{}: <FTC_Manager_New: {:#2X}>", __FUNCTION__
, error
);
626 if ((error
= FTC_SBitCache_New(m_Manager
, &m_Cache
)))
628 FTC_Manager_Done(m_Manager
);
629 FT_Done_FreeType(m_Library
);
632 CLog::Log(LOGERROR
, "{}: <FTC_SBit_Cache_New: {:#2X}>", __FUNCTION__
, error
);
636 /* calculate font dimensions */
637 m_RenderInfo
.Width
= (int)(CServiceBroker::GetWinSystem()->GetGfxContext().GetWidth()*CServiceBroker::GetWinSystem()->GetGfxContext().GetGUIScaleX());
638 m_RenderInfo
.Height
= (int)(CServiceBroker::GetWinSystem()->GetGfxContext().GetHeight()*CServiceBroker::GetWinSystem()->GetGfxContext().GetGUIScaleY());
639 m_RenderInfo
.FontHeight
= m_RenderInfo
.Height
/ 25;
640 m_RenderInfo
.FontWidth_Normal
= m_RenderInfo
.Width
/ (m_RenderInfo
.Show39
? 39 : 40);
641 SetFontWidth(m_RenderInfo
.FontWidth_Normal
);
642 for (int i
= 0; i
<= 10; i
++)
643 m_RenderInfo
.axdrcs
[i
+12+1] = (m_RenderInfo
.FontHeight
* i
+ 6) / 10;
646 m_TypeTTF
.face_id
= (FTC_FaceID
) const_cast<char*>(m_teletextFont
.c_str());
647 m_TypeTTF
.height
= (FT_UShort
) m_RenderInfo
.FontHeight
;
648 m_TypeTTF
.flags
= FT_LOAD_MONOCHROME
;
649 if (FTC_Manager_LookupFace(m_Manager
, m_TypeTTF
.face_id
, &m_Face
))
651 m_TypeTTF
.face_id
= (FTC_FaceID
) const_cast<char*>(m_teletextFont
.c_str());
652 if ((error
= FTC_Manager_LookupFace(m_Manager
, m_TypeTTF
.face_id
, &m_Face
)))
654 CLog::Log(LOGERROR
, "{}: <FTC_Manager_Lookup_Face failed with Errorcode {:#2X}>",
655 __FUNCTION__
, error
);
656 FTC_Manager_Done(m_Manager
);
657 FT_Done_FreeType(m_Library
);
663 m_Ascender
= m_RenderInfo
.FontHeight
* m_Face
->ascender
/ m_Face
->units_per_EM
;
665 /* set variable screeninfo for double buffering */
667 m_TextureBuffer
= new UTILS::COLOR::Color
[4 * m_RenderInfo
.Height
* m_RenderInfo
.Width
];
669 ClearFB(GetColorRGB(TXT_ColorTransp
));
670 ClearBB(GetColorRGB(TXT_ColorTransp
)); /* initialize backbuffer */
671 /* set new colormap */
672 SetColors(DefaultColors
, 0, TXT_Color_SIZECOLTABLE
);
674 for (int i
= 0; i
< 40 * 25; i
++)
676 m_RenderInfo
.PageChar
[i
] = ' ';
677 m_RenderInfo
.PageAtrb
[i
].fg
= TXT_ColorTransp
;
678 m_RenderInfo
.PageAtrb
[i
].bg
= TXT_ColorTransp
;
679 m_RenderInfo
.PageAtrb
[i
].charset
= C_G0P
;
680 m_RenderInfo
.PageAtrb
[i
].doubleh
= 0;
681 m_RenderInfo
.PageAtrb
[i
].doublew
= 0;
682 m_RenderInfo
.PageAtrb
[i
].IgnoreAtBlackBgSubst
= 0;
685 m_RenderInfo
.TranspMode
= false;
691 void CTeletextDecoder::EndDecoder()
693 /* clear SubtitleCache */
694 for (TextSubtitleCache_t
*& subtitleCache
: m_RenderInfo
.SubtitleCache
)
696 if (subtitleCache
!= NULL
)
698 delete subtitleCache
;
699 subtitleCache
= NULL
;
705 delete[] m_TextureBuffer
;
706 m_TextureBuffer
= NULL
;
712 FTC_Node_Unref(m_anode
, m_Manager
);
713 FTC_Manager_Done(m_Manager
);
717 FT_Done_FreeType(m_Library
);
725 CLog::Log(LOGINFO
, "{}: called without cache", __FUNCTION__
);
729 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
730 m_txtCache
->PageUpdate
= true;
731 CLog::Log(LOGDEBUG
, "Teletext: Rendering ended");
735 void CTeletextDecoder::PageInput(int Number
)
737 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
739 m_updateTexture
= true;
741 /* clear m_TempPage */
742 if (m_RenderInfo
.InputCounter
== 2)
745 /* check for 0 & 9 on first position */
746 if (Number
== 0 && m_RenderInfo
.InputCounter
== 2)
749 m_TempPage
= m_LastPage
; /* 0 toggles to last page as in program switching */
750 m_RenderInfo
.InputCounter
= -1;
752 else if (Number
== 9 && m_RenderInfo
.InputCounter
== 2)
758 if (m_RenderInfo
.ZoomMode
== 2)
760 m_RenderInfo
.ZoomMode
= 1;
764 m_RenderInfo
.PosY
= 0;
766 switch (m_RenderInfo
.InputCounter
)
770 RenderCharFB(Number
| '0', &Text_AtrTable
[ATR_WB
]);
771 RenderCharFB('-', &Text_AtrTable
[ATR_WB
]);
772 RenderCharFB('-', &Text_AtrTable
[ATR_WB
]);
777 RenderCharFB(Number
| '0', &Text_AtrTable
[ATR_WB
]);
782 RenderCharFB(Number
| '0', &Text_AtrTable
[ATR_WB
]);
786 /* generate pagenumber */
787 m_TempPage
|= Number
<< (m_RenderInfo
.InputCounter
*4);
789 m_RenderInfo
.InputCounter
--;
791 if (m_RenderInfo
.InputCounter
< 0)
793 /* disable SubPage zapping */
794 m_txtCache
->ZapSubpageManual
= false;
797 m_RenderInfo
.InputCounter
= 2;
800 m_LastPage
= m_txtCache
->Page
;
802 m_txtCache
->Page
= m_TempPage
;
803 m_RenderInfo
.HintMode
= false;
806 int subp
= m_txtCache
->SubPageTable
[m_txtCache
->Page
];
809 m_txtCache
->SubPage
= subp
;
810 m_txtCache
->PageUpdate
= true;
814 m_txtCache
->SubPage
= 0;
815 // RenderMessage(PageNotFound);
820 void CTeletextDecoder::GetNextPageOne(bool up
)
822 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
824 /* disable subpage zapping */
825 m_txtCache
->ZapSubpageManual
= false;
827 /* abort pageinput */
828 m_RenderInfo
.InputCounter
= 2;
830 /* find next cached page */
831 m_LastPage
= m_txtCache
->Page
;
836 CDVDTeletextTools::NextDec(&m_txtCache
->Page
);
838 CDVDTeletextTools::PrevDec(&m_txtCache
->Page
);
839 subp
= m_txtCache
->SubPageTable
[m_txtCache
->Page
];
840 } while (subp
== 0xFF && m_txtCache
->Page
!= m_LastPage
);
843 if (m_txtCache
->Page
!= m_LastPage
)
845 if (m_RenderInfo
.ZoomMode
== 2)
846 m_RenderInfo
.ZoomMode
= 1;
848 m_txtCache
->SubPage
= subp
;
849 m_RenderInfo
.HintMode
= false;
850 m_txtCache
->PageUpdate
= true;
854 void CTeletextDecoder::GetNextSubPage(int offset
)
856 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
858 /* abort pageinput */
859 m_RenderInfo
.InputCounter
= 2;
861 for (int loop
= m_txtCache
->SubPage
+ offset
; loop
!= m_txtCache
->SubPage
; loop
+= offset
)
865 else if (loop
> 0x79)
867 if (loop
== m_txtCache
->SubPage
)
870 if (m_txtCache
->astCachetable
[m_txtCache
->Page
][loop
])
872 /* enable manual SubPage zapping */
873 m_txtCache
->ZapSubpageManual
= true;
876 if (m_RenderInfo
.ZoomMode
== 2) /* if zoomed to lower half */
877 m_RenderInfo
.ZoomMode
= 1; /* activate upper half */
879 m_txtCache
->SubPage
= loop
;
880 m_RenderInfo
.HintMode
= false;
881 m_txtCache
->PageUpdate
= true;
888 void CTeletextDecoder::SwitchZoomMode()
890 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
892 if (m_txtCache
->SubPageTable
[m_txtCache
->Page
] != 0xFF)
895 m_RenderInfo
.ZoomMode
++;
897 if (m_RenderInfo
.ZoomMode
== 3)
898 m_RenderInfo
.ZoomMode
= 0;
901 m_txtCache
->PageUpdate
= true;
905 void CTeletextDecoder::SwitchTranspMode()
907 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
910 if (!m_RenderInfo
.TranspMode
)
911 m_RenderInfo
.TranspMode
= true;
913 m_RenderInfo
.TranspMode
= false; /* backward to immediately switch to TV-screen */
916 if (!m_RenderInfo
.TranspMode
) /* normal text-only */
918 ClearBB(m_txtCache
->FullScrColor
);
919 m_txtCache
->PageUpdate
= true;
921 else /* semi-transparent BG with FG text */
923 ClearBB(TXT_ColorTransp
);
924 m_txtCache
->PageUpdate
= true;
928 void CTeletextDecoder::SwitchHintMode()
930 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
933 m_RenderInfo
.HintMode
^= true;
935 if (!m_RenderInfo
.HintMode
) /* toggle evaluation of level 2.5 information by explicitly switching off HintMode */
937 m_RenderInfo
.Showl25
^= true;
940 m_txtCache
->PageUpdate
= true;
943 void CTeletextDecoder::ColorKey(int target
)
945 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
950 if (m_RenderInfo
.ZoomMode
== 2)
951 m_RenderInfo
.ZoomMode
= 1;
953 m_LastPage
= m_txtCache
->Page
;
954 m_txtCache
->Page
= target
;
955 m_txtCache
->SubPage
= m_txtCache
->SubPageTable
[m_txtCache
->Page
];
956 m_RenderInfo
.InputCounter
= 2;
957 m_RenderInfo
.HintMode
= false;
958 m_txtCache
->PageUpdate
= true;
961 void CTeletextDecoder::StartPageCatching()
963 m_RenderInfo
.PageCatching
= true;
965 /* abort pageinput */
966 m_RenderInfo
.InputCounter
= 2;
969 m_RenderInfo
.ZoomMode
= 0;
970 m_RenderInfo
.PosX
= 0;
971 m_RenderInfo
.PosY
= 24*m_RenderInfo
.FontHeight
;
973 /* check for pagenumber(s) */
978 m_PCOldCol
= 0; /* no inverted page number to restore yet */
983 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
985 m_RenderInfo
.PageCatching
= false;
986 m_txtCache
->PageUpdate
= true;
991 void CTeletextDecoder::StopPageCatching()
993 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
996 if (m_RenderInfo
.ZoomMode
== 2)
997 m_RenderInfo
.ZoomMode
= 1;
999 m_LastPage
= m_txtCache
->Page
;
1000 m_txtCache
->Page
= m_CatchedPage
;
1001 m_RenderInfo
.HintMode
= false;
1002 m_txtCache
->PageUpdate
= true;
1003 m_RenderInfo
.PageCatching
= false;
1005 int subp
= m_txtCache
->SubPageTable
[m_txtCache
->Page
];
1007 m_txtCache
->SubPage
= subp
;
1009 m_txtCache
->SubPage
= 0;
1012 void CTeletextDecoder::CatchNextPage(int firstlineinc
, int inc
)
1014 int tmp_page
, allowwrap
= 1; /* allow first wrap around */
1016 /* catch next page */
1019 unsigned char *p
= &(m_RenderInfo
.PageChar
[m_CatchRow
*40 + m_CatchCol
]);
1020 TextPageAttr_t a
= m_RenderInfo
.PageAtrb
[m_CatchRow
*40 + m_CatchCol
];
1022 if (!(a
.charset
== C_G1C
|| a
.charset
== C_G1S
) && /* no mosaic */
1023 (a
.fg
!= a
.bg
) && /* not hidden */
1024 (*p
>= '1' && *p
<= '8' && /* valid page number */
1025 *(p
+1) >= '0' && *(p
+1) <= '9' &&
1026 *(p
+2) >= '0' && *(p
+2) <= '9') &&
1027 (m_CatchRow
== 0 || (*(p
-1) < '0' || *(p
-1) > '9')) && /* non-numeric char before and behind */
1028 (m_CatchRow
== 37 || (*(p
+3) < '0' || *(p
+3) > '9')))
1030 tmp_page
= ((*p
- '0')<<8) | ((*(p
+1) - '0')<<4) | (*(p
+2) - '0');
1033 if (tmp_page
!= m_CatchedPage
) /* confusing to skip identical page numbers - I want to reach what I aim to */
1036 m_CatchedPage
= tmp_page
;
1037 RenderCatchedPage();
1038 m_CatchCol
+= inc
; /* FIXME: limit */
1043 if (firstlineinc
> 0)
1049 else if (firstlineinc
< 0)
1058 if (m_CatchCol
> 37)
1063 else if (m_CatchCol
< 0)
1069 if (m_CatchRow
> 23)
1082 else if (m_CatchRow
< 1)
1098 void CTeletextDecoder::RenderCatchedPage()
1101 m_updateTexture
= true;
1104 if (m_RenderInfo
.ZoomMode
)
1107 if (m_PCOldRow
|| m_PCOldCol
) /* not at first call */
1109 /* restore pagenumber */
1110 SetPosX(m_PCOldCol
);
1112 if (m_RenderInfo
.ZoomMode
== 2)
1113 m_RenderInfo
.PosY
= (m_PCOldRow
-12)*m_RenderInfo
.FontHeight
*((zoom
>>10)+1);
1115 m_RenderInfo
.PosY
= m_PCOldRow
*m_RenderInfo
.FontHeight
*((zoom
>>10)+1);
1117 RenderCharFB(m_RenderInfo
.PageChar
[m_PCOldRow
*40 + m_PCOldCol
], &m_RenderInfo
.PageAtrb
[m_PCOldRow
*40 + m_PCOldCol
]);
1118 RenderCharFB(m_RenderInfo
.PageChar
[m_PCOldRow
*40 + m_PCOldCol
+ 1], &m_RenderInfo
.PageAtrb
[m_PCOldRow
*40 + m_PCOldCol
+ 1]);
1119 RenderCharFB(m_RenderInfo
.PageChar
[m_PCOldRow
*40 + m_PCOldCol
+ 2], &m_RenderInfo
.PageAtrb
[m_PCOldRow
*40 + m_PCOldCol
+ 2]);
1122 m_PCOldRow
= m_CatchRow
;
1123 m_PCOldCol
= m_CatchCol
;
1125 /* mark pagenumber */
1126 if (m_RenderInfo
.ZoomMode
== 1 && m_CatchRow
> 11)
1128 m_RenderInfo
.ZoomMode
= 2;
1131 else if (m_RenderInfo
.ZoomMode
== 2 && m_CatchRow
< 12)
1133 m_RenderInfo
.ZoomMode
= 1;
1136 SetPosX(m_CatchCol
);
1138 if (m_RenderInfo
.ZoomMode
== 2)
1139 m_RenderInfo
.PosY
= (m_CatchRow
-12)*m_RenderInfo
.FontHeight
*((zoom
>>10)+1);
1141 m_RenderInfo
.PosY
= m_CatchRow
*m_RenderInfo
.FontHeight
*((zoom
>>10)+1);
1143 TextPageAttr_t a0
= m_RenderInfo
.PageAtrb
[m_CatchRow
*40 + m_CatchCol
];
1144 TextPageAttr_t a1
= m_RenderInfo
.PageAtrb
[m_CatchRow
*40 + m_CatchCol
+ 1];
1145 TextPageAttr_t a2
= m_RenderInfo
.PageAtrb
[m_CatchRow
*40 + m_CatchCol
+ 2];
1148 /* exchange colors */
1149 t
= a0
.fg
; a0
.fg
= a0
.bg
; a0
.bg
= t
;
1150 t
= a1
.fg
; a1
.fg
= a1
.bg
; a1
.bg
= t
;
1151 t
= a2
.fg
; a2
.fg
= a2
.bg
; a2
.bg
= t
;
1153 RenderCharFB(m_RenderInfo
.PageChar
[m_CatchRow
*40 + m_CatchCol
], &a0
);
1154 RenderCharFB(m_RenderInfo
.PageChar
[m_CatchRow
*40 + m_CatchCol
+ 1], &a1
);
1155 RenderCharFB(m_RenderInfo
.PageChar
[m_CatchRow
*40 + m_CatchCol
+ 2], &a2
);
1158 void CTeletextDecoder::RenderPage()
1160 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
1163 int national_subset_bak
= m_txtCache
->NationalSubset
;
1165 if (m_txtCache
->PageUpdate
)
1166 m_updateTexture
= true;
1168 /* update page or timestring */
1169 if (m_txtCache
->PageUpdate
&& m_txtCache
->PageReceiving
!= m_txtCache
->Page
&& m_RenderInfo
.InputCounter
== 2)
1171 /* reset update flag */
1172 m_txtCache
->PageUpdate
= false;
1173 if (m_RenderInfo
.Boxed
&& m_RenderInfo
.SubtitleDelay
)
1175 TextSubtitleCache_t
* c
= NULL
;
1177 for (int i
= 0; i
< SUBTITLE_CACHESIZE
; i
++)
1179 if (j
== -1 && !m_RenderInfo
.SubtitleCache
[i
])
1181 if (m_RenderInfo
.SubtitleCache
[i
] && !m_RenderInfo
.SubtitleCache
[i
]->Valid
)
1183 c
= m_RenderInfo
.SubtitleCache
[i
];
1189 if (j
== -1) // no more space in SubtitleCache
1192 c
= new TextSubtitleCache_t
;
1197 m_RenderInfo
.SubtitleCache
[j
] = c
;
1200 c
->Timestamp
= std::chrono::steady_clock::now();
1202 if (m_txtCache
->SubPageTable
[m_txtCache
->Page
] != 0xFF)
1204 TextPageinfo_t
* p
= DecodePage(m_RenderInfo
.Showl25
, c
->PageChar
, c
->PageAtrb
, m_RenderInfo
.HintMode
, m_RenderInfo
.ShowFlof
);
1207 m_RenderInfo
.Boxed
= p
->boxed
;
1210 m_RenderInfo
.DelayStarted
= true;
1213 m_RenderInfo
.DelayStarted
= false;
1215 if (m_txtCache
->SubPageTable
[m_txtCache
->Page
] != 0xFF)
1217 TextPageinfo_t
* p
= DecodePage(m_RenderInfo
.Showl25
, m_RenderInfo
.PageChar
, m_RenderInfo
.PageAtrb
, m_RenderInfo
.HintMode
, m_RenderInfo
.ShowFlof
);
1220 m_RenderInfo
.PageInfo
= p
;
1221 m_RenderInfo
.Boxed
= p
->boxed
;
1223 if (m_RenderInfo
.Boxed
|| m_RenderInfo
.TranspMode
)
1224 FillBorder(GetColorRGB(TXT_ColorTransp
));
1226 FillBorder(GetColorRGB((enumTeletextColor
)m_txtCache
->FullScrColor
));
1228 if (m_txtCache
->ColorTable
) /* as late as possible to shorten the time the old page is displayed with the new colors */
1229 SetColors(m_txtCache
->ColorTable
, 16, 16); /* set colors for CLUTs 2+3 */
1234 DoRenderPage(StartRow
, national_subset_bak
);
1238 if (m_RenderInfo
.DelayStarted
)
1240 auto now
= std::chrono::steady_clock::now();
1241 for (TextSubtitleCache_t
* const subtitleCache
: m_RenderInfo
.SubtitleCache
)
1243 if (subtitleCache
&& subtitleCache
->Valid
&&
1244 std::chrono::duration_cast
<std::chrono::seconds
>(now
- subtitleCache
->Timestamp
)
1245 .count() >= m_RenderInfo
.SubtitleDelay
)
1247 memcpy(m_RenderInfo
.PageChar
, subtitleCache
->PageChar
, 40 * 25);
1248 memcpy(m_RenderInfo
.PageAtrb
, subtitleCache
->PageAtrb
, 40 * 25 * sizeof(TextPageAttr_t
));
1249 DoRenderPage(StartRow
, national_subset_bak
);
1250 subtitleCache
->Valid
= false;
1255 if (m_RenderInfo
.ZoomMode
!= 2)
1257 m_RenderInfo
.PosY
= 0;
1258 if (m_txtCache
->SubPageTable
[m_txtCache
->Page
] == 0xff)
1260 m_RenderInfo
.PageAtrb
[32].fg
= TXT_ColorYellow
;
1261 m_RenderInfo
.PageAtrb
[32].bg
= TXT_ColorMenu1
;
1262 int showpage
= m_txtCache
->PageReceiving
;
1265 // Verify that showpage is positive before any access to the array
1266 if (showpage
>= 0 && (showsubpage
= m_txtCache
->SubPageTable
[showpage
]) != 0xff)
1268 TextCachedPage_t
*pCachedPage
;
1269 pCachedPage
= m_txtCache
->astCachetable
[showpage
][showsubpage
];
1270 if (pCachedPage
&& IsDec(showpage
))
1272 m_RenderInfo
.PosX
= 0;
1273 if (m_RenderInfo
.InputCounter
== 2)
1275 if (m_txtCache
->BTTok
&& !m_txtCache
->BasicTop
[m_txtCache
->Page
]) /* page non-existent according to TOP (continue search anyway) */
1277 m_RenderInfo
.PageAtrb
[0].fg
= TXT_ColorWhite
;
1278 m_RenderInfo
.PageAtrb
[0].bg
= TXT_ColorRed
;
1282 m_RenderInfo
.PageAtrb
[0].fg
= TXT_ColorYellow
;
1283 m_RenderInfo
.PageAtrb
[0].bg
= TXT_ColorMenu1
;
1285 CDVDTeletextTools::Hex2Str((char*)m_RenderInfo
.PageChar
+3, m_txtCache
->Page
);
1288 for (col
= m_RenderInfo
.nofirst
; col
< 7; col
++) // selected page
1290 RenderCharFB(m_RenderInfo
.PageChar
[col
], &m_RenderInfo
.PageAtrb
[0]);
1292 RenderCharFB(m_RenderInfo
.PageChar
[col
], &m_RenderInfo
.PageAtrb
[32]);
1297 memcpy(&m_RenderInfo
.PageChar
[8], pCachedPage
->p0
, 24); /* header line without timestring */
1298 for (unsigned char i
: pCachedPage
->p0
)
1300 RenderCharFB(i
, &m_RenderInfo
.PageAtrb
[32]);
1303 /* Update on every Header number change */
1304 if (pCachedPage
->p0
[2] != prevHeaderPage
)
1306 prevHeaderPage
= pCachedPage
->p0
[2];
1307 m_updateTexture
= true;
1313 /* update timestring */
1315 for (int i
= 0; i
< 8; i
++)
1317 if (!m_RenderInfo
.PageAtrb
[32+i
].flashing
)
1318 RenderCharFB(m_txtCache
->TimeString
[i
], &m_RenderInfo
.PageAtrb
[32]);
1325 if (!IsSubtitlePage(m_txtCache
->Page
))
1327 /* Update on every changed second */
1328 if (m_txtCache
->TimeString
[7] != prevTimeSec
)
1330 prevTimeSec
= m_txtCache
->TimeString
[7];
1331 m_updateTexture
= true;
1336 m_updateTexture
= true;
1339 DoFlashing(StartRow
);
1340 m_txtCache
->NationalSubset
= national_subset_bak
;
1344 bool CTeletextDecoder::IsSubtitlePage(int pageNumber
) const
1349 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
1351 for (const auto subPage
: m_txtCache
->SubtitlePages
)
1353 if (subPage
.page
== pageNumber
)
1360 void CTeletextDecoder::DoFlashing(int startrow
)
1362 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
1364 TextCachedPage_t
* textCachepage
=
1365 m_txtCache
->astCachetable
[m_txtCache
->Page
][m_txtCache
->SubPage
];
1367 // Verify that the page is not deleted by the other thread: CDVDTeletextData::ResetTeletextCache()
1368 if (!textCachepage
|| m_RenderInfo
.PageInfo
!= &textCachepage
->pageinfo
)
1369 m_RenderInfo
.PageInfo
= nullptr;
1371 /* get national subset */
1372 if (m_txtCache
->NationalSubset
<= NAT_MAX_FROM_HEADER
&& /* not for GR/RU as long as line28 is not evaluated */
1373 m_RenderInfo
.PageInfo
&& m_RenderInfo
.PageInfo
->nationalvalid
) /* individual subset according to page header */
1375 m_txtCache
->NationalSubset
= CountryConversionTable
[m_RenderInfo
.PageInfo
->national
];
1379 TextPageAttr_t flashattr
;
1381 std::chrono::milliseconds flashphase
= std::chrono::duration_cast
<std::chrono::milliseconds
>(
1382 std::chrono::steady_clock::now().time_since_epoch()) %
1385 int srow
= startrow
;
1389 switch (m_RenderInfo
.ZoomMode
)
1391 case 1: erow
= 12; factor
=2;break;
1392 case 2: srow
= 12; factor
=2;break;
1395 m_RenderInfo
.PosY
= startrow
*m_RenderInfo
.FontHeight
*factor
;
1396 for (int row
= srow
; row
< erow
; row
++)
1398 int index
= row
* 40;
1403 m_RenderInfo
.PosX
= 0;
1404 for (int col
= m_RenderInfo
.nofirst
; col
< 40; col
++)
1406 if (m_RenderInfo
.PageAtrb
[index
+ col
].flashing
&& m_RenderInfo
.PageChar
[index
+ col
] > 0x20 && m_RenderInfo
.PageChar
[index
+ col
] != 0xff )
1409 flashchar
= m_RenderInfo
.PageChar
[index
+ col
];
1410 bool doflash
= false;
1411 memcpy(&flashattr
, &m_RenderInfo
.PageAtrb
[index
+ col
], sizeof(TextPageAttr_t
));
1412 switch (flashattr
.flashing
&0x1c) // Flash Rate
1415 if (flashphase
> 500ms
)
1418 case 0x04 : // 2 Hz Phase 1
1419 if (flashphase
< 250ms
)
1422 case 0x08 : // 2 Hz Phase 2
1423 if (flashphase
>= 250ms
&& flashphase
< 500ms
)
1426 case 0x0c : // 2 Hz Phase 3
1427 if (flashphase
>= 500ms
&& flashphase
< 750ms
)
1430 case 0x10 : // incremental flash
1432 if (incflash
>3) incflash
= 1;
1436 if (flashphase
< 250ms
)
1440 if (flashphase
>= 250ms
&& flashphase
< 500ms
)
1444 if (flashphase
>= 500ms
&& flashphase
< 750ms
)
1449 case 0x14 : // decremental flash
1451 if (decflash
<1) decflash
= 3;
1455 if (flashphase
< 250ms
)
1459 if (flashphase
>= 250ms
&& flashphase
< 500ms
)
1463 if (flashphase
>= 500ms
&& flashphase
< 750ms
)
1471 switch (flashattr
.flashing
&0x03) // Flash Mode
1473 case 0x01 : // normal Flashing
1474 if (doflash
) flashattr
.fg
= flashattr
.bg
;
1476 case 0x02 : // inverted Flashing
1478 if (doflash
) flashattr
.fg
= flashattr
.bg
;
1480 case 0x03 : // color Flashing
1481 if (doflash
) flashattr
.fg
= flashattr
.fg
+ (flashattr
.fg
> 7 ? (-8) : 8);
1485 RenderCharFB(flashchar
, &flashattr
);
1486 if (flashattr
.doublew
) col
++;
1487 if (flashattr
.doubleh
) dhset
= 1;
1489 m_updateTexture
= true;
1495 m_RenderInfo
.PosY
+= m_RenderInfo
.FontHeight
*factor
;
1497 m_RenderInfo
.PosY
+= m_RenderInfo
.FontHeight
*factor
;
1501 void CTeletextDecoder::DoRenderPage(int startrow
, int national_subset_bak
)
1503 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
1505 /* display first column? */
1506 m_RenderInfo
.nofirst
= m_RenderInfo
.Show39
;
1507 for (int row
= 1; row
< 24; row
++)
1509 int Byte
= m_RenderInfo
.PageChar
[row
*40];
1510 if (Byte
!= ' ' && Byte
!= 0x00 && Byte
!= 0xFF && m_RenderInfo
.PageAtrb
[row
*40].fg
!= m_RenderInfo
.PageAtrb
[row
*40].bg
)
1512 m_RenderInfo
.nofirst
= 0;
1516 m_RenderInfo
.FontWidth_Normal
= m_RenderInfo
.Width
/ (m_RenderInfo
.nofirst
? 39 : 40);
1517 SetFontWidth(m_RenderInfo
.FontWidth_Normal
);
1519 if (m_RenderInfo
.TranspMode
|| m_RenderInfo
.Boxed
)
1521 FillBorder(GetColorRGB(TXT_ColorTransp
));//ClearBB(transp);
1522 m_RenderInfo
.ClearBBColor
= TXT_ColorTransp
;
1525 /* get national subset */
1526 if (m_txtCache
->NationalSubset
<= NAT_MAX_FROM_HEADER
&& /* not for GR/RU as long as line28 is not evaluated */
1527 m_RenderInfo
.PageInfo
&& m_RenderInfo
.PageInfo
->nationalvalid
) /* individual subset according to page header */
1529 m_txtCache
->NationalSubset
= CountryConversionTable
[m_RenderInfo
.PageInfo
->national
];
1532 if (m_RenderInfo
.PageInfo
&& (m_RenderInfo
.PageInfo
->function
== FUNC_GDRCS
|| m_RenderInfo
.PageInfo
->function
== FUNC_DRCS
)) /* character definitions */
1535 #define DRCSCOLS (48/DRCSROWS)
1538 #define DRCSXSPC (12*DRCSZOOMX + 2)
1539 #define DRCSYSPC (10*DRCSZOOMY + 2)
1541 unsigned char ax
[] = { /* array[0..12] of x-offsets, array[0..10] of y-offsets for each pixel */
1568 ClearBB(TXT_ColorBlack
);
1569 for (int col
= 0; col
< 24*40; col
++)
1570 m_RenderInfo
.PageAtrb
[col
] = Text_AtrTable
[ATR_WB
];
1572 for (int row
= 0; row
< DRCSROWS
; row
++)
1574 for (int col
= 0; col
< DRCSCOLS
; col
++)
1576 RenderDRCS(m_RenderInfo
.Width
,
1577 m_RenderInfo
.PageChar
+ 20 * (DRCSCOLS
* row
+ col
+ 2),
1579 + (m_RenderInfo
.FontHeight
+ DRCSYSPC
* row
+ m_RenderInfo
.Height
) * m_RenderInfo
.Width
1581 ax
, GetColorRGB(TXT_ColorWhite
), GetColorRGB(TXT_ColorBlack
));
1584 memset(m_RenderInfo
.PageChar
+ 40, 0xff, 24*40); /* don't render any char below row 0 */
1586 m_RenderInfo
.PosY
= startrow
*m_RenderInfo
.FontHeight
;
1587 for (int row
= startrow
; row
< 24; row
++)
1589 int index
= row
* 40;
1591 m_RenderInfo
.PosX
= 0;
1592 for (int col
= m_RenderInfo
.nofirst
; col
< 40; col
++)
1594 RenderCharBB(m_RenderInfo
.PageChar
[index
+ col
], &m_RenderInfo
.PageAtrb
[index
+ col
]);
1596 if (m_RenderInfo
.PageAtrb
[index
+ col
].doubleh
&& m_RenderInfo
.PageChar
[index
+ col
] != 0xff && row
< 24-1) /* disable lower char in case of doubleh setting in l25 objects */
1597 m_RenderInfo
.PageChar
[index
+ col
+ 40] = 0xff;
1598 if (m_RenderInfo
.PageAtrb
[index
+ col
].doublew
&& col
< 40-1) /* skip next column if double width */
1601 if (m_RenderInfo
.PageAtrb
[index
+ col
- 1].doubleh
&& m_RenderInfo
.PageChar
[index
+ col
] != 0xff && row
< 24-1) /* disable lower char in case of doubleh setting in l25 objects */
1602 m_RenderInfo
.PageChar
[index
+ col
+ 40] = 0xff;
1605 m_RenderInfo
.PosY
+= m_RenderInfo
.FontHeight
;
1607 DoFlashing(startrow
);
1609 /* update framebuffer */
1611 m_txtCache
->NationalSubset
= national_subset_bak
;
1614 void CTeletextDecoder::Decode_BTT()
1616 /* basic top table */
1617 int current
, b1
, b2
, b3
, b4
;
1618 unsigned char btt
[23*40];
1620 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
1622 if (m_txtCache
->SubPageTable
[0x1f0] == 0xff || 0 == m_txtCache
->astCachetable
[0x1f0][m_txtCache
->SubPageTable
[0x1f0]]) /* not yet received */
1625 auto& components
= CServiceBroker::GetAppComponents();
1626 const auto appPlayer
= components
.GetComponent
<CApplicationPlayer
>();
1628 appPlayer
->LoadPage(0x1f0, m_txtCache
->SubPageTable
[0x1f0], btt
);
1629 if (btt
[799] == ' ') /* not completely received or error */
1633 for (int i
= 0; i
< 800; i
++)
1641 if (b1
== 0xFF) /* hamming error in btt */
1643 btt
[799] = ' '; /* mark btt as not received */
1647 m_txtCache
->BasicTop
[current
] = b1
;
1648 CDVDTeletextTools::NextDec(¤t
);
1650 /* page linking table */
1651 m_txtCache
->ADIP_PgMax
= -1; /* rebuild table of adip pages */
1652 for (int i
= 0; i
< 10; i
++)
1654 b1
= dehamming
[btt
[800 + 8*i
+0]];
1657 continue; /* unused */
1661 b4
= dehamming
[btt
[800 + 8*i
+7]];
1663 if (b4
!= 2) /* only adip, ignore multipage (1) */
1666 b2
= dehamming
[btt
[800 + 8*i
+1]];
1667 b3
= dehamming
[btt
[800 + 8*i
+2]];
1669 if (b1
== 0xFF || b2
== 0xFF || b3
== 0xFF)
1671 CLog::Log(LOGERROR
, "CTeletextDecoder::Decode_BTT <Biterror in btt/plt index {}>", i
);
1672 btt
[799] = ' '; /* mark btt as not received */
1676 b1
= b1
<<8 | b2
<<4 | b3
; /* page number */
1677 m_txtCache
->ADIP_Pg
[++m_txtCache
->ADIP_PgMax
] = b1
;
1680 m_txtCache
->BTTok
= true;
1683 void CTeletextDecoder::Decode_ADIP() /* additional information table */
1685 int i
, p
, j
, b1
, b2
, b3
, charfound
;
1686 unsigned char padip
[23*40];
1688 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
1690 auto& components
= CServiceBroker::GetAppComponents();
1691 const auto appPlayer
= components
.GetComponent
<CApplicationPlayer
>();
1693 for (i
= 0; i
<= m_txtCache
->ADIP_PgMax
; i
++)
1695 p
= m_txtCache
->ADIP_Pg
[i
];
1696 if (!p
|| m_txtCache
->SubPageTable
[p
] == 0xff || 0 == m_txtCache
->astCachetable
[p
][m_txtCache
->SubPageTable
[p
]]) /* not cached (avoid segfault) */
1699 appPlayer
->LoadPage(p
, m_txtCache
->SubPageTable
[p
], padip
);
1700 for (j
= 0; j
< 44; j
++)
1702 b1
= dehamming
[padip
[20*j
+0]];
1704 continue; /* unused */
1709 b2
= dehamming
[padip
[20*j
+1]];
1710 b3
= dehamming
[padip
[20*j
+2]];
1712 if (b1
== 0xFF || b2
== 0xFF || b3
== 0xFF)
1715 "CTeletextDecoder::Decode_BTT <Biterror in ait {:03x} {} {:02x} {:02x} {:02x} "
1716 "{:02x} {:02x} {:02x}>",
1717 p
, j
, padip
[20 * j
+ 0], padip
[20 * j
+ 1], padip
[20 * j
+ 2], b1
, b2
, b3
);
1721 if (b1
>8 || b2
>9 || b3
>9) /* ignore entries with invalid or hex page numbers */
1726 b1
= b1
<<8 | b2
<<4 | b3
; /* page number */
1727 charfound
= 0; /* flag: no printable char found */
1729 for (b2
= 11; b2
>= 0; b2
--)
1731 b3
= deparity
[padip
[20*j
+ 8 + b2
]];
1735 if (b3
== ' ' && !charfound
)
1736 m_txtCache
->ADIPTable
[b1
][b2
] = '\0';
1739 m_txtCache
->ADIPTable
[b1
][b2
] = b3
;
1745 m_txtCache
->ADIP_Pg
[i
] = 0; /* completely decoded: clear entry */
1746 } /* next adip page i */
1748 while ((m_txtCache
->ADIP_PgMax
>= 0) && !m_txtCache
->ADIP_Pg
[m_txtCache
->ADIP_PgMax
]) /* and shrink table */
1749 m_txtCache
->ADIP_PgMax
--;
1752 int CTeletextDecoder::TopText_GetNext(int startpage
, int up
, int findgroup
)
1754 int current
, nextgrp
, nextblk
;
1756 int stoppage
= (IsDec(startpage
) ? startpage
: startpage
& 0xF00); // avoid endless loop in hexmode
1757 nextgrp
= nextblk
= 0;
1758 current
= startpage
;
1760 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
1764 CDVDTeletextTools::NextDec(¤t
);
1766 CDVDTeletextTools::PrevDec(¤t
);
1768 if (!m_txtCache
->BTTok
|| m_txtCache
->BasicTop
[current
]) /* only if existent */
1772 if (m_txtCache
->BasicTop
[current
] >= 6 && m_txtCache
->BasicTop
[current
] <= 7)
1774 if (!nextgrp
&& (current
&0x00F) == 0)
1777 if (m_txtCache
->BasicTop
[current
] >= 2 && m_txtCache
->BasicTop
[current
] <= 5) /* always find block */
1780 if (!nextblk
&& (current
&0x0FF) == 0)
1783 } while (current
!= stoppage
);
1793 void CTeletextDecoder::Showlink(int column
, int linkpage
)
1795 unsigned char line
[] = " >??? ";
1796 int oldfontwidth
= m_RenderInfo
.FontWidth
;
1802 yoffset
= m_RenderInfo
.Height
;
1804 int abx
= ((m_RenderInfo
.Width
)%(40-m_RenderInfo
.nofirst
) == 0 ? m_RenderInfo
.Width
+1 : (m_RenderInfo
.Width
)/(((m_RenderInfo
.Width
)%(40-m_RenderInfo
.nofirst
)))+1);// distance between 'inserted' pixels
1805 int width
= m_RenderInfo
.Width
/4;
1807 m_RenderInfo
.PosY
= 24*m_RenderInfo
.FontHeight
;
1809 if (m_RenderInfo
.Boxed
)
1811 m_RenderInfo
.PosX
= column
*width
;
1812 FillRect(m_TextureBuffer
, m_RenderInfo
.Width
, m_RenderInfo
.PosX
, m_RenderInfo
.PosY
+yoffset
, m_RenderInfo
.Width
, m_RenderInfo
.FontHeight
, GetColorRGB(TXT_ColorTransp
));
1816 if (m_txtCache
->ADIPTable
[linkpage
][0])
1818 m_RenderInfo
.PosX
= column
*width
;
1819 int l
= strlen(m_txtCache
->ADIPTable
[linkpage
]);
1821 if (l
> 9) /* smaller font, if no space for one half space at front and end */
1822 SetFontWidth(oldfontwidth
* 10 / (l
+1));
1824 FillRect(m_TextureBuffer
, m_RenderInfo
.Width
, m_RenderInfo
.PosX
, m_RenderInfo
.PosY
+yoffset
, width
+(m_RenderInfo
.Width
%4), m_RenderInfo
.FontHeight
, GetColorRGB((enumTeletextColor
)Text_AtrTable
[ATR_L250
+ column
].bg
));
1825 m_RenderInfo
.PosX
+= ((width
) - (l
*m_RenderInfo
.FontWidth
+l
*m_RenderInfo
.FontWidth
/abx
))/2; /* center */
1827 for (char *p
= m_txtCache
->ADIPTable
[linkpage
]; *p
; p
++)
1828 RenderCharBB(*p
, &Text_AtrTable
[ATR_L250
+ column
]);
1830 SetFontWidth(oldfontwidth
);
1832 else /* display number */
1834 m_RenderInfo
.PosX
= column
*width
;
1835 FillRect(m_TextureBuffer
, m_RenderInfo
.Width
, m_RenderInfo
.PosX
, m_RenderInfo
.PosY
+yoffset
, m_RenderInfo
.Width
-m_RenderInfo
.PosX
, m_RenderInfo
.FontHeight
, GetColorRGB((enumTeletextColor
)Text_AtrTable
[ATR_L250
+ column
].bg
));
1836 if (linkpage
< m_txtCache
->Page
)
1839 CDVDTeletextTools::Hex2Str((char*)line
+ 5, linkpage
);
1842 CDVDTeletextTools::Hex2Str((char*)line
+ 6, linkpage
);
1844 for (unsigned char *p
= line
; p
< line
+9; p
++)
1845 RenderCharBB(*p
, &Text_AtrTable
[ATR_L250
+ column
]);
1849 void CTeletextDecoder::CreateLine25()
1851 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
1853 /* btt completely received and not yet decoded */
1854 if (!m_txtCache
->BTTok
)
1857 if (m_txtCache
->ADIP_PgMax
>= 0)
1860 if (!m_RenderInfo
.ShowHex
&& m_RenderInfo
.ShowFlof
&&
1861 (m_txtCache
->FlofPages
[m_txtCache
->Page
][0] || m_txtCache
->FlofPages
[m_txtCache
->Page
][1] || m_txtCache
->FlofPages
[m_txtCache
->Page
][2] || m_txtCache
->FlofPages
[m_txtCache
->Page
][3])) // FLOF-Navigation present
1863 m_RenderInfo
.Prev_100
= m_txtCache
->FlofPages
[m_txtCache
->Page
][0];
1864 m_RenderInfo
.Prev_10
= m_txtCache
->FlofPages
[m_txtCache
->Page
][1];
1865 m_RenderInfo
.Next_10
= m_txtCache
->FlofPages
[m_txtCache
->Page
][2];
1866 m_RenderInfo
.Next_100
= m_txtCache
->FlofPages
[m_txtCache
->Page
][3];
1868 m_RenderInfo
.PosY
= 24*m_RenderInfo
.FontHeight
;
1869 m_RenderInfo
.PosX
= 0;
1870 for (int i
=m_RenderInfo
.nofirst
; i
<40; i
++)
1871 RenderCharBB(m_RenderInfo
.PageChar
[24*40 + i
], &m_RenderInfo
.PageAtrb
[24*40 + i
]);
1875 /* normal: blk-1, grp+1, grp+2, blk+1 */
1876 /* hex: hex+1, blk-1, grp+1, blk+1 */
1877 if (m_RenderInfo
.ShowHex
)
1879 /* arguments: startpage, up, findgroup */
1880 m_RenderInfo
.Prev_100
= NextHex(m_txtCache
->Page
);
1881 m_RenderInfo
.Prev_10
= TopText_GetNext(m_txtCache
->Page
, 0, 0);
1882 m_RenderInfo
.Next_10
= TopText_GetNext(m_txtCache
->Page
, 1, 1);
1886 m_RenderInfo
.Prev_100
= TopText_GetNext(m_txtCache
->Page
, 0, 0);
1887 m_RenderInfo
.Prev_10
= TopText_GetNext(m_txtCache
->Page
, 1, 1);
1888 m_RenderInfo
.Next_10
= TopText_GetNext(m_RenderInfo
.Prev_10
, 1, 1);
1890 m_RenderInfo
.Next_100
= TopText_GetNext(m_RenderInfo
.Next_10
, 1, 0);
1891 Showlink(0, m_RenderInfo
.Prev_100
);
1892 Showlink(1, m_RenderInfo
.Prev_10
);
1893 Showlink(2, m_RenderInfo
.Next_10
);
1894 Showlink(3, m_RenderInfo
.Next_100
);
1898 void CTeletextDecoder::RenderCharFB(int Char
, TextPageAttr_t
*Attribute
)
1900 RenderCharIntern(&m_RenderInfo
, Char
, Attribute
, m_RenderInfo
.ZoomMode
, m_YOffset
);
1903 void CTeletextDecoder::RenderCharBB(int Char
, TextPageAttr_t
*Attribute
)
1905 RenderCharIntern(&m_RenderInfo
, Char
, Attribute
, 0, m_RenderInfo
.Height
-m_YOffset
);
1908 void CTeletextDecoder::CopyBB2FB()
1910 UTILS::COLOR::Color
*src
, *dst
, *topsrc
;
1912 UTILS::COLOR::Color fillcolor
;
1914 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
1917 if (!m_RenderInfo
.PageCatching
)
1920 /* copy backbuffer to framebuffer */
1921 if (!m_RenderInfo
.ZoomMode
)
1926 m_YOffset
= m_RenderInfo
.Height
;
1928 if (m_RenderInfo
.ClearBBColor
>= 0)
1930 m_RenderInfo
.ClearBBColor
= -1;
1935 src
= dst
= topsrc
= m_TextureBuffer
+ m_RenderInfo
.Width
;
1939 dst
+= m_RenderInfo
.Width
* m_RenderInfo
.Height
;
1943 src
+= m_RenderInfo
.Width
* m_RenderInfo
.Height
;
1944 topsrc
+= m_RenderInfo
.Width
* m_RenderInfo
.Height
;
1947 if (!m_RenderInfo
.PageCatching
)
1948 SDL_memcpy4(dst
+(24*m_RenderInfo
.FontHeight
)*m_RenderInfo
.Width
, src
+ (24*m_RenderInfo
.FontHeight
)*m_RenderInfo
.Width
, m_RenderInfo
.Width
*m_RenderInfo
.FontHeight
); /* copy line25 in normal height */
1950 if (m_RenderInfo
.TranspMode
)
1951 fillcolor
= GetColorRGB(TXT_ColorTransp
);
1953 fillcolor
= GetColorRGB((enumTeletextColor
)m_txtCache
->FullScrColor
);
1955 if (m_RenderInfo
.ZoomMode
== 2)
1956 src
+= 12*m_RenderInfo
.FontHeight
*m_RenderInfo
.Width
;
1958 screenwidth
= m_RenderInfo
.Width
;
1960 for (int i
= 12*m_RenderInfo
.FontHeight
; i
; i
--)
1962 SDL_memcpy4(dst
, src
, screenwidth
);
1963 dst
+= m_RenderInfo
.Width
;
1964 SDL_memcpy4(dst
, src
, screenwidth
);
1965 dst
+= m_RenderInfo
.Width
;
1966 src
+= m_RenderInfo
.Width
;
1969 for (int i
= m_RenderInfo
.Height
- 25*m_RenderInfo
.FontHeight
; i
>= 0;i
--)
1971 SDL_memset4(dst
+ m_RenderInfo
.Width
*(m_RenderInfo
.FontHeight
+i
), fillcolor
, screenwidth
);
1975 FT_Error
CTeletextDecoder::MyFaceRequester(FTC_FaceID face_id
, FT_Library library
, FT_Pointer request_data
, FT_Face
*aface
)
1977 FT_Error result
= FT_New_Face(library
, (const char*)face_id
, 0, aface
);
1980 CLog::Log(LOGINFO
, "Teletext font {} loaded", (char*)face_id
);
1982 CLog::Log(LOGERROR
, "Opening of Teletext font {} failed", (char*)face_id
);
1987 void CTeletextDecoder::SetFontWidth(int newWidth
)
1989 if (m_RenderInfo
.FontWidth
!= newWidth
)
1991 m_RenderInfo
.FontWidth
= newWidth
;
1992 m_TypeTTF
.width
= (FT_UShort
) m_RenderInfo
.FontWidth
;
1994 for (int i
= 0; i
<= 12; i
++)
1995 m_RenderInfo
.axdrcs
[i
] = (m_RenderInfo
.FontWidth
* i
+ 6) / 12;
1999 int CTeletextDecoder::GetCurFontWidth()
2001 int mx
= (m_RenderInfo
.Width
)%(40-m_RenderInfo
.nofirst
); // # of unused pixels
2002 int abx
= (mx
== 0 ? m_RenderInfo
.Width
+1 : (m_RenderInfo
.Width
)/(mx
+1)); // distance between 'inserted' pixels
2003 int nx
= abx
+1-(m_RenderInfo
.PosX
% (abx
+1)); // # of pixels to next insert
2004 return m_RenderInfo
.FontWidth
+(((m_RenderInfo
.PosX
+m_RenderInfo
.FontWidth
+1) <= m_RenderInfo
.Width
&& nx
<= m_RenderInfo
.FontWidth
+1) ? 1 : 0);
2007 void CTeletextDecoder::SetPosX(int column
)
2009 m_RenderInfo
.PosX
= 0;
2011 for (int i
= 0; i
< column
-m_RenderInfo
.nofirst
; i
++)
2012 m_RenderInfo
.PosX
+= GetCurFontWidth();
2015 void CTeletextDecoder::ClearBB(UTILS::COLOR::Color Color
)
2017 SDL_memset4(m_TextureBuffer
+ (m_RenderInfo
.Height
-m_YOffset
)*m_RenderInfo
.Width
, Color
, m_RenderInfo
.Width
*m_RenderInfo
.Height
);
2020 void CTeletextDecoder::ClearFB(UTILS::COLOR::Color Color
)
2022 SDL_memset4(m_TextureBuffer
+ m_RenderInfo
.Width
*m_YOffset
, Color
, m_RenderInfo
.Width
*m_RenderInfo
.Height
);
2025 void CTeletextDecoder::FillBorder(UTILS::COLOR::Color Color
)
2027 FillRect(m_TextureBuffer
+ (m_RenderInfo
.Height
-m_YOffset
)*m_RenderInfo
.Width
, m_RenderInfo
.Width
, 0, 25*m_RenderInfo
.FontHeight
, m_RenderInfo
.Width
, m_RenderInfo
.Height
-(25*m_RenderInfo
.FontHeight
), Color
);
2028 FillRect(m_TextureBuffer
+ m_RenderInfo
.Width
*m_YOffset
, m_RenderInfo
.Width
, 0, 25*m_RenderInfo
.FontHeight
, m_RenderInfo
.Width
, m_RenderInfo
.Height
-(25*m_RenderInfo
.FontHeight
), Color
);
2031 void CTeletextDecoder::FillRect(
2032 UTILS::COLOR::Color
* buffer
, int xres
, int x
, int y
, int w
, int h
, UTILS::COLOR::Color Color
)
2034 if (!buffer
) return;
2036 UTILS::COLOR::Color
* p
= buffer
+ x
+ y
* xres
;
2040 for ( ; h
> 0 ; h
--)
2042 SDL_memset4(p
, Color
, w
);
2048 void CTeletextDecoder::DrawVLine(
2049 UTILS::COLOR::Color
* lfb
, int xres
, int x
, int y
, int l
, UTILS::COLOR::Color color
)
2052 UTILS::COLOR::Color
* p
= lfb
+ x
+ y
* xres
;
2054 for ( ; l
> 0 ; l
--)
2061 void CTeletextDecoder::DrawHLine(
2062 UTILS::COLOR::Color
* lfb
, int xres
, int x
, int y
, int l
, UTILS::COLOR::Color color
)
2066 SDL_memset4(lfb
+ x
+ y
* xres
, color
, l
);
2069 void CTeletextDecoder::RenderDRCS(
2071 unsigned char* s
, /* pointer to char data, parity undecoded */
2072 UTILS::COLOR::Color
* d
, /* pointer to frame buffer of top left pixel */
2073 unsigned char* ax
, /* array[0..12] of x-offsets, array[0..10] of y-offsets for each pixel */
2074 UTILS::COLOR::Color fgcolor
,
2075 UTILS::COLOR::Color bgcolor
)
2077 if (d
== NULL
) return;
2079 unsigned char *ay
= ax
+ 13; /* array[0..10] of y-offsets for each pixel */
2081 for (int y
= 0; y
< 10; y
++) /* 10*2 bytes a 6 pixels per char definition */
2083 unsigned char c1
= deparity
[*s
++];
2084 unsigned char c2
= deparity
[*s
++];
2085 int h
= ay
[y
+1] - ay
[y
];
2089 if (((c1
== ' ') && (*(s
-2) != ' ')) || ((c2
== ' ') && (*(s
-1) != ' '))) /* parity error: stop decoding FIXME */
2091 for (int bit
= 0x20, x
= 0;
2093 bit
>>= 1, x
++) /* bit mask (MSB left), column counter */
2095 UTILS::COLOR::Color f1
= (c1
& bit
) ? fgcolor
: bgcolor
;
2096 UTILS::COLOR::Color f2
= (c2
& bit
) ? fgcolor
: bgcolor
;
2097 for (int i
= 0; i
< h
; i
++)
2099 if (ax
[x
+1] > ax
[x
])
2100 SDL_memset4(d
+ ax
[x
], f1
, ax
[x
+1] - ax
[x
]);
2101 if (ax
[x
+7] > ax
[x
+6])
2102 SDL_memset4(d
+ ax
[x
+6], f2
, ax
[x
+7] - ax
[x
+6]); /* 2nd byte 6 pixels to the right */
2111 void CTeletextDecoder::FillRectMosaicSeparated(UTILS::COLOR::Color
* lfb
,
2117 UTILS::COLOR::Color fgcolor
,
2118 UTILS::COLOR::Color bgcolor
,
2122 FillRect(lfb
,xres
,x
, y
, w
, h
, bgcolor
);
2125 FillRect(lfb
,xres
,x
+1, y
+1, w
-2, h
-2, fgcolor
);
2129 void CTeletextDecoder::FillTrapez(UTILS::COLOR::Color
* lfb
,
2137 UTILS::COLOR::Color color
)
2139 UTILS::COLOR::Color
* p
= lfb
+ x0
+ y0
* xres
;
2142 for (int yoffset
= 0; yoffset
< h
; yoffset
++)
2144 l
= l0
+ ((l1
-l0
) * yoffset
+ h
/2) / h
;
2145 xoffset
= (xoffset1
* yoffset
+ h
/2) / h
;
2147 SDL_memset4(p
+ xoffset
, color
, l
);
2152 void CTeletextDecoder::FlipHorz(UTILS::COLOR::Color
* lfb
, int xres
, int x
, int y
, int w
, int h
)
2154 UTILS::COLOR::Color buf
[2048];
2155 UTILS::COLOR::Color
* p
= lfb
+ x
+ y
* xres
;
2158 for (h1
= 0 ; h1
< h
; h1
++)
2160 SDL_memcpy4(buf
,p
,w
);
2161 for (w1
= 0 ; w1
< w
; w1
++)
2163 *(p
+w1
) = buf
[w
-(w1
+1)];
2169 void CTeletextDecoder::FlipVert(UTILS::COLOR::Color
* lfb
, int xres
, int x
, int y
, int w
, int h
)
2171 UTILS::COLOR::Color buf
[2048];
2172 UTILS::COLOR::Color
*p
= lfb
+ x
+ y
* xres
, *p1
, *p2
;
2175 for (h1
= 0 ; h1
< h
/2 ; h1
++)
2178 p2
= (p
+(h
-(h1
+1))*xres
);
2179 SDL_memcpy4(buf
, p1
, w
);
2180 SDL_memcpy4(p1
, p2
, w
);
2181 SDL_memcpy4(p2
, buf
, w
);
2185 int CTeletextDecoder::ShapeCoord(int param
, int curfontwidth
, int curFontHeight
)
2190 return curfontwidth
/3;
2192 return curfontwidth
/2;
2194 return curfontwidth
*2/3;
2196 return curfontwidth
;
2198 return curfontwidth
-3;
2200 return curFontHeight
/3;
2202 return curFontHeight
/2;
2204 return curFontHeight
*2/3;
2206 return curFontHeight
;
2212 void CTeletextDecoder::DrawShape(UTILS::COLOR::Color
* lfb
,
2220 UTILS::COLOR::Color fgcolor
,
2221 UTILS::COLOR::Color bgcolor
,
2224 if (!lfb
|| shapenumber
< 0x20 || shapenumber
> 0x7e || (shapenumber
== 0x7e && clear
))
2227 unsigned char *p
= aShapes
[shapenumber
- 0x20];
2238 FillRect(lfb
, xres
, x
, y
, curfontwidth
, FontHeight
, bgcolor
);
2246 int offset
= ShapeCoord(*p
++, curfontwidth
, curFontHeight
);
2247 DrawHLine(lfb
, xres
, x
, y
+ offset
, curfontwidth
, fgcolor
);
2252 int offset
= ShapeCoord(*p
++, curfontwidth
, curFontHeight
);
2253 DrawVLine(lfb
,xres
,x
+ offset
, y
, FontHeight
, fgcolor
);
2257 FlipHorz(lfb
,xres
,x
,y
,curfontwidth
, FontHeight
);
2260 FlipVert(lfb
,xres
,x
,y
,curfontwidth
, FontHeight
);
2264 int xo
= ShapeCoord(*p
++, curfontwidth
, curFontHeight
);
2265 int yo
= ShapeCoord(*p
++, curfontwidth
, curFontHeight
);
2266 int w
= ShapeCoord(*p
++, curfontwidth
, curFontHeight
);
2267 int h
= ShapeCoord(*p
++, curfontwidth
, curFontHeight
);
2268 FillRect(lfb
,xres
,x
+ xo
, y
+ yo
, w
, h
, fgcolor
);
2273 int x0
= ShapeCoord(*p
++, curfontwidth
, curFontHeight
);
2274 int y0
= ShapeCoord(*p
++, curfontwidth
, curFontHeight
);
2275 int l0
= ShapeCoord(*p
++, curfontwidth
, curFontHeight
);
2276 int x1
= ShapeCoord(*p
++, curfontwidth
, curFontHeight
);
2277 int y1
= ShapeCoord(*p
++, curfontwidth
, curFontHeight
);
2278 int l1
= ShapeCoord(*p
++, curfontwidth
, curFontHeight
);
2279 FillTrapez(lfb
, xres
,x
+ x0
, y
+ y0
, l0
, x1
-x0
, y1
-y0
, l1
, fgcolor
);
2284 int x0
= ShapeCoord(*p
++, curfontwidth
, curFontHeight
);
2285 int y0
= ShapeCoord(*p
++, curfontwidth
, curFontHeight
);
2286 int l0
= ShapeCoord(*p
++, curfontwidth
, curFontHeight
);
2287 int x1
= ShapeCoord(*p
++, curfontwidth
, curFontHeight
);
2288 int y1
= ShapeCoord(*p
++, curfontwidth
, curFontHeight
);
2289 int l1
= ShapeCoord(*p
++, curfontwidth
, curFontHeight
);
2290 FillTrapez(lfb
, xres
, x
+ x0
, y
+ y0
, l0
, x1
-x0
, y1
-y0
, l1
, bgcolor
);
2295 DrawShape(lfb
,xres
,x
, y
, ShapeCoord(*p
, curfontwidth
, curFontHeight
), curfontwidth
, FontHeight
, curFontHeight
, fgcolor
, bgcolor
, false);
2304 void CTeletextDecoder::RenderCharIntern(TextRenderInfo_t
* RenderInfo
, int Char
, TextPageAttr_t
*Attribute
, int zoom
, int yoffset
)
2308 UTILS::COLOR::Color bgcolor
, fgcolor
;
2309 int factor
, xfactor
;
2310 unsigned char *sbitbuffer
;
2312 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
2314 int national_subset_local
= m_txtCache
->NationalSubset
;
2315 int curfontwidth
= GetCurFontWidth();
2316 int t
= curfontwidth
;
2317 m_RenderInfo
.PosX
+= t
;
2318 int curfontwidth2
= GetCurFontWidth();
2319 m_RenderInfo
.PosX
-= t
;
2320 int alphachar
= RenderChar(m_TextureBuffer
+(yoffset
)*m_RenderInfo
.Width
, m_RenderInfo
.Width
, Char
, &m_RenderInfo
.PosX
, m_RenderInfo
.PosY
, Attribute
, zoom
> 0, curfontwidth
, curfontwidth2
, m_RenderInfo
.FontHeight
, m_RenderInfo
.TranspMode
, m_RenderInfo
.axdrcs
, m_Ascender
);
2321 if (alphachar
<= 0) return;
2323 if (zoom
&& Attribute
->doubleh
)
2325 else if (zoom
|| Attribute
->doubleh
)
2330 fgcolor
= GetColorRGB((enumTeletextColor
)Attribute
->fg
);
2331 if (m_RenderInfo
.TranspMode
&& m_RenderInfo
.PosY
< 24*m_RenderInfo
.FontHeight
)
2333 bgcolor
= GetColorRGB(TXT_ColorTransp
);
2337 bgcolor
= GetColorRGB((enumTeletextColor
)Attribute
->bg
);
2340 if (Attribute
->doublew
)
2342 curfontwidth
+= curfontwidth2
;
2348 // Check if the alphanumeric char has diacritical marks (or results from composing chars) or
2349 // on the other hand it is just a simple alphanumeric char
2350 if (!Attribute
->diacrit
)
2356 if ((national_subset_local
== NAT_SC
) || (national_subset_local
== NAT_RB
) ||
2357 (national_subset_local
== NAT_UA
))
2358 Char
= G2table
[1][0x20 + Attribute
->diacrit
];
2359 else if (national_subset_local
== NAT_GR
)
2360 Char
= G2table
[2][0x20 + Attribute
->diacrit
];
2361 else if (national_subset_local
== NAT_HB
)
2362 Char
= G2table
[3][0x20 + Attribute
->diacrit
];
2363 else if (national_subset_local
== NAT_AR
)
2364 Char
= G2table
[4][0x20 + Attribute
->diacrit
];
2366 Char
= G2table
[0][0x20 + Attribute
->diacrit
];
2368 // use harfbuzz to combine the diacritical mark with the alphanumeric char
2369 // fallback to the alphanumeric char if composition fails
2370 hb_unicode_funcs_t
* ufuncs
= hb_unicode_funcs_get_default();
2371 hb_codepoint_t composedChar
;
2372 const hb_bool_t isComposed
= hb_unicode_compose(ufuncs
, alphachar
, Char
, &composedChar
);
2373 Char
= isComposed
? composedChar
: alphachar
;
2377 if (!(glyph
= FT_Get_Char_Index(m_Face
, Char
)))
2379 CLog::Log(LOGERROR
, "{}: <FT_Get_Char_Index for Char {:x} \"{}\" failed", __FUNCTION__
,
2380 alphachar
, alphachar
);
2382 FillRect(m_TextureBuffer
, m_RenderInfo
.Width
, m_RenderInfo
.PosX
, m_RenderInfo
.PosY
+ yoffset
, curfontwidth
, factor
*m_RenderInfo
.FontHeight
, bgcolor
);
2383 m_RenderInfo
.PosX
+= curfontwidth
;
2387 if (FTC_SBitCache_Lookup(m_Cache
, &m_TypeTTF
, glyph
, &m_sBit
, &m_anode
) != 0)
2389 FillRect(m_TextureBuffer
, m_RenderInfo
.Width
, m_RenderInfo
.PosX
, m_RenderInfo
.PosY
+ yoffset
, curfontwidth
, m_RenderInfo
.FontHeight
, bgcolor
);
2390 m_RenderInfo
.PosX
+= curfontwidth
;
2394 sbitbuffer
= m_sBit
->buffer
;
2396 int backupTTFshiftY
= m_RenderInfo
.TTFShiftY
;
2397 if (national_subset_local
== NAT_AR
)
2398 m_RenderInfo
.TTFShiftY
= backupTTFshiftY
- 2; // for arabic TTF font should be shifted up slightly
2400 UTILS::COLOR::Color
* p
;
2401 int f
; /* running counter for zoom factor */
2402 int he
= m_sBit
->height
; // sbit->height should not be altered, I guess
2403 Row
= factor
* (m_Ascender
- m_sBit
->top
+ m_RenderInfo
.TTFShiftY
);
2406 sbitbuffer
-= m_sBit
->pitch
*Row
;
2412 FillRect(m_TextureBuffer
, m_RenderInfo
.Width
, m_RenderInfo
.PosX
, m_RenderInfo
.PosY
+ yoffset
, curfontwidth
, Row
, bgcolor
); /* fill upper margin */
2415 if (m_Ascender
- m_sBit
->top
+ m_RenderInfo
.TTFShiftY
+ he
> m_RenderInfo
.FontHeight
)
2416 he
= m_RenderInfo
.FontHeight
- m_Ascender
+ m_sBit
->top
- m_RenderInfo
.TTFShiftY
; /* limit char height to defined/calculated FontHeight */
2417 if (he
< 0) he
= m_RenderInfo
.FontHeight
;
2419 p
= m_TextureBuffer
+ m_RenderInfo
.PosX
+ (yoffset
+ m_RenderInfo
.PosY
+ Row
) * m_RenderInfo
.Width
; /* running pointer into framebuffer */
2420 for (Row
= he
; Row
; Row
--) /* row counts up, but down may be a little faster :) */
2422 int pixtodo
= m_sBit
->width
;
2423 UTILS::COLOR::Color
* pstart
= p
;
2425 for (int Bit
= xfactor
* (m_sBit
->left
+ m_RenderInfo
.TTFShiftX
); Bit
> 0; Bit
--) /* fill left margin */
2427 for (f
= factor
-1; f
>= 0; f
--)
2428 *(p
+ f
*m_RenderInfo
.Width
) = bgcolor
;
2432 for (Pitch
= m_sBit
->pitch
; Pitch
; Pitch
--)
2434 for (int Bit
= 0x80; Bit
; Bit
>>= 1)
2436 UTILS::COLOR::Color color
;
2441 if (*sbitbuffer
& Bit
) /* bit set -> foreground */
2443 else /* bit not set -> background */
2446 for (f
= factor
-1; f
>= 0; f
--)
2447 *(p
+ f
*m_RenderInfo
.Width
) = color
;
2450 if (xfactor
> 1) /* double width */
2452 for (f
= factor
-1; f
>= 0; f
--)
2453 *(p
+ f
*m_RenderInfo
.Width
) = color
;
2459 for (int Bit
= (curfontwidth
- xfactor
*(m_sBit
->width
+ m_sBit
->left
+ m_RenderInfo
.TTFShiftX
));
2460 Bit
> 0; Bit
--) /* fill rest of char width */
2462 for (f
= factor
-1; f
>= 0; f
--)
2463 *(p
+ f
*m_RenderInfo
.Width
) = bgcolor
;
2467 p
= pstart
+ factor
*m_RenderInfo
.Width
;
2470 Row
= m_Ascender
- m_sBit
->top
+ he
+ m_RenderInfo
.TTFShiftY
;
2471 FillRect(m_TextureBuffer
,
2474 m_RenderInfo
.PosY
+ yoffset
+ Row
* factor
,
2476 (m_RenderInfo
.FontHeight
- Row
) * factor
,
2477 bgcolor
); /* fill lower margin */
2479 if (Attribute
->underline
)
2480 FillRect(m_TextureBuffer
,
2483 m_RenderInfo
.PosY
+ yoffset
+ (m_RenderInfo
.FontHeight
-2)* factor
,
2486 fgcolor
); /* underline char */
2488 m_RenderInfo
.PosX
+= curfontwidth
;
2489 m_RenderInfo
.TTFShiftY
= backupTTFshiftY
; // restore TTFShiftY
2492 int CTeletextDecoder::RenderChar(
2493 UTILS::COLOR::Color
* buffer
, // pointer to render buffer, min. FontHeight*2*xres
2494 int xres
, // length of 1 line in render buffer
2495 int Char
, // character to render
2497 pPosX
, // left border for rendering relative to *buffer, will be set to right border after rendering
2498 int PosY
, // vertical position of char in *buffer
2499 TextPageAttr_t
* Attribute
, // Attributes of Char
2500 bool zoom
, // 1= character will be rendered in double height
2501 int curfontwidth
, // rendering width of character
2502 int curfontwidth2
, // rendering width of next character (needed for doublewidth)
2503 int FontHeight
, // height of character
2504 bool transpmode
, // 1= transparent display
2505 unsigned char* axdrcs
, // width and height of DRCS-chars
2506 int Ascender
) // Ascender of font
2508 UTILS::COLOR::Color bgcolor
, fgcolor
;
2509 int factor
, xfactor
;
2511 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
2513 int national_subset_local
= m_txtCache
->NationalSubset
;
2515 ymosaic
[0] = 0; /* y-offsets for 2*3 mosaic */
2516 ymosaic
[1] = (FontHeight
+ 1) / 3;
2517 ymosaic
[2] = (FontHeight
* 2 + 1) / 3;
2518 ymosaic
[3] = FontHeight
;
2520 if (Attribute
->setX26
)
2522 national_subset_local
= 0; // no national subset
2525 // G0+G2 set designation
2526 if (Attribute
->setG0G2
!= 0x3f)
2528 switch (Attribute
->setG0G2
)
2531 national_subset_local
= NAT_SC
;
2534 national_subset_local
= NAT_RB
;
2537 national_subset_local
= NAT_UA
;
2540 national_subset_local
= NAT_GR
;
2543 national_subset_local
= NAT_HB
;
2547 national_subset_local
= NAT_AR
;
2550 national_subset_local
= CountryConversionTable
[Attribute
->setG0G2
& 0x07];
2555 if (Attribute
->charset
== C_G0S
) // use secondary charset
2556 national_subset_local
= m_txtCache
->NationalSubsetSecondary
;
2557 if (zoom
&& Attribute
->doubleh
)
2559 else if (zoom
|| Attribute
->doubleh
)
2564 if (Attribute
->doublew
)
2566 curfontwidth
+= curfontwidth2
;
2572 if (Char
== 0xFF) /* skip doubleheight chars in lower line */
2574 *pPosX
+= curfontwidth
;
2579 if (Attribute
->inverted
)
2581 int t
= Attribute
->fg
;
2582 Attribute
->fg
= Attribute
->bg
;
2585 fgcolor
= GetColorRGB((enumTeletextColor
)Attribute
->fg
);
2586 if (transpmode
== true && PosY
< 24*FontHeight
)
2588 bgcolor
= GetColorRGB(TXT_ColorTransp
);
2592 bgcolor
= GetColorRGB((enumTeletextColor
)Attribute
->bg
);
2596 if ((Attribute
->charset
== C_G1C
|| Attribute
->charset
== C_G1S
) &&
2597 ((Char
&0xA0) == 0x20))
2599 int w1
= (curfontwidth
/ 2 ) *xfactor
;
2600 int w2
= (curfontwidth
- w1
) *xfactor
;
2602 Char
= (Char
& 0x1f) | ((Char
& 0x40) >> 1);
2603 if (Attribute
->charset
== C_G1S
) /* separated mosaic */
2605 for (int y
= 0; y
< 3; y
++)
2607 FillRectMosaicSeparated(buffer
, xres
,*pPosX
, PosY
+ ymosaic
[y
]*factor
, w1
, (ymosaic
[y
+1] - ymosaic
[y
])*factor
, fgcolor
, bgcolor
, Char
& 0x01);
2608 FillRectMosaicSeparated(buffer
, xres
,*pPosX
+ w1
, PosY
+ ymosaic
[y
]*factor
, w2
, (ymosaic
[y
+1] - ymosaic
[y
])*factor
, fgcolor
, bgcolor
, Char
& 0x02);
2614 for (int y
= 0; y
< 3; y
++)
2616 FillRect(buffer
, xres
, *pPosX
, PosY
+ ymosaic
[y
]*factor
, w1
, (ymosaic
[y
+1] - ymosaic
[y
])*factor
, (Char
& 0x01) ? fgcolor
: bgcolor
);
2617 FillRect(buffer
, xres
, *pPosX
+ w1
, PosY
+ ymosaic
[y
]*factor
, w2
, (ymosaic
[y
+1] - ymosaic
[y
])*factor
, (Char
& 0x02) ? fgcolor
: bgcolor
);
2622 *pPosX
+= curfontwidth
;
2626 if (Attribute
->charset
== C_G3
)
2628 if (Char
< 0x20 || Char
> 0x7d)
2634 if (*aShapes
[Char
- 0x20] == S_CHR
)
2636 unsigned char *p
= aShapes
[Char
- 0x20];
2637 Char
= (*(p
+1) <<8) + (*(p
+2));
2639 else if (*aShapes
[Char
- 0x20] == S_ADT
)
2644 UTILS::COLOR::Color
* p
= buffer
+ *pPosX
+ PosY
* xres
;
2645 for (y
=0; y
<FontHeight
;y
++)
2647 for (f
=0; f
<factor
; f
++)
2649 for (x
=0; x
<curfontwidth
*xfactor
;x
++)
2651 c
= (y
&4 ? (x
/3)&1 :((x
+3)/3)&1);
2652 *(p
+x
) = (c
? fgcolor
: bgcolor
);
2658 *pPosX
+= curfontwidth
;
2663 DrawShape(buffer
, xres
,*pPosX
, PosY
, Char
, curfontwidth
, FontHeight
, factor
*FontHeight
, fgcolor
, bgcolor
, true);
2664 *pPosX
+= curfontwidth
;
2669 else if (Attribute
->charset
>= C_OFFSET_DRCS
)
2671 TextCachedPage_t
*pcache
= m_txtCache
->astCachetable
[(Attribute
->charset
& 0x10) ? m_txtCache
->drcs
: m_txtCache
->gdrcs
][Attribute
->charset
& 0x0f];
2674 unsigned char drcs_data
[23*40];
2675 auto& components
= CServiceBroker::GetAppComponents();
2676 const auto appPlayer
= components
.GetComponent
<CApplicationPlayer
>();
2677 appPlayer
->LoadPage((Attribute
->charset
& 0x10) ? m_txtCache
->drcs
: m_txtCache
->gdrcs
,
2678 Attribute
->charset
& 0x0f, drcs_data
);
2681 p
= drcs_data
+ 20*Char
;
2682 else if (pcache
->pageinfo
.p24
)
2683 p
= pcache
->pageinfo
.p24
+ 20*(Char
- 23*2);
2686 FillRect(buffer
, xres
,*pPosX
, PosY
, curfontwidth
, factor
*FontHeight
, bgcolor
);
2687 *pPosX
+= curfontwidth
;
2690 axdrcs
[12] = curfontwidth
; /* adjust last x-offset according to position, FIXME: double width */
2691 RenderDRCS(xres
, p
, buffer
+ *pPosX
+ PosY
* xres
, axdrcs
, fgcolor
, bgcolor
);
2695 FillRect(buffer
,xres
,*pPosX
, PosY
, curfontwidth
, factor
*FontHeight
, bgcolor
);
2697 *pPosX
+= curfontwidth
;
2700 else if (Attribute
->charset
== C_G2
&& Char
>= 0x20 && Char
<= 0x7F)
2702 if ((national_subset_local
== NAT_SC
) || (national_subset_local
== NAT_RB
) || (national_subset_local
== NAT_UA
))
2703 Char
= G2table
[1][Char
-0x20];
2704 else if (national_subset_local
== NAT_GR
)
2705 Char
= G2table
[2][Char
-0x20];
2706 else if (national_subset_local
== NAT_AR
)
2707 Char
= G2table
[3][Char
-0x20];
2709 Char
= G2table
[0][Char
-0x20];
2713 // FillRect(buffer,xres,*pPosX, PosY, curfontwidth, factor*Ascender, fgcolor);
2714 // FillRect(buffer,xres,*pPosX, PosY + factor*Ascender, curfontwidth, factor*(FontHeight-Ascender), bgcolor);
2715 // *pPosX += curfontwidth;
2719 else if (national_subset_local
== NAT_SC
&& Char
>= 0x20 && Char
<= 0x7F) /* remap complete areas for serbian/croatian */
2720 Char
= G0table
[0][Char
-0x20];
2721 else if (national_subset_local
== NAT_RB
&& Char
>= 0x20 && Char
<= 0x7F) /* remap complete areas for russian/bulgarian */
2722 Char
= G0table
[1][Char
-0x20];
2723 else if (national_subset_local
== NAT_UA
&& Char
>= 0x20 && Char
<= 0x7F) /* remap complete areas for ukrainian */
2724 Char
= G0table
[2][Char
-0x20];
2725 else if (national_subset_local
== NAT_GR
&& Char
>= 0x20 && Char
<= 0x7F) /* remap complete areas for greek */
2726 Char
= G0table
[3][Char
-0x20];
2727 else if (national_subset_local
== NAT_HB
&& Char
>= 0x20 && Char
<= 0x7F) /* remap complete areas for hebrew */
2728 Char
= G0table
[4][Char
-0x20];
2729 else if (national_subset_local
== NAT_AR
&& Char
>= 0x20 && Char
<= 0x7F) /* remap complete areas for arabic */
2730 Char
= G0table
[5][Char
-0x20];
2738 FillRect(buffer
, xres
, *pPosX
, PosY
, curfontwidth
, factor
*FontHeight
, bgcolor
);
2739 *pPosX
+= curfontwidth
;
2743 Char
= nationaltable23
[national_subset_local
][Char
-0x23];
2746 Char
= nationaltable40
[national_subset_local
];
2754 Char
= nationaltable5b
[national_subset_local
][Char
-0x5B];
2760 Char
= nationaltable7b
[national_subset_local
][Char
-0x7B];
2763 FillRect(buffer
,xres
,*pPosX
, PosY
, curfontwidth
, factor
*Ascender
, fgcolor
);
2764 FillRect(buffer
,xres
,*pPosX
, PosY
+ factor
*Ascender
, curfontwidth
, factor
*(FontHeight
-Ascender
), bgcolor
);
2765 *pPosX
+= curfontwidth
;
2768 DrawHLine(buffer
,xres
,*pPosX
, PosY
, curfontwidth
, fgcolor
);
2769 DrawVLine(buffer
,xres
,*pPosX
, PosY
+1, FontHeight
-1, fgcolor
);
2770 FillRect(buffer
,xres
,*pPosX
+1, PosY
+1, curfontwidth
-1, FontHeight
-1, bgcolor
);
2771 *pPosX
+= curfontwidth
;
2774 DrawHLine(buffer
,xres
,*pPosX
, PosY
, curfontwidth
, fgcolor
);
2775 FillRect(buffer
,xres
,*pPosX
, PosY
+1, curfontwidth
, FontHeight
-1, bgcolor
);
2776 *pPosX
+= curfontwidth
;
2779 DrawHLine(buffer
,xres
,*pPosX
, PosY
, curfontwidth
, fgcolor
);
2780 DrawVLine(buffer
,xres
,*pPosX
+ curfontwidth
-1, PosY
+1, FontHeight
-1, fgcolor
);
2781 FillRect(buffer
,xres
,*pPosX
, PosY
+1, curfontwidth
-1, FontHeight
-1, bgcolor
);
2782 *pPosX
+= curfontwidth
;
2785 DrawVLine(buffer
,xres
,*pPosX
, PosY
, FontHeight
, fgcolor
);
2786 FillRect(buffer
,xres
,*pPosX
+1, PosY
, curfontwidth
-1, FontHeight
, bgcolor
);
2787 *pPosX
+= curfontwidth
;
2790 DrawVLine(buffer
,xres
,*pPosX
+ curfontwidth
-1, PosY
, FontHeight
, fgcolor
);
2791 FillRect(buffer
,xres
,*pPosX
, PosY
, curfontwidth
-1, FontHeight
, bgcolor
);
2792 *pPosX
+= curfontwidth
;
2795 DrawHLine(buffer
,xres
,*pPosX
, PosY
+ FontHeight
-1, curfontwidth
, fgcolor
);
2796 DrawVLine(buffer
,xres
,*pPosX
, PosY
, FontHeight
-1, fgcolor
);
2797 FillRect(buffer
,xres
,*pPosX
+1, PosY
, curfontwidth
-1, FontHeight
-1, bgcolor
);
2798 *pPosX
+= curfontwidth
;
2801 DrawHLine(buffer
,xres
,*pPosX
, PosY
+ FontHeight
-1, curfontwidth
, fgcolor
);
2802 FillRect(buffer
,xres
,*pPosX
, PosY
, curfontwidth
, FontHeight
-1, bgcolor
);
2803 *pPosX
+= curfontwidth
;
2806 DrawHLine(buffer
,xres
,*pPosX
, PosY
+ FontHeight
-1, curfontwidth
, fgcolor
);
2807 DrawVLine(buffer
,xres
,*pPosX
+ curfontwidth
-1, PosY
, FontHeight
-1, fgcolor
);
2808 FillRect(buffer
,xres
,*pPosX
, PosY
, curfontwidth
-1, FontHeight
-1, bgcolor
);
2809 *pPosX
+= curfontwidth
;
2812 FillRect(buffer
,xres
,*pPosX
+1, PosY
, curfontwidth
-1, FontHeight
, bgcolor
);
2813 for (int Row
=0; Row
< curfontwidth
/2; Row
++)
2814 DrawVLine(buffer
,xres
,*pPosX
+ Row
, PosY
+ Row
, FontHeight
- Row
, fgcolor
);
2815 *pPosX
+= curfontwidth
;
2818 FillRect(buffer
,xres
,*pPosX
, PosY
, curfontwidth
/2, FontHeight
, fgcolor
);
2819 FillRect(buffer
,xres
,*pPosX
+ curfontwidth
/2, PosY
, (curfontwidth
+1)/2, FontHeight
, bgcolor
);
2820 *pPosX
+= curfontwidth
;
2822 case 0xEA: /* ∞ */
2823 FillRect(buffer
,xres
,*pPosX
, PosY
, curfontwidth
, FontHeight
, bgcolor
);
2824 FillRect(buffer
,xres
,*pPosX
, PosY
, curfontwidth
/2, curfontwidth
/2, fgcolor
);
2825 *pPosX
+= curfontwidth
;
2828 FillRect(buffer
,xres
,*pPosX
, PosY
+1, curfontwidth
, FontHeight
-1, bgcolor
);
2829 for (int Row
=0; Row
< curfontwidth
/2; Row
++)
2830 DrawHLine(buffer
,xres
,*pPosX
+ Row
, PosY
+ Row
, curfontwidth
- Row
, fgcolor
);
2831 *pPosX
+= curfontwidth
;
2834 FillRect(buffer
, xres
,*pPosX
, PosY
, curfontwidth
, curfontwidth
/2, fgcolor
);
2835 FillRect(buffer
, xres
,*pPosX
, PosY
+ curfontwidth
/2, curfontwidth
, FontHeight
- curfontwidth
/2, bgcolor
);
2836 *pPosX
+= curfontwidth
;
2846 Char
= arrowtable
[Char
- 0xED];
2854 FillRect(buffer
, xres
, *pPosX
, PosY
, curfontwidth
, factor
*FontHeight
, bgcolor
);
2855 *pPosX
+= curfontwidth
;
2858 return Char
; // Char is an alphanumeric unicode character
2861 TextPageinfo_t
* CTeletextDecoder::DecodePage(bool showl25
, // 1=decode Level2.5-graphics
2862 unsigned char* PageChar
, // page buffer, min. 25*40
2863 TextPageAttr_t
*PageAtrb
, // attribute buffer, min 25*40
2864 bool HintMode
, // 1=show hidden information
2865 bool showflof
) // 1=decode FLOF-line
2869 int foreground
, background
, doubleheight
, doublewidth
, charset
, previous_charset
, mosaictype
, IgnoreAtBlackBgSubst
, concealed
, flashmode
, boxwin
;
2870 unsigned char held_mosaic
, *p
;
2871 TextCachedPage_t
*pCachedPage
;
2873 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
2875 /* copy page to decode buffer */
2876 if (m_txtCache
->SubPageTable
[m_txtCache
->Page
] == 0xff) /* not cached: do nothing */
2879 if (m_txtCache
->ZapSubpageManual
)
2880 pCachedPage
= m_txtCache
->astCachetable
[m_txtCache
->Page
][m_txtCache
->SubPage
];
2882 pCachedPage
= m_txtCache
->astCachetable
[m_txtCache
->Page
][m_txtCache
->SubPageTable
[m_txtCache
->Page
]];
2883 if (!pCachedPage
) /* not cached: do nothing */
2886 auto& components
= CServiceBroker::GetAppComponents();
2887 const auto appPlayer
= components
.GetComponent
<CApplicationPlayer
>();
2888 appPlayer
->LoadPage(m_txtCache
->Page
, m_txtCache
->SubPage
, &PageChar
[40]);
2890 memcpy(&PageChar
[8], pCachedPage
->p0
, 24); /* header line without TimeString */
2892 TextPageinfo_t
* PageInfo
= &(pCachedPage
->pageinfo
);
2894 memcpy(&PageChar
[24*40], PageInfo
->p24
, 40); /* line 25 for FLOF */
2896 /* copy TimeString */
2897 memcpy(&PageChar
[32], &m_txtCache
->TimeString
, 8);
2900 /* check for newsflash & subtitle */
2901 if (PageInfo
->boxed
&& IsDec(m_txtCache
->Page
))
2910 memset(PageChar
, ' ', 40);
2914 memset(PageChar
, ' ', 8);
2915 CDVDTeletextTools::Hex2Str((char*)PageChar
+3, m_txtCache
->Page
);
2916 if (m_txtCache
->SubPage
)
2920 CDVDTeletextTools::Hex2Str((char*)PageChar
+6, m_txtCache
->SubPage
);
2924 if (!IsDec(m_txtCache
->Page
))
2926 TextPageAttr_t atr
= { TXT_ColorWhite
, TXT_ColorBlack
, C_G0P
, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f};
2927 if (PageInfo
->function
== FUNC_MOT
) /* magazine organization table */
2929 for (col
= 0; col
< 24*40; col
++)
2930 PageAtrb
[col
] = atr
;
2931 for (col
= 40; col
< 24*40; col
++)
2932 PageChar
[col
] = number2char(PageChar
[col
]);
2933 return PageInfo
; /* don't interpret irregular pages */
2935 else if (PageInfo
->function
== FUNC_GPOP
|| PageInfo
->function
== FUNC_POP
) /* object definitions */
2937 for (int col
= 0; col
< 24*40; col
++)
2938 PageAtrb
[col
] = atr
;
2941 for (int row
= 1; row
< 12; row
++)
2943 *p
++ = number2char(row
); /* first column: number (0-9, A-..) */
2944 for (int col
= 1; col
< 40; col
+= 3)
2946 int d
= CDVDTeletextTools::deh24(p
);
2949 memcpy(p
, "???", 3);
2954 *p
++ = number2char((d
>> 6) & 0x1f); /* mode */
2955 *p
++ = number2char(d
& 0x3f); /* address */
2956 *p
++ = number2char((d
>> 11) & 0x7f); /* data */
2960 return PageInfo
; /* don't interpret irregular pages */
2962 else if (PageInfo
->function
== FUNC_GDRCS
|| PageInfo
->function
== FUNC_DRCS
) /* character definitions */
2964 return PageInfo
; /* don't interpret irregular pages */
2968 int h
, parityerror
= 0;
2970 for (int i
= 0; i
< 8; i
++)
2973 /* decode parity/hamming */
2974 for (unsigned int i
= 40; i
< TELETEXT_PAGE_SIZE
; i
++)
2979 if (parityerror
&& h
!= 0xFF) /* if no regular page (after any parity error) */
2980 CDVDTeletextTools::Hex2Str((char*)p
, h
); /* first try dehamming */
2983 if (*p
== ' ' || deparity
[*p
] != ' ') /* correct parity */
2988 if (h
!= 0xFF) /* first parity error: try dehamming */
2989 CDVDTeletextTools::Hex2Str((char*)p
, h
);
2997 return PageInfo
; /* don't interpret irregular pages */
3001 int mosaic_pending
,esc_pending
;
3003 for (int row
= 0; row
< ((showflof
&& PageInfo
->p24
) ? 25 : 24); row
++)
3005 /* start-of-row default conditions */
3006 foreground
= TXT_ColorWhite
;
3007 background
= TXT_ColorBlack
;
3010 charset
= previous_charset
= C_G0P
; // remember charset for switching back after mosaic charset was used
3018 IgnoreAtBlackBgSubst
= 0;
3019 mosaic_pending
= esc_pending
= 0; // we need to render at least one mosaic char if 'esc' is received immediately after mosaic charset switch on
3021 if (boxed
&& memchr(&PageChar
[row
*40], start_box
, 40) == 0)
3023 foreground
= TXT_ColorTransp
;
3024 background
= TXT_ColorTransp
;
3027 for (int col
= 0; col
< 40; col
++)
3029 int index
= row
*40 + col
;
3031 PageAtrb
[index
].fg
= foreground
;
3032 PageAtrb
[index
].bg
= background
;
3033 PageAtrb
[index
].charset
= charset
;
3034 PageAtrb
[index
].doubleh
= doubleheight
;
3035 PageAtrb
[index
].doublew
= (col
< 39 ? doublewidth
: 0);
3036 PageAtrb
[index
].IgnoreAtBlackBgSubst
= IgnoreAtBlackBgSubst
;
3037 PageAtrb
[index
].concealed
= concealed
;
3038 PageAtrb
[index
].flashing
= flashmode
;
3039 PageAtrb
[index
].boxwin
= boxwin
;
3040 PageAtrb
[index
].inverted
= 0; // only relevant for Level 2.5
3041 PageAtrb
[index
].underline
= 0; // only relevant for Level 2.5
3042 PageAtrb
[index
].diacrit
= 0; // only relevant for Level 2.5
3043 PageAtrb
[index
].setX26
= 0; // only relevant for Level 2.5
3044 PageAtrb
[index
].setG0G2
= 0x3f; // only relevant for Level 2.5
3046 if (PageChar
[index
] < ' ')
3048 if (esc_pending
) { // mosaic char has been rendered and we can switch charsets
3049 charset
= previous_charset
;
3050 if (charset
== C_G0P
)
3051 charset
= previous_charset
= C_G0S
;
3052 else if (charset
== C_G0S
)
3053 charset
= previous_charset
= C_G0P
;
3056 switch (PageChar
[index
])
3067 foreground
= PageChar
[index
] - alpha_black
+ TXT_ColorBlack
;
3068 if (col
== 0 && PageChar
[index
] == alpha_white
)
3069 PageAtrb
[index
].fg
= TXT_ColorBlack
; // indicate level 1 color change on column 0; (hack)
3070 if ((charset
!=C_G0P
) && (charset
!=C_G0S
)) // we need to change charset to state it was before mosaic
3071 charset
= previous_charset
;
3080 PageAtrb
[index
].flashing
= 0;
3085 IgnoreAtBlackBgSubst
= 0;
3096 PageAtrb
[index
].doubleh
= doubleheight
;
3097 PageAtrb
[index
].doublew
= doublewidth
;
3131 case mosaic_magenta
:
3135 foreground
= PageChar
[index
] - mosaic_black
+ TXT_ColorBlack
;
3136 if ((charset
==C_G0P
) || (charset
==C_G0S
))
3137 previous_charset
=charset
;
3138 charset
= mosaictype
? C_G1S
: C_G1C
;
3143 PageAtrb
[index
].concealed
= 1;
3147 foreground
= background
;
3148 PageAtrb
[index
].fg
= foreground
;
3152 case contiguous_mosaic
:
3154 if (charset
== C_G1S
)
3157 PageAtrb
[index
].charset
= charset
;
3161 case separated_mosaic
:
3163 if (charset
== C_G1C
)
3166 PageAtrb
[index
].charset
= charset
;
3171 if (!mosaic_pending
) { // if mosaic is pending we need to wait before mosaic arrives
3172 if ((charset
!= C_G0P
) && (charset
!= C_G0S
)) // we need to switch to charset which was active before mosaic
3173 charset
= previous_charset
;
3174 if (charset
== C_G0P
)
3175 charset
= previous_charset
= C_G0S
;
3176 else if (charset
== C_G0S
)
3177 charset
= previous_charset
= C_G0P
;
3178 } else esc_pending
= 1;
3181 case black_background
:
3182 background
= TXT_ColorBlack
;
3183 IgnoreAtBlackBgSubst
= 0;
3184 PageAtrb
[index
].bg
= background
;
3185 PageAtrb
[index
].IgnoreAtBlackBgSubst
= IgnoreAtBlackBgSubst
;
3188 case new_background
:
3189 background
= foreground
;
3190 if (background
== TXT_ColorBlack
)
3191 IgnoreAtBlackBgSubst
= 1;
3193 IgnoreAtBlackBgSubst
= 0;
3194 PageAtrb
[index
].bg
= background
;
3195 PageAtrb
[index
].IgnoreAtBlackBgSubst
= IgnoreAtBlackBgSubst
;
3202 case release_mosaic
:
3207 /* handle spacing attributes */
3208 if (hold
&& (PageAtrb
[index
].charset
== C_G1C
|| PageAtrb
[index
].charset
== C_G1S
))
3209 PageChar
[index
] = held_mosaic
;
3211 PageChar
[index
] = ' ';
3216 else /* char >= ' ' */
3218 mosaic_pending
= 0; // charset will be switched next if esc_pending
3219 /* set new held-mosaic char */
3220 if ((charset
== C_G1C
|| charset
== C_G1S
) &&
3221 ((PageChar
[index
]&0xA0) == 0x20))
3222 held_mosaic
= PageChar
[index
];
3223 if (PageAtrb
[index
].doubleh
)
3224 PageChar
[index
+ 40] = 0xFF;
3227 if (!(charset
== C_G1C
|| charset
== C_G1S
))
3228 held_mosaic
= ' '; /* forget if outside mosaic */
3232 /* skip row if doubleheight */
3233 if (row
< 23 && dhset
)
3235 for (int col
= 0; col
< 40; col
++)
3237 int index
= row
*40 + col
;
3238 PageAtrb
[index
+40].bg
= PageAtrb
[index
].bg
;
3239 PageAtrb
[index
+40].fg
= TXT_ColorWhite
;
3240 if (!PageAtrb
[index
].doubleh
)
3241 PageChar
[index
+40] = ' ';
3242 PageAtrb
[index
+40].flashing
= 0;
3243 PageAtrb
[index
+40].charset
= C_G0P
;
3244 PageAtrb
[index
+40].doubleh
= 0;
3245 PageAtrb
[index
+40].doublew
= 0;
3246 PageAtrb
[index
+40].IgnoreAtBlackBgSubst
= 0;
3247 PageAtrb
[index
+40].concealed
= 0;
3248 PageAtrb
[index
+40].flashing
= 0;
3249 PageAtrb
[index
+40].boxwin
= PageAtrb
[index
].boxwin
;
3254 m_txtCache
->FullScrColor
= TXT_ColorBlack
;
3257 Eval_l25(PageChar
, PageAtrb
, HintMode
);
3259 /* handle Black Background Color Substitution and transparency (CLUT1#0) */
3264 for (unsigned char row
: m_txtCache
->FullRowColor
)
3266 for (int c
= 0; c
< 40; c
++)
3268 bitmask
= (PageAtrb
[o
].bg
== 0x08 ? 0x08 : 0x00) | (row
== 0x08 ? 0x04 : 0x00) | (PageAtrb
[o
].boxwin
<<1) | (int)boxed
;
3274 PageAtrb
[o
].bg
= m_txtCache
->FullScrColor
;
3276 PageAtrb
[o
].bg
= row
;
3286 PageAtrb
[o
].bg
= TXT_ColorTransp
;
3289 bitmask
= (PageAtrb
[o
].fg
== 0x08 ? 0x08 : 0x00) | (row
== 0x08 ? 0x04 : 0x00) | (PageAtrb
[o
].boxwin
<<1) | (int)boxed
;
3295 PageAtrb
[o
].fg
= m_txtCache
->FullScrColor
;
3297 PageAtrb
[o
].fg
= row
;
3307 PageAtrb
[o
].fg
= TXT_ColorTransp
;
3317 void CTeletextDecoder::Eval_l25(unsigned char* PageChar
, TextPageAttr_t
*PageAtrb
, bool HintMode
)
3319 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
3321 memset(m_txtCache
->FullRowColor
, 0, sizeof(m_txtCache
->FullRowColor
));
3322 m_txtCache
->FullScrColor
= TXT_ColorBlack
;
3323 m_txtCache
->ColorTable
= NULL
;
3325 if (!m_txtCache
->astCachetable
[m_txtCache
->Page
][m_txtCache
->SubPage
])
3329 if (IsDec(m_txtCache
->Page
))
3331 unsigned char APx0
, APy0
, APx
, APy
;
3332 TextPageinfo_t
*pi
= &(m_txtCache
->astCachetable
[m_txtCache
->Page
][m_txtCache
->SubPage
]->pageinfo
);
3333 TextCachedPage_t
*pmot
= m_txtCache
->astCachetable
[(m_txtCache
->Page
& 0xf00) | 0xfe][0];
3334 int p26Received
= 0;
3335 int BlackBgSubst
= 0;
3336 int ColorTableRemapping
= 0;
3338 m_txtCache
->pop
= m_txtCache
->gpop
= m_txtCache
->drcs
= m_txtCache
->gdrcs
= 0;
3342 TextExtData_t
*e
= pi
->ext
;
3349 Textp27_t
*p27
= e
->p27
;
3351 m_txtCache
->gpop
= p27
[0].page
;
3353 m_txtCache
->pop
= p27
[1].page
;
3355 m_txtCache
->gdrcs
= p27
[2].page
;
3357 m_txtCache
->drcs
= p27
[3].page
;
3362 m_txtCache
->ColorTable
= e
->bgr
;
3363 BlackBgSubst
= e
->BlackBgSubst
;
3364 ColorTableRemapping
= e
->ColorTableRemapping
;
3365 memset(m_txtCache
->FullRowColor
, e
->DefRowColor
, sizeof(m_txtCache
->FullRowColor
));
3366 m_txtCache
->FullScrColor
= e
->DefScreenColor
;
3367 m_txtCache
->NationalSubset
= SetNational(e
->DefaultCharset
);
3368 m_txtCache
->NationalSubsetSecondary
= SetNational(e
->SecondCharset
);
3369 } /* e->p28Received */
3372 if (!m_txtCache
->ColorTable
&& m_txtCache
->astP29
[m_txtCache
->Page
>> 8])
3374 TextExtData_t
*e
= m_txtCache
->astP29
[m_txtCache
->Page
>> 8];
3375 m_txtCache
->ColorTable
= e
->bgr
;
3376 BlackBgSubst
= e
->BlackBgSubst
;
3377 ColorTableRemapping
= e
->ColorTableRemapping
;
3378 memset(m_txtCache
->FullRowColor
, e
->DefRowColor
, sizeof(m_txtCache
->FullRowColor
));
3379 m_txtCache
->FullScrColor
= e
->DefScreenColor
;
3380 m_txtCache
->NationalSubset
= SetNational(e
->DefaultCharset
);
3381 m_txtCache
->NationalSubsetSecondary
= SetNational(e
->SecondCharset
);
3384 if (ColorTableRemapping
)
3386 for (int i
= 0; i
< 25*40; i
++)
3388 PageAtrb
[i
].fg
+= MapTblFG
[ColorTableRemapping
- 1];
3389 if (!BlackBgSubst
|| PageAtrb
[i
].bg
!= TXT_ColorBlack
|| PageAtrb
[i
].IgnoreAtBlackBgSubst
)
3390 PageAtrb
[i
].bg
+= MapTblBG
[ColorTableRemapping
- 1];
3394 /* determine ?pop/?drcs from MOT */
3397 unsigned char pmot_data
[23*40];
3398 auto& components
= CServiceBroker::GetAppComponents();
3399 const auto appPlayer
= components
.GetComponent
<CApplicationPlayer
>();
3400 appPlayer
->LoadPage((m_txtCache
->Page
& 0xf00) | 0xfe, 0, pmot_data
);
3402 unsigned char *p
= pmot_data
; /* start of link data */
3403 int o
= 2 * (((m_txtCache
->Page
& 0xf0) >> 4) * 10 + (m_txtCache
->Page
& 0x0f)); /* offset of links for current page */
3404 int opop
= p
[o
] & 0x07; /* index of POP link */
3405 int odrcs
= p
[o
+1] & 0x07; /* index of DRCS link */
3406 unsigned char obj
[3*4*4]; /* types* objects * (triplet,packet,subp,high) */
3407 unsigned char type
,ct
, tstart
= 4*4;
3408 memset(obj
,0,sizeof(obj
));
3410 if (p
[o
] & 0x08) /* GPOP data used */
3412 if (!m_txtCache
->gpop
|| !(p
[18*40] & 0x08)) /* no p27 data or higher prio of MOT link */
3414 m_txtCache
->gpop
= ((p
[18*40] << 8) | (p
[18*40+1] << 4) | p
[18*40+2]) & 0x7ff;
3415 if ((m_txtCache
->gpop
& 0xff) == 0xff)
3416 m_txtCache
->gpop
= 0;
3419 if (m_txtCache
->gpop
< 0x100)
3420 m_txtCache
->gpop
+= 0x800;
3427 type
= (p
[18*40+5] >> 2*ct
) & 0x03;
3429 if (type
== 0) continue;
3430 obj
[(type
-1)*(tstart
)+ct
*4 ] = 3 * ((p
[18*40+7+ct
*2] >> 1) & 0x03) + type
; //triplet
3431 obj
[(type
-1)*(tstart
)+ct
*4+1] = ((p
[18*40+7+ct
*2] & 0x08) >> 3) + 1 ; //packet
3432 obj
[(type
-1)*(tstart
)+ct
*4+2] = p
[18*40+6+ct
*2] & 0x0f ; //subp
3433 obj
[(type
-1)*(tstart
)+ct
*4+3] = p
[18*40+7+ct
*2] & 0x01 ; //high
3439 if (opop
) /* POP data used */
3441 opop
= 18*40 + 10*opop
; /* offset to POP link */
3442 if (!m_txtCache
->pop
|| !(p
[opop
] & 0x08)) /* no p27 data or higher prio of MOT link */
3444 m_txtCache
->pop
= ((p
[opop
] << 8) | (p
[opop
+1] << 4) | p
[opop
+2]) & 0x7ff;
3445 if ((m_txtCache
->pop
& 0xff) == 0xff)
3446 m_txtCache
->pop
= 0;
3449 if (m_txtCache
->pop
< 0x100)
3450 m_txtCache
->pop
+= 0x800;
3457 type
= (p
[opop
+5] >> 2*ct
) & 0x03;
3459 if (type
== 0) continue;
3460 obj
[(type
-1)*(tstart
)+(ct
+2)*4 ] = 3 * ((p
[opop
+7+ct
*2] >> 1) & 0x03) + type
; //triplet
3461 obj
[(type
-1)*(tstart
)+(ct
+2)*4+1] = ((p
[opop
+7+ct
*2] & 0x08) >> 3) + 1 ; //packet
3462 obj
[(type
-1)*(tstart
)+(ct
+2)*4+2] = p
[opop
+6+ct
*2] ; //subp
3463 obj
[(type
-1)*(tstart
)+(ct
+2)*4+3] = p
[opop
+7+ct
*2] & 0x01 ; //high
3469 // eval default objects in correct order
3470 for (int i
= 0; i
< 12; i
++)
3474 APx0
= APy0
= APx
= APy
= m_txtCache
->tAPx
= m_txtCache
->tAPy
= 0;
3475 Eval_NumberedObject(i
% 4 > 1 ? m_txtCache
->pop
: m_txtCache
->gpop
, obj
[i
*4+2], obj
[i
*4+1], obj
[i
*4], obj
[i
*4+3], &APx
, &APy
, &APx0
, &APy0
, PageChar
, PageAtrb
);
3479 if (p
[o
+1] & 0x08) /* GDRCS data used */
3481 if (!m_txtCache
->gdrcs
|| !(p
[20*40] & 0x08)) /* no p27 data or higher prio of MOT link */
3483 m_txtCache
->gdrcs
= ((p
[20*40] << 8) | (p
[20*40+1] << 4) | p
[20*40+2]) & 0x7ff;
3484 if ((m_txtCache
->gdrcs
& 0xff) == 0xff)
3485 m_txtCache
->gdrcs
= 0;
3486 else if (m_txtCache
->gdrcs
< 0x100)
3487 m_txtCache
->gdrcs
+= 0x800;
3490 if (odrcs
) /* DRCS data used */
3492 odrcs
= 20*40 + 4*odrcs
; /* offset to DRCS link */
3493 if (!m_txtCache
->drcs
|| !(p
[odrcs
] & 0x08)) /* no p27 data or higher prio of MOT link */
3495 m_txtCache
->drcs
= ((p
[odrcs
] << 8) | (p
[odrcs
+1] << 4) | p
[odrcs
+2]) & 0x7ff;
3496 if ((m_txtCache
->drcs
& 0xff) == 0xff)
3497 m_txtCache
->drcs
= 0;
3498 else if (m_txtCache
->drcs
< 0x100)
3499 m_txtCache
->drcs
+= 0x800;
3502 if (m_txtCache
->astCachetable
[m_txtCache
->gpop
][0])
3503 m_txtCache
->astCachetable
[m_txtCache
->gpop
][0]->pageinfo
.function
= FUNC_GPOP
;
3504 if (m_txtCache
->astCachetable
[m_txtCache
->pop
][0])
3505 m_txtCache
->astCachetable
[m_txtCache
->pop
][0]->pageinfo
.function
= FUNC_POP
;
3506 if (m_txtCache
->astCachetable
[m_txtCache
->gdrcs
][0])
3507 m_txtCache
->astCachetable
[m_txtCache
->gdrcs
][0]->pageinfo
.function
= FUNC_GDRCS
;
3508 if (m_txtCache
->astCachetable
[m_txtCache
->drcs
][0])
3509 m_txtCache
->astCachetable
[m_txtCache
->drcs
][0]->pageinfo
.function
= FUNC_DRCS
;
3512 /* evaluate local extension data from p26 */
3515 APx0
= APy0
= APx
= APy
= m_txtCache
->tAPx
= m_txtCache
->tAPy
= 0;
3516 Eval_Object(13 * (23-2 + 2), m_txtCache
->astCachetable
[m_txtCache
->Page
][m_txtCache
->SubPage
], &APx
, &APy
, &APx0
, &APy0
, OBJ_ACTIVE
, &PageChar
[40], PageChar
, PageAtrb
); /* 1st triplet p26/0 */
3521 for (unsigned char row
: m_txtCache
->FullRowColor
)
3523 for (int c
= 0; c
< 40; c
++)
3525 if (BlackBgSubst
&& PageAtrb
[o
].bg
== TXT_ColorBlack
&& !(PageAtrb
[o
].IgnoreAtBlackBgSubst
))
3528 PageAtrb
[o
].bg
= m_txtCache
->FullScrColor
;
3530 PageAtrb
[o
].bg
= row
;
3539 for (int i
= 0; i
< 25*40; i
++)
3541 if (PageAtrb
[i
].concealed
) PageAtrb
[i
].fg
= PageAtrb
[i
].bg
;
3544 } /* is_dec(page) */
3547 /* dump interpreted object data to stdout */
3548 /* in: 18 bit object data */
3549 /* out: termination info, >0 if end of object */
3550 void CTeletextDecoder::Eval_Object(int iONr
, TextCachedPage_t
*pstCachedPage
,
3551 unsigned char *pAPx
, unsigned char *pAPy
,
3552 unsigned char *pAPx0
, unsigned char *pAPy0
,
3553 tObjType ObjType
, unsigned char* pagedata
, unsigned char* PageChar
, TextPageAttr_t
* PageAtrb
)
3556 int iONr1
= iONr
+ 1; /* don't terminate after first triplet */
3557 unsigned char drcssubp
=0, gdrcssubp
=0;
3558 signed char endcol
= -1; /* last column to which to extend attribute changes */
3559 TextPageAttr_t attrPassive
= { TXT_ColorWhite
, TXT_ColorBlack
, C_G0P
, 0, 0, 1 ,0, 0, 0, 0, 0, 0, 0, 0x3f}; /* current attribute for passive objects */
3563 iOData
= iTripletNumber2Data(iONr
, pstCachedPage
, pagedata
); /* get triplet data, next triplet */
3564 if (iOData
< 0) /* invalid number, not cached, or hamming error: terminate */
3569 if (ObjType
== OBJ_ACTIVE
)
3573 else if (ObjType
== OBJ_ADAPTIVE
) /* search end of line */
3575 for (int i
= iONr
; i
<= 506; i
++)
3577 int iTempOData
= iTripletNumber2Data(i
, pstCachedPage
, pagedata
); /* get triplet data, next triplet */
3578 int iAddress
= (iTempOData
) & 0x3f;
3579 int iMode
= (iTempOData
>> 6) & 0x1f;
3580 //int iData = (iTempOData >> 11) & 0x7f;
3581 if (iTempOData
< 0 || /* invalid number, not cached, or hamming error: terminate */
3582 (iAddress
>= 40 /* new row: row address and */
3583 && (iMode
== 0x01 || /* Full Row Color or */
3584 iMode
== 0x04 || /* Set Active Position */
3585 (iMode
>= 0x15 && iMode
<= 0x17) || /* Object Definition */
3586 iMode
== 0x17))) /* Object Termination */
3588 if (iAddress
< 40 && iMode
!= 0x06)
3595 while (0 == Eval_Triplet(iOData
, pstCachedPage
, pAPx
, pAPy
, pAPx0
, pAPy0
, &drcssubp
, &gdrcssubp
, &endcol
, &attrPassive
, pagedata
, PageChar
, PageAtrb
) || iONr1
== iONr
); /* repeat until termination reached */
3598 void CTeletextDecoder::Eval_NumberedObject(int p
, int s
, int packet
, int triplet
, int high
,
3599 unsigned char *pAPx
, unsigned char *pAPy
,
3600 unsigned char *pAPx0
, unsigned char *pAPy0
, unsigned char* PageChar
, TextPageAttr_t
* PageAtrb
)
3602 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
3604 if (!packet
|| 0 == m_txtCache
->astCachetable
[p
][s
])
3607 unsigned char pagedata
[23*40];
3608 auto& components
= CServiceBroker::GetAppComponents();
3609 const auto appPlayer
= components
.GetComponent
<CApplicationPlayer
>();
3610 appPlayer
->LoadPage(p
, s
, pagedata
);
3612 int idata
= CDVDTeletextTools::deh24(pagedata
+ 40*(packet
-1) + 1 + 3*triplet
);
3615 if (idata
< 0) /* hamming error: ignore triplet */
3618 iONr
= idata
>> 9; /* triplet number of odd object data */
3620 iONr
= idata
& 0x1ff; /* triplet number of even object data */
3623 Eval_Object(iONr
, m_txtCache
->astCachetable
[p
][s
], pAPx
, pAPy
, pAPx0
, pAPy0
, (tObjType
)(triplet
% 3),pagedata
, PageChar
, PageAtrb
);
3627 int CTeletextDecoder::Eval_Triplet(int iOData
, TextCachedPage_t
*pstCachedPage
,
3628 unsigned char *pAPx
, unsigned char *pAPy
,
3629 unsigned char *pAPx0
, unsigned char *pAPy0
,
3630 unsigned char *drcssubp
, unsigned char *gdrcssubp
,
3631 signed char *endcol
, TextPageAttr_t
*attrPassive
, unsigned char* pagedata
, unsigned char* PageChar
, TextPageAttr_t
* PageAtrb
)
3633 int iAddress
= (iOData
) & 0x3f;
3634 int iMode
= (iOData
>> 6) & 0x1f;
3635 int iData
= (iOData
>> 11) & 0x7f;
3637 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
3639 if (iAddress
< 40) /* column addresses */
3641 int offset
; /* offset to PageChar and PageAtrb */
3644 *pAPx
= iAddress
; /* new Active Column */
3645 offset
= (*pAPy0
+ *pAPy
) * 40 + *pAPx0
+ *pAPx
; /* offset to PageChar and PageAtrb */
3650 if (0 == (iData
>>5))
3652 int newcolor
= iData
& 0x1f;
3653 if (*endcol
< 0) /* passive object */
3654 attrPassive
->fg
= newcolor
;
3655 else if (*endcol
== 40) /* active object */
3657 TextPageAttr_t
*p
= &PageAtrb
[offset
];
3658 int oldcolor
= (p
)->fg
; /* current color (set-after) */
3659 int c
= *pAPx0
+ *pAPx
; /* current column absolute */
3665 } while (c
< 40 && p
->fg
== oldcolor
); /* stop at change by level 1 page */
3667 else /* adaptive object */
3669 TextPageAttr_t
*p
= &PageAtrb
[offset
];
3670 int c
= *pAPx
; /* current column relative to object origin */
3676 } while (c
<= *endcol
);
3683 PageChar
[offset
] = iData
;
3684 if (*endcol
< 0) /* passive object */
3686 attrPassive
->charset
= C_G1C
; /* FIXME: separated? */
3687 PageAtrb
[offset
] = *attrPassive
;
3689 else if (PageAtrb
[offset
].charset
!= C_G1S
)
3690 PageAtrb
[offset
].charset
= C_G1C
; /* FIXME: separated? */
3695 PageChar
[offset
] = iData
;
3696 if (*endcol
< 0) /* passive object */
3698 attrPassive
->charset
= C_G3
;
3699 PageAtrb
[offset
] = *attrPassive
;
3702 PageAtrb
[offset
].charset
= C_G3
;
3705 if (0 == (iData
>>5))
3707 int newcolor
= iData
& 0x1f;
3708 if (*endcol
< 0) /* passive object */
3709 attrPassive
->bg
= newcolor
;
3710 else if (*endcol
== 40) /* active object */
3712 TextPageAttr_t
*p
= &PageAtrb
[offset
];
3713 int oldcolor
= (p
)->bg
; /* current color (set-after) */
3714 int c
= *pAPx0
+ *pAPx
; /* current column absolute */
3718 if (newcolor
== TXT_ColorBlack
)
3719 p
->IgnoreAtBlackBgSubst
= 1;
3722 } while (c
< 40 && p
->bg
== oldcolor
); /* stop at change by level 1 page */
3724 else /* adaptive object */
3726 TextPageAttr_t
*p
= &PageAtrb
[offset
];
3727 int c
= *pAPx
; /* current column relative to object origin */
3731 if (newcolor
== TXT_ColorBlack
)
3732 p
->IgnoreAtBlackBgSubst
= 1;
3735 } while (c
<= *endcol
);
3743 if ((iData
& 0x60) != 0) break; // reserved data field
3744 if (*endcol
< 0) /* passive object */
3746 attrPassive
->flashing
=iData
& 0x1f;
3747 PageAtrb
[offset
] = *attrPassive
;
3750 PageAtrb
[offset
].flashing
=iData
& 0x1f;
3753 if (*endcol
< 0) /* passive object */
3755 attrPassive
->setG0G2
=iData
& 0x3f;
3756 PageAtrb
[offset
] = *attrPassive
;
3759 PageAtrb
[offset
].setG0G2
=iData
& 0x3f;
3762 PageChar
[offset
] = iData
;
3763 if (*endcol
< 0) /* passive object */
3765 attrPassive
->charset
= C_G0P
; /* FIXME: secondary? */
3766 attrPassive
->setX26
= 1;
3767 PageAtrb
[offset
] = *attrPassive
;
3771 PageAtrb
[offset
].charset
= C_G0P
; /* FIXME: secondary? */
3772 PageAtrb
[offset
].setX26
= 1;
3775 // case 0x0b: (see 0x02)
3778 int conc
= (iData
& 0x04);
3779 int inv
= (iData
& 0x10);
3780 int dw
= (iData
& 0x40 ?1:0);
3781 int dh
= (iData
& 0x01 ?1:0);
3782 int sep
= (iData
& 0x20);
3783 int bw
= (iData
& 0x02 ?1:0);
3784 if (*endcol
< 0) /* passive object */
3788 attrPassive
->concealed
= 1;
3789 attrPassive
->fg
= attrPassive
->bg
;
3791 attrPassive
->inverted
= (inv
? 1- attrPassive
->inverted
: 0);
3792 attrPassive
->doubleh
= dh
;
3793 attrPassive
->doublew
= dw
;
3794 attrPassive
->boxwin
= bw
;
3795 if (bw
) attrPassive
->IgnoreAtBlackBgSubst
= 0;
3798 if (attrPassive
->charset
== C_G1C
)
3799 attrPassive
->charset
= C_G1S
;
3801 attrPassive
->underline
= 1;
3805 if (attrPassive
->charset
== C_G1S
)
3806 attrPassive
->charset
= C_G1C
;
3808 attrPassive
->underline
= 0;
3814 int c
= *pAPx0
+ (*endcol
== 40 ? *pAPx
: 0); /* current column */
3816 TextPageAttr_t
*p
= &PageAtrb
[offset
];
3819 p
->inverted
= (inv
? 1- p
->inverted
: 0);
3827 if (p
->charset
== C_G1C
)
3834 if (p
->charset
== C_G1S
)
3842 if (bw
) p
->IgnoreAtBlackBgSubst
= 0;
3846 } while (c
< *endcol
);
3851 PageChar
[offset
] = iData
& 0x3f;
3852 if (*endcol
< 0) /* passive object */
3854 attrPassive
->charset
= C_OFFSET_DRCS
+ ((iData
& 0x40) ? (0x10 + *drcssubp
) : *gdrcssubp
);
3855 PageAtrb
[offset
] = *attrPassive
;
3858 PageAtrb
[offset
].charset
= C_OFFSET_DRCS
+ ((iData
& 0x40) ? (0x10 + *drcssubp
) : *gdrcssubp
);
3861 PageChar
[offset
] = iData
;
3862 if (*endcol
< 0) /* passive object */
3864 attrPassive
->charset
= C_G2
;
3865 PageAtrb
[offset
] = *attrPassive
;
3868 PageAtrb
[offset
].charset
= C_G2
;
3871 if (iMode
== 0x10 && iData
== 0x2a)
3875 PageChar
[offset
] = iData
;
3876 if (*endcol
< 0) /* passive object */
3878 attrPassive
->charset
= C_G0P
;
3879 attrPassive
->diacrit
= iMode
& 0x0f;
3880 attrPassive
->setX26
= 1;
3881 PageAtrb
[offset
] = *attrPassive
;
3885 PageAtrb
[offset
].charset
= C_G0P
;
3886 PageAtrb
[offset
].diacrit
= iMode
& 0x0f;
3887 PageAtrb
[offset
].setX26
= 1;
3890 break; /* unsupported or not yet implemented mode: ignore */
3891 } /* switch (iMode) */
3893 else /* ================= (iAddress >= 40): row addresses ====================== */
3898 if (0 == (iData
>>5))
3900 m_txtCache
->FullScrColor
= iData
& 0x1f;
3904 if (*endcol
== 40) /* active object */
3906 *pAPy
= RowAddress2Row(iAddress
); /* new Active Row */
3908 int color
= iData
& 0x1f;
3909 int row
= *pAPy0
+ *pAPy
;
3912 if (row
<= 24 && 0 == (iData
>>5))
3914 else if (3 == (iData
>>5))
3918 for (; row
<= maxrow
; row
++)
3919 m_txtCache
->FullRowColor
[row
] = color
;
3924 *pAPy
= RowAddress2Row(iAddress
); /* new Active Row */
3926 *pAPx
= iData
; /* new Active Column */
3927 *endcol
= -1; /* FIXME: check if row changed? */
3930 if (iAddress
== 0x3f)
3932 *pAPx
= *pAPy
= 0; /* new Active Position 0,0 */
3933 if (*endcol
== 40) /* active object */
3935 int color
= iData
& 0x1f;
3936 int row
= *pAPy0
; // + *pAPy;
3939 if (row
<= 24 && 0 == (iData
>>5))
3941 else if (3 == (iData
>>5))
3945 for (; row
<= maxrow
; row
++)
3946 m_txtCache
->FullRowColor
[row
] = color
;
3962 m_txtCache
->tAPy
= iAddress
- 40;
3963 m_txtCache
->tAPx
= iData
;
3968 if (iAddress
& 0x10) /* POP or GPOP */
3970 unsigned char APx
= 0, APy
= 0;
3971 unsigned char APx0
= *pAPx0
+ *pAPx
+ m_txtCache
->tAPx
, APy0
= *pAPy0
+ *pAPy
+ m_txtCache
->tAPy
;
3972 int triplet
= 3 * ((iData
>> 5) & 0x03) + (iMode
& 0x03);
3973 int packet
= (iAddress
& 0x03) + 1;
3974 int subp
= iData
& 0x0f;
3975 int high
= (iData
>> 4) & 0x01;
3978 if (APx0
< 40) /* not in side panel */
3980 Eval_NumberedObject((iAddress
& 0x08) ? m_txtCache
->gpop
: m_txtCache
->pop
, subp
, packet
, triplet
, high
, &APx
, &APy
, &APx0
, &APy0
, PageChar
,PageAtrb
);
3983 else if (iAddress
& 0x08) /* local: eval invoked object */
3985 unsigned char APx
= 0, APy
= 0;
3986 unsigned char APx0
= *pAPx0
+ *pAPx
+ m_txtCache
->tAPx
, APy0
= *pAPy0
+ *pAPy
+ m_txtCache
->tAPy
;
3987 int descode
= ((iAddress
& 0x01) << 3) | (iData
>> 4);
3988 int triplet
= iData
& 0x0f;
3990 if (APx0
< 40) /* not in side panel */
3992 Eval_Object(13 * 23 + 13 * descode
+ triplet
, pstCachedPage
, &APx
, &APy
, &APx0
, &APy0
, (tObjType
)(triplet
% 3), pagedata
, PageChar
, PageAtrb
);
3999 if (0 == (iAddress
& 0x08)) /* Object Definition illegal or only level 3.5 */
4002 m_txtCache
->tAPx
= m_txtCache
->tAPy
= 0;
4004 return 0xFF; /* termination by object definition */
4007 if (0 == (iData
& 0x10)) /* DRCS Mode reserved or only level 3.5 */
4011 *drcssubp
= iData
& 0x0f;
4013 *gdrcssubp
= iData
& 0x0f;
4016 m_txtCache
->tAPx
= m_txtCache
->tAPy
= 0;
4018 return 0x80 | iData
; /* explicit termination */
4021 break; /* unsupported or not yet implemented mode: ignore */
4022 } /* switch (iMode) */
4023 } /* (iAddress >= 40): row addresses */
4025 if (iAddress
< 40 || iMode
!= 0x10) /* leave temp. AP-Offset unchanged only immediately after definition */
4026 m_txtCache
->tAPx
= m_txtCache
->tAPy
= 0;
4028 return 0; /* normal exit, no termination */
4031 /* get object data */
4032 /* in: absolute triplet number (0..506, start at packet 3 byte 1) */
4033 /* in: pointer to cache struct of page data */
4034 /* out: 18 bit triplet data, <0 if invalid number, not cached, or hamming error */
4035 int CTeletextDecoder::iTripletNumber2Data(int iONr
, TextCachedPage_t
*pstCachedPage
, unsigned char* pagedata
)
4037 if (iONr
> 506 || 0 == pstCachedPage
)
4041 int packet
= (iONr
/ 13) + 3;
4042 int packetoffset
= 3 * (iONr
% 13);
4045 p
= pagedata
+ 40*(packet
-1) + packetoffset
+ 1;
4046 else if (packet
<= 25)
4048 if (0 == pstCachedPage
->pageinfo
.p24
)
4050 p
= pstCachedPage
->pageinfo
.p24
+ 40*(packet
-24) + packetoffset
+ 1;
4054 int descode
= packet
- 26;
4055 if (0 == pstCachedPage
->pageinfo
.ext
)
4057 if (0 == pstCachedPage
->pageinfo
.ext
->p26
[descode
])
4059 p
= pstCachedPage
->pageinfo
.ext
->p26
[descode
] + packetoffset
; /* first byte (=designation code) is not cached */
4061 return CDVDTeletextTools::deh24(p
);
4064 int CTeletextDecoder::SetNational(unsigned char sec
)
4066 std::unique_lock
<CCriticalSection
> lock(m_txtCache
->m_critSection
);
4071 return NAT_PL
; //polish
4074 return NAT_TR
; //turkish
4076 return NAT_SR
; //serbian, croatian, slovenian
4078 return NAT_SC
; // serbian, croatian
4080 return NAT_RB
; // russian, bulgarian
4082 return NAT_UA
; // ukrainian
4084 return NAT_ET
; // estonian
4086 return NAT_LV
; // latvian, lithuanian
4088 return NAT_GR
; // greek
4090 return NAT_HB
; // hebrew
4093 return NAT_AR
; // arabic
4095 return CountryConversionTable
[sec
& 0x07];
4098 int CTeletextDecoder::NextHex(int i
) /* return next existing non-decimal page number */
4101 if (startpage
< 0x100)
4111 } while ((m_txtCache
->SubPageTable
[i
] == 0xFF) || IsDec(i
));
4115 void CTeletextDecoder::SetColors(const unsigned short *pcolormap
, int offset
, int number
)
4117 int j
= offset
; /* index in global color table */
4119 for (int i
= 0; i
< number
; i
++)
4121 int r
= ((pcolormap
[i
] >> 8) & 0xf) << 4;
4122 int g
= ((pcolormap
[i
] >> 4) & 0xf) << 4;
4123 int b
= ((pcolormap
[i
]) & 0xf) << 4;
4125 if (m_RenderInfo
.rd0
[j
] != r
)
4127 m_RenderInfo
.rd0
[j
] = r
;
4129 if (m_RenderInfo
.gn0
[j
] != g
)
4131 m_RenderInfo
.gn0
[j
] = g
;
4133 if (m_RenderInfo
.bl0
[j
] != b
)
4135 m_RenderInfo
.bl0
[j
] = b
;
4141 UTILS::COLOR::Color
CTeletextDecoder::GetColorRGB(enumTeletextColor ttc
)
4145 case TXT_ColorBlack
: return 0xFF000000;
4146 case TXT_ColorRed
: return 0xFFFC1414;
4147 case TXT_ColorGreen
: return 0xFF24FC24;
4148 case TXT_ColorYellow
: return 0xFFFCC024;
4149 case TXT_ColorBlue
: return 0xFF0000FC;
4150 case TXT_ColorMagenta
: return 0xFFB000FC;
4151 case TXT_ColorCyan
: return 0xFF00FCFC;
4152 case TXT_ColorWhite
: return 0xFFFCFCFC;
4153 case TXT_ColorTransp
: return 0x00000000;
4157 /* Get colors for CLUTs 2+3 */
4158 int index
= (int)ttc
;
4159 UTILS::COLOR::Color color
= (m_RenderInfo
.tr0
[index
] << 24) | (m_RenderInfo
.bl0
[index
] << 16) |
4160 (m_RenderInfo
.gn0
[index
] << 8) | m_RenderInfo
.rd0
[index
];