libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
cea708windowstate.h
Go to the documentation of this file.
1
8#pragma once
9
10
11#include <promeki/config.h>
12#if PROMEKI_ENABLE_PROAV
13#include <cstdint>
14#include <promeki/array.h>
15#include <promeki/buffer.h>
17#include <promeki/color.h>
19#include <promeki/list.h>
20#include <promeki/namespace.h>
21#include <promeki/string.h>
22#include <promeki/subtitle.h>
23
24PROMEKI_NAMESPACE_BEGIN
25
38struct Cea708PenAttr {
39 bool italic = false;
40 bool underline = false;
41 SubtitleEdgeStyle edgeStyle = SubtitleEdgeStyle::None;
42 SubtitleFontFace fontFace = SubtitleFontFace::Default;
49 SubtitlePenSize penSize = SubtitlePenSize::Standard;
54 SubtitlePenOffset penOffset = SubtitlePenOffset::Normal;
62 SubtitleTextTag textTag = SubtitleTextTag::Dialog;
63 Color foregroundColor;
64 Color backgroundColor;
65 Color edgeColor;
66 SubtitleOpacity foregroundOpacity = SubtitleOpacity::Solid;
67 SubtitleOpacity backgroundOpacity = SubtitleOpacity::Solid;
68 SubtitleOpacity edgeOpacity = SubtitleOpacity::Solid;
69
73 bool hasAnyStyle() const {
74 return italic || underline
75 || edgeStyle != SubtitleEdgeStyle::None
76 || fontFace != SubtitleFontFace::Default
77 || penSize != SubtitlePenSize::Standard
78 || penOffset != SubtitlePenOffset::Normal
79 || textTag != SubtitleTextTag::Dialog
80 || foregroundColor.isValid() || backgroundColor.isValid()
81 || edgeColor.isValid()
82 || foregroundOpacity != SubtitleOpacity::Solid
83 || backgroundOpacity != SubtitleOpacity::Solid
84 || edgeOpacity != SubtitleOpacity::Solid;
85 }
86
87 bool operator==(const Cea708PenAttr &o) const {
88 return italic == o.italic && underline == o.underline
89 && edgeStyle.value() == o.edgeStyle.value()
90 && fontFace.value() == o.fontFace.value()
91 && penSize.value() == o.penSize.value()
92 && penOffset.value() == o.penOffset.value()
93 && textTag.value() == o.textTag.value()
94 && foregroundColor == o.foregroundColor
95 && backgroundColor == o.backgroundColor
96 && edgeColor == o.edgeColor
97 && foregroundOpacity.value() == o.foregroundOpacity.value()
98 && backgroundOpacity.value() == o.backgroundOpacity.value()
99 && edgeOpacity.value() == o.edgeOpacity.value();
100 }
101 bool operator!=(const Cea708PenAttr &o) const { return !(*this == o); }
102};
103
130struct Cea708WindowAttr {
133 Color fillColor;
134 SubtitleOpacity fillOpacity = SubtitleOpacity::Solid;
135
138 Color borderColor;
142 uint8_t borderType = 0;
143
145 uint8_t justify = 0;
147 uint8_t printDirection = 0;
149 uint8_t scrollDirection = 3; // BtT — caption convention
151 bool wordWrap = false;
153 uint8_t displayEffect = 0;
155 uint8_t effectDirection = 0;
157 uint8_t effectSpeed = 0;
158
163 bool hasAnyAttribute() const {
164 return fillColor.isValid()
165 || fillOpacity != SubtitleOpacity::Solid
166 || borderColor.isValid()
167 || borderType != 0
168 || justify != 0
169 || printDirection != 0
170 || scrollDirection != 3
171 || wordWrap
172 || displayEffect != 0
173 || effectDirection != 0
174 || effectSpeed != 0;
175 }
176
177 bool operator==(const Cea708WindowAttr &o) const {
178 return fillColor == o.fillColor
179 && fillOpacity.value() == o.fillOpacity.value()
180 && borderColor == o.borderColor && borderType == o.borderType
181 && justify == o.justify && printDirection == o.printDirection
182 && scrollDirection == o.scrollDirection && wordWrap == o.wordWrap
183 && displayEffect == o.displayEffect && effectDirection == o.effectDirection
184 && effectSpeed == o.effectSpeed;
185 }
186 bool operator!=(const Cea708WindowAttr &o) const { return !(*this == o); }
187};
188
198struct Cea708Cell {
199 uint32_t codepoint = 0;
200 Cea708PenAttr pen;
201
202 bool operator==(const Cea708Cell &o) const {
203 return codepoint == o.codepoint && pen == o.pen;
204 }
205 bool operator!=(const Cea708Cell &o) const { return !(*this == o); }
206};
207
239struct Cea708Window {
242 static constexpr int MaxRows = 15;
245 static constexpr int MaxCols = 42;
246
247 bool visible = false;
248 bool defined = false;
249 int priority = 0;
250 int anchorPoint = 0;
251 int anchorV = 0;
252 int anchorH = 0;
253 bool relativePos = true;
254 int rowCount = 15;
255 int colCount = 32;
269 bool rowLock = true;
274 bool colLock = true;
275 int penRow = 0;
276 int penCol = 0;
284 uint8_t lastWindowStyleId = 0;
287 uint8_t lastPenStyleId = 0;
288
294 Cea708WindowAttr attrs;
295
311 Cea708PenAttr pen;
312
318 List<List<Cea708Cell>> grid;
319
322 void resize(int rows, int cols);
323
326 void clearGrid();
327
334 void putChar(uint32_t cp, const Cea708PenAttr &pen);
335
342 void putChar(uint32_t cp) { putChar(cp, Cea708PenAttr{}); }
343
346 void carriageReturn();
347
353 String text() const;
354
362 SubtitleSpan::List visibleSpans() const;
363
365 bool isEmpty() const;
366
367 bool operator==(const Cea708Window &o) const;
368 bool operator!=(const Cea708Window &o) const { return !(*this == o); }
369};
370
438class Cea708WindowState {
439 public:
441 static constexpr int WindowCount = 8;
442
462 enum class DisplayAspect {
463 WideScreen,
464 Standard,
465 };
466
467 Cea708WindowState();
468
473 void reset();
474
477 int currentWindowId() const { return _currentWindow; }
480 void setCurrentWindowId(int id) {
481 _currentWindow = (id < 0) ? 0 : (id > 7) ? 7 : id;
482 }
483
485 const Cea708Window &window(int id) const { return _windows[clampId(id)]; }
486
488 Cea708Window &window(int id) { return _windows[clampId(id)]; }
489
492 const Cea708Window &currentWindow() const { return _windows[_currentWindow]; }
493 Cea708Window &currentWindow() { return _windows[_currentWindow]; }
494
497 DisplayAspect displayAspect() const { return _displayAspect; }
498
506 void setDisplayAspect(DisplayAspect a) { _displayAspect = a; }
507
519 const Cea708PenAttr &currentPen() const { return _windows[_currentWindow].pen; }
520 Cea708PenAttr &currentPen() { return _windows[_currentWindow].pen; }
521
524 bool anyVisible() const;
525
531 String visibleText() const;
532
540 SubtitleSpan::List visibleSpans() const;
541
546 void processServiceBytes(const Cea708Service &svc);
547
555 void processBytes(const void *data, size_t size);
556
557 private:
559 using WindowArray = Array<Cea708Window, WindowCount>;
560
561 WindowArray _windows;
562 int _currentWindow = 0;
563 DisplayAspect _displayAspect = DisplayAspect::WideScreen;
564
575 uint32_t _pendingHighSurrogate = 0;
576
577 static int clampId(int id) {
578 if (id < 0) return 0;
579 if (id > 7) return 7;
580 return id;
581 }
582};
583
584PROMEKI_NAMESPACE_END
585
586#endif // PROMEKI_ENABLE_PROAV