00001
00002
00003
00004 #include <cassert>
00005 #include <algorithm>
00006 using namespace std;
00007
00008 #include "cc708window.h"
00009 #include "mythcontext.h"
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 const uint k708JustifyLeft = 0;
00057 const uint k708JustifyRight = 1;
00058 const uint k708JustifyCenter = 2;
00059 const uint k708JustifyFull = 3;
00060
00061 const uint k708EffectSnap = 0;
00062 const uint k708EffectFade = 1;
00063 const uint k708EffectWipe = 2;
00064
00065 const uint k708BorderNone = 0;
00066 const uint k708BorderRaised = 1;
00067 const uint k708BorderDepressed = 2;
00068 const uint k708BorderUniform = 3;
00069 const uint k708BorderShadowLeft = 4;
00070 const uint k708BorderShadowRight = 5;
00071
00072 const uint k708DirLeftToRight = 0;
00073 const uint k708DirRightToLeft = 1;
00074 const uint k708DirTopToBottom = 2;
00075 const uint k708DirBottomToTop = 3;
00076
00077 const uint k708AttrSizeSmall = 0;
00078 const uint k708AttrSizeStandard = 1;
00079 const uint k708AttrSizeLarge = 2;
00080
00081 const uint k708AttrOffsetSubscript = 0;
00082 const uint k708AttrOffsetNormal = 1;
00083 const uint k708AttrOffsetSuperscript = 2;
00084
00085 const uint k708AttrFontDefault = 1;
00086 const uint k708AttrFontMonospacedSerif = 1;
00087 const uint k708AttrFontProportionalSerif = 2;
00088 const uint k708AttrFontMonospacedSansSerif = 3;
00089 const uint k708AttrFontProportionalSansSerif = 4;
00090 const uint k708AttrFontCasual = 5;
00091 const uint k708AttrFontCursive = 6;
00092 const uint k708AttrFontSmallCaps = 7;
00093
00094 const uint k708AttrColorBlack = 0;
00095 const uint k708AttrColorWhite = 63;
00096
00097 const uint k708AttrOpacitySolid = 0;
00098 const uint k708AttrOpacityFlash = 1;
00099 const uint k708AttrOpacityTranslucent = 2;
00100 const uint k708AttrOpacityTransparent = 3;
00101
00102 CC708Window::CC708Window()
00103 : priority(0), visible(0),
00104 anchor_point(0),
00105 anchor_vertical(0), anchor_horizontal(0),
00106 row_count(0), column_count(0),
00107 row_lock(0), column_lock(0),
00108 pen_style(0), window_style(0),
00109
00110 fill_color(0), fill_opacity(0),
00111 border_color(0), border_type(0),
00112 scroll_dir(0), print_dir(0),
00113 effect_dir(0), display_effect(0),
00114 effect_speed(0),
00115 justify(0), word_wrap(0),
00116
00117 true_row_count(0), true_column_count(0),
00118 text(NULL), exists(false),
00119 lock(true)
00120 {
00121 }
00122
00123 void CC708Window::DefineWindow(int _priority, int _visible,
00124 int _anchor_point, int _relative_pos,
00125 int _anchor_vertical, int _anchor_horizontal,
00126 int _row_count, int _column_count,
00127 int _row_lock, int _column_lock,
00128 int _pen_style, int _window_style)
00129 {
00130 QMutexLocker locker(&lock);
00131
00132 _row_count++;
00133 _column_count++;
00134
00135 priority = _priority;
00136 visible = _visible;
00137 anchor_point = _anchor_point;
00138 relative_pos = _relative_pos;
00139 anchor_vertical = _anchor_vertical;
00140 anchor_horizontal = _anchor_horizontal;
00141 row_count = _row_count;
00142 column_count = _column_count;
00143 row_lock = _row_lock;
00144 column_lock = _column_lock;
00145
00146 if ((!_pen_style && !exists) || _pen_style)
00147 pen.SetPenStyle(_pen_style ? _pen_style : 1);
00148
00149 if ((!_window_style && !exists) || _window_style)
00150 SetWindowStyle(_window_style ? _window_style : 1);
00151
00152 uint old_row = true_row_count;
00153 uint old_col = true_column_count;
00154
00155 true_row_count = (row_lock) ? row_count : max(row_count + 1, (uint)2);
00156 true_column_count = column_count;
00157
00158 if (text && (!exists || (old_row != true_row_count) ||
00159 (old_col != true_column_count)))
00160 {
00161 delete [] text;
00162 text = NULL;
00163 }
00164
00165 if (!text)
00166 {
00167 uint num = true_row_count * true_column_count;
00168 text = new CC708Character[num];
00169 pen.column = 0;
00170 pen.row = 0;
00171 for (uint i = 0; i < num; i++)
00172 text[i].attr = pen.attr;
00173 }
00174
00175 exists = true;
00176 }
00177
00178
00179 CC708Window::~CC708Window()
00180 {
00181 QMutexLocker locker(&lock);
00182
00183 exists = false;
00184 true_row_count = 0;
00185 true_column_count = 0;
00186
00187 if (text)
00188 {
00189 delete [] text;
00190 text = NULL;
00191 }
00192 }
00193
00194 void CC708Window::Clear(void)
00195 {
00196 QMutexLocker locker(&lock);
00197
00198 if (!exists || !text)
00199 return;
00200
00201 for (uint i = 0; i < true_row_count * true_column_count; i++)
00202 {
00203 text[i].character = QChar(' ');
00204 text[i].attr = pen.attr;
00205 }
00206 }
00207
00208 CC708Character &CC708Window::GetCCChar(void) const
00209 {
00210 QMutexLocker locker(&lock);
00211 assert(exists);
00212 assert(text);
00213 assert(pen.row < true_row_count);
00214 assert(pen.column < true_column_count);
00215 return text[pen.row * true_column_count + pen.column];
00216 }
00217
00218 vector<CC708String*> CC708Window::GetStrings(void) const
00219 {
00220 QMutexLocker locker(&lock);
00221
00222 vector<CC708String*> list;
00223
00224 CC708String *cur = NULL;
00225
00226 for (uint j = 0; j < true_row_count; j++)
00227 {
00228 for (uint i = 0; i < true_column_count; i++)
00229 {
00230 CC708Character &chr = text[j * true_column_count + i];
00231 if (!cur)
00232 {
00233 cur = new CC708String;
00234 cur->x = i;
00235 cur->y = j;
00236 cur->str = QString("%1").arg(chr.character);
00237 cur->attr = chr.attr;
00238 }
00239 else if (cur->attr == chr.attr)
00240 {
00241 cur->str = QString("%1%2").arg(cur->str).arg(chr.character);
00242 }
00243 else
00244 {
00245 list.push_back(cur);
00246 cur = NULL;
00247 i--;
00248 }
00249 }
00250 if (cur)
00251 {
00252 list.push_back(cur);
00253 cur = NULL;
00254 }
00255 }
00256 return list;
00257 }
00258
00259 void CC708Window::SetWindowStyle(uint style)
00260 {
00261 const uint style2justify[] =
00262 {
00263 k708JustifyLeft, k708JustifyLeft, k708JustifyLeft, k708JustifyCenter,
00264 k708JustifyLeft, k708JustifyLeft, k708JustifyCenter, k708JustifyLeft,
00265 };
00266
00267 if ((style < 1) || (style > 7))
00268 return;
00269
00270 fill_color = k708AttrColorBlack;
00271 fill_opacity = ((2 == style) || (5 == style)) ?
00272 k708AttrOpacityTransparent : k708AttrOpacitySolid;
00273 border_color = k708AttrColorBlack;
00274 border_type = k708BorderNone;
00275 scroll_dir = (style < 7) ? k708DirBottomToTop : k708DirRightToLeft;
00276 print_dir = (style < 7) ? k708DirLeftToRight : k708DirTopToBottom;
00277 effect_dir = scroll_dir;
00278 display_effect = k708EffectSnap;
00279 effect_speed = 0;
00280 justify = style2justify[style];
00281 word_wrap = (style > 3) && (style < 7) ? 1 : 0;
00282 }
00283
00284 void CC708Window::AddChar(QChar ch)
00285 {
00286 if (!exists)
00287 return;
00288
00289 QString dbg_char = ch;
00290 if ((int)ch < 32)
00291 dbg_char = QString("0x%1").arg((int)ch, 0,16);
00292
00293 if (!IsPenValid())
00294 {
00295 VERBOSE(VB_VBI,
00296 QString("AddChar(%1) at (c %2, r %3) INVALID win(%4,%5)")
00297 .arg(dbg_char).arg(pen.column).arg(pen.row)
00298 .arg(true_column_count).arg(true_row_count));
00299 return;
00300 }
00301
00302 if ((int)ch == 0x0D)
00303 {
00304 Scroll(pen.row + 1, 0);
00305 return;
00306 }
00307
00308 GetCCChar().attr = pen.attr;
00309 GetCCChar().character = ch;
00310 int c = pen.column;
00311 int r = pen.row;
00312 IncrPenLocation();
00313
00314 VERBOSE(VB_VBI, QString("AddChar(%1) at (c %2, r %3) -> (%4,%5)")
00315 .arg(dbg_char).arg(c).arg(r).arg(pen.column).arg(pen.row));
00316 }
00317
00318 void CC708Window::Scroll(int row, int col)
00319 {
00320 QMutexLocker locker(&lock);
00321
00322 if (!true_row_count || !true_column_count)
00323 return;
00324
00325 if ((k708DirBottomToTop == scroll_dir) &&
00326 (row >= (int)true_row_count))
00327 {
00328 for (uint j = 0; j < true_row_count - 1; j++)
00329 for (uint i = 0; i < true_column_count; i++)
00330 text[(true_column_count * j) + i] =
00331 text[(true_column_count * (j+1)) + i];
00332
00333
00334
00335 CC708Character tmp(*this);
00336 for (uint i = 0; i < true_column_count; i++)
00337 text[(true_column_count * (true_row_count - 1)) + i] = tmp;
00338
00339 pen.row = true_row_count - 1;
00340 }
00341 else
00342 {
00343 pen.row = row;
00344 }
00345
00346
00347 pen.column = col;
00348 }
00349
00350 void CC708Window::IncrPenLocation(void)
00351 {
00352
00353
00354 int new_column = pen.column, new_row = pen.row;
00355
00356 new_column += (print_dir == k708DirLeftToRight) ? +1 : 0;
00357 new_column += (print_dir == k708DirRightToLeft) ? -1 : 0;
00358 new_row += (print_dir == k708DirTopToBottom) ? +1 : 0;
00359 new_row += (print_dir == k708DirBottomToTop) ? -1 : 0;
00360
00361 #if 0
00362 VERBOSE(VB_VBI, QString("IncrPen dir%1: (c %2, r %3) -> (%4,%5)")
00363 .arg(print_dir).arg(pen.column).arg(pen.row)
00364 .arg(new_column).arg(new_row));
00365 #endif
00366
00367 if (k708DirLeftToRight == print_dir || k708DirRightToLeft == print_dir)
00368 {
00369
00370 if (new_column >= (int)true_column_count)
00371 {
00372 new_column = 0;
00373 new_row += 1;
00374 }
00375 else if (new_column < 0)
00376 {
00377 new_column = (int)true_column_count - 1;
00378 new_row -= 1;
00379 }
00380 Scroll(new_row, new_column);
00381 }
00382 else
00383 {
00384 pen.column = max(new_column, 0);
00385 pen.row = max(new_row, 0);
00386 }
00387
00388
00389 LimitPenLocation();
00390 }
00391
00392 void CC708Window::SetPenLocation(uint row, uint column)
00393 {
00394 Scroll(row, column);
00395 LimitPenLocation();
00396 }
00397
00398 void CC708Window::LimitPenLocation(void)
00399 {
00400
00401 uint max_col = max((int)true_column_count - 1, 0);
00402 uint max_row = max((int)true_row_count - 1, 0);
00403 pen.column = min(pen.column, max_col);
00404 pen.row = min(pen.row, max_row);
00405 }
00406
00407
00408
00409 void CC708Pen::SetPenStyle(uint style)
00410 {
00411 static const uint style2font[] = { 1, 1, 2, 3, 4, 5, 4, 5 };
00412
00413 if ((style < 1) || (style > 7))
00414 return;
00415
00416 attr.pen_size = k708AttrSizeStandard;
00417 attr.offset = k708AttrOffsetNormal;
00418 attr.font_tag = style2font[style];
00419 attr.italics = 0;
00420 attr.underline = 0;
00421 attr.edge_type = 0;
00422 attr.fg_color = k708AttrColorWhite;
00423 attr.fg_opacity = k708AttrOpacitySolid;
00424 attr.bg_color = k708AttrColorBlack;
00425 attr.bg_opacity = (style<6) ?
00426 k708AttrOpacitySolid : k708AttrOpacityTransparent;
00427 attr.edge_color = k708AttrColorBlack;
00428 }
00429
00430 CC708Character::CC708Character(const CC708Window &win)
00431 {
00432 attr = win.pen.attr;
00433 character = ' ';
00434 }
00435
00436 bool CC708CharacterAttribute::operator==(
00437 const CC708CharacterAttribute &other) const
00438 {
00439 return ((pen_size == other.pen_size) &&
00440 (offset == other.offset) &&
00441 (text_tag == other.text_tag) &&
00442 (font_tag == other.font_tag) &&
00443 (edge_type == other.edge_type) &&
00444 (underline == other.underline) &&
00445 (italics == other.italics) &&
00446 (fg_color == other.fg_color) &&
00447 (fg_opacity == other.fg_opacity) &&
00448 (bg_color == other.bg_color) &&
00449 (bg_opacity == other.bg_opacity) &&
00450 (edge_color == other.edge_color));
00451 }
00452
00453 QColor CC708CharacterAttribute::ConvertToQColor(uint c)
00454 {
00455
00456 return QColor((c & 0x30) << 2, (c & 0x0c) << 4, (c & 0x3) << 6);
00457 }