#include "DST_WinManager.h" #include "DST_CC_Setup.h" #include "DST_CCTask.h" #include "DST_HostInterface.h" #include "DST_FontEngine.h" extern DS_U16 DMW_KSX2UniSub(DS_U8 high, DS_U8 low); #define COLOR_TRANSPARENT 0 #if 0 ____CC_708_Font_Size_Decide__() #endif static int debug_cc = 0; extern "C" void DST_708Debug(bool bOn) { debug_cc = bOn ? 1 : 0; } #define MAX_708_ROW 15 #define MAX_708_COL 52 // korean 708 cc static int DST_708_FontSize[3] = {0,0,0}; // 0 = small, 1 = standard, 2 = large int DST_708_GetFontSize(int n) // 0 = min, 1 = std, 2 = max { if (DST_708_FontSize[0] == 0) { DST_708_FontSize[0] = DST_DecideFontSize(13); // ũ ̿ 15 ׸ Samll DST_708_FontSize[1] = DST_DecideFontSize(12); // ũ ̿ 12 ׸ Standard DST_708_FontSize[2] = DST_DecideFontSize(11); // ũ ̿ 9 ׸ Large DST_Printf("708 Font Size = %d %d %d\n", DST_708_FontSize[0], DST_708_FontSize[1], DST_708_FontSize[2]); } return DST_708_FontSize[n]; } #if 0 ____CC_708_Region_Process___() #endif static DST_RECT rect = { 0,0,0,0}; static void DST_UpdateRegionReset() { memset(&rect, 0, sizeof(DST_RECT)); } static void DST_UpdateRegionAdd(DST_RECT rectNew) { if (rectNew.w == 0 || rectNew.h == 0) return; // ڽ ũⰡ 0̸ ڽ ũ üѴ. if (rect.w == 0 || rect.h == 0) { rect = rectNew; return; } DST_RECT rectTemp = rect; #ifndef min #define min(a,b) ((a)>(b)?(b):(a)) #endif #ifndef max #define max(a,b) ((a)>(b)?(a):(b)) #endif rect.x = min(rectTemp.x, rectNew.x ); rect.y = min(rectTemp.y, rectNew.y ); rect.w = max(rectTemp.x + rectTemp.w, rectNew.x + rectNew.w) - rect.x; rect.h = max(rectTemp.y + rectTemp.h, rectNew.y + rectNew.h) - rect.y; if (rect.x < 0) rect.x = 0; if (rect.y < 0) rect.y = 0; int nScreenHeight = DST_GetCCScreenHeight(); int nScreenWidth = DST_GetCCScreenWidth(); if (rect.w > nScreenWidth - rect.x) rect.w = nScreenWidth - rect.x; if (rect.h > nScreenHeight - rect.y) rect.h = nScreenHeight - rect.y; } static DST_RECT DST_UpdateRegionGet() { return rect; } #if 0 ____CC_708_Queue____() #endif #define QUEUE_LENGTH 2048 class CCCircularQueue { private: int head; int tail; int nLength; unsigned char buffer[QUEUE_LENGTH]; public: CCCircularQueue() { Reset(); } void Reset() { head = 0; tail = 0; nLength = 0; } int GetSize() { return nLength; } int GetFreeSize() { return QUEUE_LENGTH - GetSize(); } bool Add(unsigned char *Buff, int nSize) { if (GetFreeSize() < nSize) return false; while (nSize--) Add(*(Buff++)); return true; } bool Add(unsigned char ucBuff) { if (GetFreeSize() < 1) return false; buffer[head] = ucBuff; head = (head == QUEUE_LENGTH-1) ? 0 : head + 1; nLength++; return true; } unsigned char GetByte() { if (GetSize() < 1) return 0; return buffer[tail]; } unsigned char GetNextByte() { if (GetSize() < 2) return 0; switch (tail) { case QUEUE_LENGTH - 1: return buffer [0]; } return buffer[tail+1]; } unsigned char GetNextNextByte() { if (GetSize() < 3) return 0; switch (tail) { case QUEUE_LENGTH - 2: return buffer [0]; case QUEUE_LENGTH - 1: return buffer [1]; } return buffer[tail+2]; } bool Get(unsigned char *data, int nSize) { if (GetSize() < nSize) return false; for (int i = 0; i < nSize; i++) { data[i] = GetByte(); RemoveByte(); } return true; } void RemoveByte() { if (GetSize() < 1) return; tail = (tail == QUEUE_LENGTH-1) ? 0 : tail+1; nLength--; } }; #if 0 ____CC_708_Window____() #endif struct DST_708_Color { DS_U8 red; DS_U8 green; DS_U8 blue; }; struct DST_708_Window { // Define Window DS_U8 priority; // 0 ~ 7 DS_U8 anchor_point; // 0 ~8 DS_U8 relative_positioning; // 0 ~ 1 DS_U8 anchor_vertical; DS_U8 anchor_horizontal; DS_U8 row_count; DS_U8 column_count; DS_U8 row_lock; DS_U8 column_lock; DS_U8 visible; DS_U8 window_styleID; DS_U8 pen_styleID; // Set Window Attributes DS_U8 justify; DS_U8 print_direction; DS_U8 scroll_direction; DS_U8 wordwrap; DS_U8 display_effect; DS_U8 effect_direction; DS_U8 effect_speed; DST_708_Color fill_color; DS_U8 fill_opacity; DS_U8 border_type; DST_708_Color border_color; }; struct DST_708_Pen { // Set Pen Attributes DS_U8 pen_size; DS_U8 font_style; DS_U8 text_tag; DS_U8 offset; DS_U8 italics; DS_U8 underline; DS_U8 edge_type; // Set Pen Color DST_708_Color fg_color; DS_U8 fg_opacity; DST_708_Color bg_color; DS_U8 bg_opacity; DST_708_Color edge_color; }; struct DST_708_Char { DS_U16 nCode; DST_708_Pen pen; }; class CC708Window { private: DST_708_Window window_data; DST_708_Pen pen_data; DST_708_Char strText[MAX_708_COL][MAX_708_ROW]; // ۿ bool bDefined; int pos_x; // Ŀ ġ int pos_y; DST_RECT rect; OSD_PIXEL_T *imgBuff; bool bNeedDraw; bool bKorean; bool bWideScreen; DS_U8 nID; int nLineWidth[MAX_708_ROW]; int nLineHeight[MAX_708_ROW]; bool bHide; // HDW DSW TGW ɿ ؼ ° ȴ. // true Ǹ ڿ ̻ ޾Ƶ ʴ´. public: void SetID(DS_U8 id) { nID = id; } void SetKorean(bool bVal) { bKorean = bVal; } bool GetNeedRedraw() { return bNeedDraw; } void SetNeedRedraw(bool bValue) { bNeedDraw = bValue; } bool GetVisible() { return window_data.visible == 0 ? false : true; } int GetPriority() { return window_data.priority; } OSD_PIXEL_T *GetImgBuff() { return imgBuff; } DST_RECT GetSize() { return rect; } CC708Window(bool bKorea, bool bWide) { imgBuff = 0; for (int i = 0; i < MAX_708_ROW; i++) { nLineWidth[i] = 0; nLineHeight[i] = 0; } Initialize(); bKorean = bKorea; bWideScreen = bWide; } void Initialize() { bHide = false; memset(&window_data, 0, sizeof(DST_708_Window)); memset(&pen_data, 0, sizeof(DST_708_Pen)); memset(&rect, 0, sizeof(DST_RECT)); ClearWindow(); if (imgBuff) DST_OS_Free(&imgBuff); imgBuff = 0; for (int i = 0; i < MAX_708_ROW; i++) { nLineWidth[i] = 0; nLineHeight[i] = 0; } bDefined = false; bNeedDraw = false; } virtual ~CC708Window() { if (imgBuff) DST_OS_Free(&imgBuff); imgBuff = 0; for (int i = 0; i < MAX_708_ROW; i++) { nLineWidth[i] = 0; nLineHeight[i] = 0; } } void DefineWindow(DS_U8 priority, DS_U8 anchor_point, DS_U8 relative_positioning, DS_U8 anchor_vertical, DS_U8 anchor_horizontal, DS_U8 row_count, DS_U8 column_count, DS_U8 row_lock, DS_U8 column_lock, DS_U8 visible, DS_U8 window_styleID, DS_U8 pen_styleID ) { if (debug_cc) { DST_Printf("Define Window[%d]", nID); DST_Printf(" p(%d)", priority); DST_Printf(" a(%d)", anchor_point); DST_Printf(" r(%d)", relative_positioning); DST_Printf(" v(%d)", anchor_vertical); DST_Printf(" h(%d)", anchor_horizontal); DST_Printf(" row(%d)", row_count); DST_Printf(" col(%d)", column_count); DST_Printf(" rl(%d)", row_lock); DST_Printf(" cl(%d)", column_lock); DST_Printf(" v(%d)", visible); DST_Printf(" s(%d)", window_styleID); DST_Printf(" pen(%d)", pen_styleID); DST_Printf("\n"); } // 608 4 ŸϷ row_count 2 δ. // football.trp if (bKorean == false && window_data.window_styleID == 4) { if (row_count > 0) row_count--; } // 4-Line Roll-Up 608 // 2 ŸϷ 鼭 row_count 2,3,4 µ 1,2,3 ; ´ ̴. // DTVCC1080 v1.1_8-08-01.trp 2 50 // SPL ׹° ٷ ڿ ٹٲ ´. // c41miscc 10.2ä Ʒ ƾ Ҽ if (bKorean == false && window_data.window_styleID == 2 && column_count == 32) { if (row_count == 2) row_count = 1; if (row_count == 3) row_count = 2; if (row_count == 4) row_count = 3; } if ( bDefined == true && window_data.priority == priority && window_data.anchor_point == anchor_point && window_data.relative_positioning == relative_positioning && window_data.anchor_vertical == anchor_vertical && window_data.anchor_horizontal == anchor_horizontal && window_data.row_count == row_count && window_data.column_count == column_count && window_data.row_lock == row_lock && window_data.column_lock == column_lock && window_data.visible == visible && window_data.window_styleID == window_styleID && window_data.pen_styleID == pen_styleID ) { if (debug_cc) DST_Printf("Same Define Window. Ignore\n"); return; } // PBS_CCD row_count پ if (window_data.row_count > row_count) { for (int i = 0; i < window_data.row_count - row_count; i++) { ScrollUp(); if (pos_y > 0) pos_y--; } } window_data.priority = priority; window_data.anchor_point = anchor_point; window_data.relative_positioning = relative_positioning; window_data.anchor_vertical = anchor_vertical; window_data.anchor_horizontal = anchor_horizontal; window_data.row_count = row_count; window_data.column_count = column_count; window_data.row_lock = row_lock; window_data.column_lock = column_lock; window_data.visible = visible; window_data.window_styleID = window_styleID; window_data.pen_styleID = pen_styleID; // Ÿ 1~7 ̶ Ѵ. // 0̶ ÿ . if (window_data.window_styleID == 0) { if (bDefined == false) SetPredefinedWindowStyleID(1); } else { SetPredefinedWindowStyleID(window_data.window_styleID); } // Ÿ 1~7 ̶ Ѵ. // 0̶ ÿ . if (window_data.pen_styleID == 0) { if (bDefined == false) SetPredefinedPenStyleID(1); } else { SetPredefinedPenStyleID(window_data.pen_styleID); } bDefined = true; bNeedDraw = true; } // ̹ ǵ Ÿ Ѵ. void SetPredefinedPenStyleID(unsigned char StyleID) { pen_data.pen_size = 1; pen_data.font_style = 0; pen_data.text_tag = 0; pen_data.offset = 1; pen_data.italics = 0; pen_data.underline = 0; pen_data.edge_type = 0; // Set Pen Color pen_data.fg_color.red = 2; pen_data.fg_color.green = 2; pen_data.fg_color.blue = 2; pen_data.fg_opacity = 0; pen_data.bg_color.red = 0; pen_data.bg_color.green = 0; pen_data.bg_color.blue = 0; pen_data.bg_opacity = 0; pen_data.edge_color.red = 0; pen_data.edge_color.green = 0; pen_data.edge_color.blue = 0; switch (StyleID) { case 2: pen_data.font_style = 1; break; case 3: pen_data.font_style = 2; break; case 4: pen_data.font_style = 3; break; case 5: pen_data.font_style = 4; break; case 6: pen_data.font_style = 3; pen_data.edge_type = 3; pen_data.bg_opacity = 3; break; case 7: pen_data.font_style = 4; pen_data.edge_type = 3; pen_data.bg_opacity = 3; break; } } // ̹ ǵ ŸϷ ä. void SetPredefinedWindowStyleID(unsigned char StyleID) { window_data.justify = 0; window_data.print_direction = 0; window_data.scroll_direction = 3; window_data.wordwrap = 1; window_data.display_effect = 0; window_data.effect_direction = 0; window_data.effect_speed = 0; window_data.fill_color.red = 0; window_data.fill_color.green = 0; window_data.fill_color.blue = 0; window_data.fill_opacity = 0; window_data.border_type = 0; window_data.border_color.red = 0; window_data.border_color.green = 0; window_data.border_color.blue = 0; switch (StyleID) { case 2: window_data.fill_opacity = 3; break; case 3: window_data.justify = 2; break; case 4: window_data.wordwrap = 0; break; case 5: window_data.wordwrap = 0; window_data.fill_opacity = 3; break; case 6: window_data.wordwrap = 0; window_data.justify = 2; break; case 7: window_data.print_direction = 2; window_data.scroll_direction = 1; break; } } void ClearWindow() { memset(&strText, 0, sizeof(DST_708_Char) * MAX_708_ROW * MAX_708_COL); pos_x = 0; pos_y = 0; bNeedDraw = true; } void DeleteWindow() { if (bDefined == false) return; UpdateScreen(); // ʱȭϸ visible Ӽ Ƿ ̸ Ʈ Ѵ. Initialize(); } void DisplayWindow() { if (bDefined == false) return; window_data.visible = true; bNeedDraw = true; bHide = false; UpdateScreen(); } void HideWindow() { if (bDefined == false) return; window_data.visible = false; bNeedDraw = true; bHide = true; UpdateScreen(); } void ToggleWindow() { if (bDefined == false) return; window_data.visible = !window_data.visible; //bHide = !bHide; bNeedDraw = true; UpdateScreen(); } void SetWindowAttribute(DS_U8 justify, DS_U8 print_direction, DS_U8 scroll_direction, DS_U8 wordwrap, DS_U8 display_effect, DS_U8 effect_direction, DS_U8 effect_speed, DS_U8 fill_color_red, //DST_708_Color fill_color, DS_U8 fill_color_green, DS_U8 fill_color_blue, DS_U8 fill_opacity, DS_U8 border_type, DS_U8 border_color_red, //DST_708_Color border_color DS_U8 border_color_green, DS_U8 border_color_blue) { if (bDefined == false) return; window_data.justify = justify; window_data.print_direction = print_direction; window_data.scroll_direction = scroll_direction; window_data.wordwrap = wordwrap; window_data.display_effect = display_effect; window_data.effect_direction = effect_direction; window_data.effect_speed = effect_speed; window_data.fill_color.red = fill_color_red; window_data.fill_color.green = fill_color_green; window_data.fill_color.blue = fill_color_blue; window_data.fill_opacity = fill_opacity; window_data.border_type = border_type; window_data.border_color.red = border_color_red; window_data.border_color.green = border_color_green; window_data.border_color.blue = border_color_blue; bNeedDraw = true; if (debug_cc) { DST_Printf("SetWindowAttribute[%d]", nID); DST_Printf(" j(%d)", justify); DST_Printf(" p(%d)", print_direction); DST_Printf(" s(%d)", scroll_direction); DST_Printf(" w(%d)", wordwrap); DST_Printf(" e(%d)", display_effect); DST_Printf(" ed(%d)", effect_direction); DST_Printf(" es(%d)", effect_speed); DST_Printf(" fill(%d,%d,%d)", fill_color_red, fill_color_green, fill_color_blue); DST_Printf(" o(%d)", fill_opacity); DST_Printf(" b(%d)", border_type); DST_Printf(" border(%d,%d,%d)", border_color_red, border_color_green, border_color_blue); DST_Printf("\n"); } } void SetPenAttribute( unsigned char pen_size, unsigned char font_style, unsigned char text_tag, unsigned char offset, unsigned char italics, unsigned char underline, unsigned char edge_type) { if (bDefined == false) return; pen_data.pen_size = pen_size; pen_data.font_style = font_style; pen_data.text_tag = text_tag; // pen_data.offset = offset; 2013.02.20 YTN OFFSET ʵ pen_data.italics = italics; pen_data.underline = underline; pen_data.edge_type = edge_type; if (debug_cc) { DST_Printf("SetPenAttribute[%d]", nID); DST_Printf(" size(%d)", pen_size); DST_Printf(" style(%d)", font_style); DST_Printf(" tt(%d)", text_tag); DST_Printf(" o(%d)", offset); DST_Printf(" i(%d)", italics); DST_Printf(" u(%d)", underline); DST_Printf(" b(%d)", edge_type); DST_Printf("\n"); } } void SetPenColor( unsigned char fg_color_red, DS_U8 fg_color_green, DS_U8 fg_color_blue, DS_U8 fg_opacity, DS_U8 bg_color_red, DS_U8 bg_color_green, DS_U8 bg_color_blue, DS_U8 bg_opacity, DS_U8 edge_color_red, DS_U8 edge_color_green, unsigned char edge_color_blue) { if (bDefined == false) return; // Set Pen Color pen_data.fg_color.red = fg_color_red; pen_data.fg_color.green = fg_color_green; pen_data.fg_color.blue = fg_color_blue; pen_data.fg_opacity = fg_opacity; pen_data.bg_color.red = bg_color_red; pen_data.bg_color.green = bg_color_green; pen_data.bg_color.blue = bg_color_blue; pen_data.bg_opacity = bg_opacity; pen_data.edge_color.red = edge_color_red; pen_data.edge_color.green = edge_color_green; pen_data.edge_color.blue = edge_color_blue; if (debug_cc) { DST_Printf("SetPenColor[%d]", nID); DST_Printf(" fg_color(%d,%d,%d)", fg_color_red, fg_color_green, fg_color_blue); DST_Printf(" fg_o(%d)", fg_opacity); DST_Printf(" bg_color(%d,%d,%d)", bg_color_red, bg_color_green, bg_color_blue); DST_Printf(" bg_opacity(%d)", bg_opacity); DST_Printf(" edge_color(%d,%d,%d)", edge_color_red, edge_color_green, edge_color_blue); DST_Printf("\n"); } } void SetPenLocation(unsigned char x,DS_U8 y) { if (bDefined == false) return; if (x > window_data.column_count) return; if (y > window_data.row_count) return; // 608 708 űٰ ߻ϴ Ѵ. // Ÿ 2 CR ʰ SPL ݺؼ PBS_CCD // kcsm43.trp pos_y = y; // x ġ Ѵ. // if (window_data.justify != 0) return; // ѱ CC ó ó ʿ if (bKorean == true) { int nLineLength = GetStingLength(pos_y); int nCount = 0; for (int i = 0; i < nLineLength; i++) { nCount = IsFullCharater(strText[i][pos_y].nCode) ? nCount+2 : nCount+1; if (nCount < x) continue; // ȿ ġϴ ġ ִ pos_x = i; return; } pos_x = nLineLength + x - nCount; } else { if (window_data.justify == 0) { pos_x = x; } else { for (int x = 0; x < MAX_708_COL; x++) strText[x][pos_y].nCode = 0; // . pos_x = 0; } } } void Reset() { window_data.visible = false; if (bDefined == false) return; DeleteWindow(); } // 1-Line Scroll Up void ScrollUp() { for (int y = 0; y < MAX_708_ROW - 1; y++) for (int x = 0; x < MAX_708_COL; x++) strText[x][y] = strText[x][y+1]; for (int x = 0; x < MAX_708_COL; x++) memset(&strText[x][MAX_708_ROW-1], 0, sizeof(DST_708_Char)); } // Multi-Line Scroll Up void ScrollUp(int nLines) { for (int i = 0; i < nLines; i++) ScrollUp(); } // 1-Line Scroll Down void ScrollDown() { for (int y = 0; y < MAX_708_ROW - 1; y++) for (int x = 0; x < MAX_708_COL; x++) strText[x][y+1] = strText[x][y]; for (int x = 0; x < MAX_708_COL; x++) memset(&strText[x][0], 0, sizeof(DST_708_Char)); } // Multi-Line Scroll Down void ScrollDown(int nLines) { for (int i = 0; i < nLines; i++) ScrollDown(); } // ѱ ڶ true return Ѵ. bool IsFullCharater(DS_U16 nCode) // ڵ ڵ̴. { if (0x1100 <= nCode && nCode < 0x1200) return true; // ѱ ڸ if (0x2113 <= nCode && nCode < 0x2127) return true; // Tel, TM if (0x2E80 <= nCode && nCode < 0xA500) return true; // 󰡳, Ÿī if (0xAC00 <= nCode && nCode < 0xD800) return true; // ѱ if (0xF900 <= nCode && nCode < 0xFB00) return true; // CJK compatibility ideographs if (0xFE30 <= nCode && nCode < 0xFE50) return true; // CJK compatibility forms return false; } void AddChar(DS_U16 data) { // if (bHide == true) return; // C16S6Pkc 10.3 #if 0 // 080703_dfa_buick_csd if (window_data.scroll_direction == 2) { AddCharTopToBottom(data); // Ʒ ũ ٿ } else #endif { AddCharBottomToTop(data); // Ʒ ũ } } // Bottom to Top void AddCharBottomToTop(DS_U16 data) { int nOverLines = GetStringLines() - window_data.row_count - 1; if (nOverLines > 0) ScrollUp(nOverLines); if (data == 0x08) // Back Space { if (pos_x == 0) return; strText[pos_x][pos_y].nCode = 0; pos_x--; bNeedDraw = true; return; } if (data == 0x0C) // FF ó ġ ư. { ClearWindow(); // c67gseta 10.3ä ȭ ó ư. return; } if (data == 0x0E) // HCR ش ó ġ ư. { for (int x = 0; x < MAX_708_COL; x++) memset(&strText[x][pos_y], 0, sizeof(DST_708_Char)); pos_x = 0; bNeedDraw = true; return; } if (data == 0x0D) // { // 608 WindowStyle 5 CR ٹٲ // PBS CCD.trp if ( /*window_data.window_styleID == 4 || */ (bKorean == false && window_data.window_styleID == 5 && pos_y != 0) || pos_y >= window_data.row_count || pos_y >= MAX_708_ROW-1) { ScrollUp(); // bNeedDraw = true; } else { pos_y++; } pos_x = 0; return; } // ڿ Column Count ū ٷ . if (bKorean == true) { int nLineLength = GetStingLength(pos_y); int nCount = 0; for (int i = 0; i < nLineLength; i++) { nCount = IsFullCharater(strText[i][pos_y].nCode) ? nCount+2 : nCount+1; } if (nCount >= window_data.column_count + 1 || nCount >= MAX_708_COL) { pos_y++; pos_x = 0; } } else { if (pos_x > window_data.column_count + 1 || pos_x >= MAX_708_COL) { pos_y++; pos_x = 0; } } // ڿ Row Count ū ũ Ѵ. if (pos_y >= window_data.row_count + 1 || pos_y >= MAX_708_ROW) { ScrollUp(); // pos_y--; } strText[pos_x][pos_y].nCode = data; strText[pos_x][pos_y].pen = pen_data; pos_x++; bNeedDraw = true; //DST_Printf("%d %d %d\n", pos_x, pos_y, data); } // Top to Bottom void AddCharTopToBottom(DS_U16 data) { int nOverLines = GetStringLines() - window_data.row_count - 1; if (nOverLines > 0) ScrollDown(nOverLines); if (data == 0x08) // Back Space { if (pos_x == 0) return; strText[pos_x][pos_y].nCode = 0; pos_x--; bNeedDraw = true; return; } if (data == 0x0C) // FF ó ġ ư. { ClearWindow(); // c67gseta 10.3ä ȭ ó ư. return; } if (data == 0x0E) // HCR ش ó ġ ư. { for (int x = 0; x < MAX_708_COL; x++) memset(&strText[x][pos_y], 0, sizeof(DST_708_Char)); pos_x = 0; bNeedDraw = true; return; } if (data == 0x0D) // { ScrollDown(); // bNeedDraw = true; pos_y = 0; pos_x = 0; return; } // ڿ Column Count ū ٷ . if (bKorean == true) { int nLineLength = GetStingLength(pos_y); int nCount = 0; for (int i = 0; i < nLineLength; i++) { nCount = IsFullCharater(strText[i][pos_y].nCode) ? nCount+2 : nCount+1; } if (nCount >= window_data.column_count + 1 || nCount >= MAX_708_COL) { ScrollDown(); // pos_y = 0; pos_x = 0; } } else { if (pos_x >= window_data.column_count || pos_x >= MAX_708_COL-1) { ScrollDown(); // pos_y = 0; pos_x = 0; } } strText[pos_x][pos_y].nCode = data; strText[pos_x][pos_y].pen = pen_data; pos_x++; bNeedDraw = true; } // ARGB 8Ʈ ȯ unsigned char ARGB(unsigned char alpha,DS_U8 red,DS_U8 green,DS_U8 blue) { if (alpha == 0 || alpha > 2) return 0; return (alpha & 0x03) * 64 + (red & 0x03) * 16 + (green & 0x03) * 4 + (blue & 0x03); } // 8Ʈ ȯ unsigned char S_RGB(DST_708_Color color) { return ARGB(2, color.red, color.green, color.blue); } // 8Ʈ ȯ unsigned char T_RGB(DST_708_Color color) { return ARGB(1, color.red, color.green, color.blue); } // Border Size ȯѴ. int GetBorderSize() { return DST_GetCCScreenHeight() / 200; } OSD_PIXEL_T ColorConvert(DS_U8 c) { DS_U32 color = 0; switch (c & 0xC0) { case 0x40: // color = 0x7F000000 + (c & 0x30) * 348160 + (c & 0x0C) * 5440 + (c & 0x03) * 85; break; case 0x80: // color = 0xFF000000 + (c & 0x30) * 348160 + (c & 0x0C) * 5440 + (c & 0x03) * 85;; break; } return CONV32_16(color); } DS_U8 GetBackGroundColor(bool bFlash) { if (window_data.fill_opacity == 3) return COLOR_TRANSPARENT; if (bFlash && window_data.fill_opacity == 1) return COLOR_TRANSPARENT; if (window_data.fill_opacity == 2) return T_RGB(window_data.fill_color); return S_RGB(window_data.fill_color); } void DrawBackGround(bool bFlash) { if (imgBuff == 0) return; OSD_PIXEL_T color = ColorConvert(GetBackGroundColor(bFlash)); int nSize = rect.w * rect.h; if (color == 0) { memset(imgBuff, 0, nSize * sizeof(OSD_PIXEL_T)); } else { OSD_PIXEL_T* buff = imgBuff; while (nSize--) *buff++ = color; } } // ش ٿ ִ int GetStingLength(int nLine) { for (int x = MAX_708_COL - 1; x >= 0; x--) if (strText[x][nLine].nCode != 0) return x+1; return 0; } // Ͱ ִ int GetStringLines() { for (int y = MAX_708_ROW - 1; y >= 0; y--) if (GetStingLength(y) != 0) return y+1; return 0; } void DrawStrings(bool bFlash) { int y_pos = 0; int nLines = GetStringLines(); int nOldHeight = GetCharHeight(); for (int y = 0; y < nLines; y++) { int x_pos = 0; OSD_PIXEL_T *LineBuff = GetLineImage(y, &nLineWidth[y], &nLineHeight[y], bFlash); switch (window_data.justify) { case 1: x_pos = rect.w - nLineWidth[y]; break; // right justify case 2: x_pos = (rect.w - nLineWidth[y])/2; break;// center justify } DrawImage(x_pos, y_pos, nLineWidth[y], nLineHeight[y], LineBuff); DST_OS_Free(&LineBuff); if (nLineHeight[y] == 0) nLineHeight[y] = nOldHeight; y_pos+=nLineHeight[y]; nLineWidth[y] = 0; nLineHeight[y] = 0; } } void DrawImage(int x_pos, int y_pos, int w, int h, OSD_PIXEL_T *buff) { if (imgBuff == 0) return; if (x_pos + w > rect.w) // ȭ鿡 ׷ ̹ ȭ麸 ū ޺κ . { int ww = rect.w - x_pos; if (ww <= 0) return; for (int y = 0; y < h; y++) { for (int x = 0; x < ww; x++) buff[y*ww+x] = buff[y*w+x]; } DrawImage(x_pos, y_pos, ww, h, buff); return; } OSD_PIXEL_T *src = buff; OSD_PIXEL_T *des = imgBuff + y_pos * rect.w + x_pos; int des_delta = rect.w - w; int y = h; while (y--) { int x = w; while (x--) { if (*src != 0) *des = *src; src++; des++; } des += des_delta; } } int GetCharHeight() { int nFontSize = DST_708_GetFontSize(1); // Default, Medium switch (DST_CC_GetSize()) { case 1: nFontSize = DST_708_GetFontSize(0); break;// Small case 3: nFontSize = DST_708_GetFontSize(2); break;// Large } return DST_GetFontHeight(nFontSize); } int GetCharWidth() { if (bKorean) { return GetCharHeight() * 45 / 100; // 40% ⺻ Ѵ. } return GetCharHeight() * 45 / 100; // 40% ⺻ Ѵ. } // CC Ʈ  Ʈ Ʈ ٲ۴. unsigned char ConvertFontSize(unsigned char nSize) { return DST_708_GetFontSize((DST_CC_GetSize() == 0) ? nSize : DST_CC_GetSize() - 1); } // CC Ʈ Ÿϸ Ʈ Ʈ Ÿ ٲ۴. unsigned char ConvertFontStyle(unsigned char nStyle) { if (bKorean == true) return 0; // ѱ ׻ ⺻ Ʈ . return (nStyle == 0) ? 4 : nStyle; // ⺻ Ʈ 4.Proportionally without serifs.ttf } // CC Ʈ italic Ʈ italic ٲ۴. bool ConvertFontItalic(unsigned char italics) { switch (DST_CC_GetItalic()) { case 0: return italics == 0 ? false : true;// default case 1: return true; // Italic on } return false; } // CC Ʈ edge style Ʈ edge style ٲ۴. unsigned char ConvertFontEdgeStyle(unsigned char edge_type) { return (DST_CC_GetEdge() == 0) ? edge_type : DST_CC_GetEdge() - 1; } // CC Ʈ Underline Ʈ underline ٲ۴. bool ConvertFontUnderLine(unsigned char underline) { switch (DST_CC_GetUnderline()) { case 0: return underline == 0 ? false : true; // default case 1: return true; // underline on } return false; } // CC Ʈ Offset Ʈ Offset ٲ۴. unsigned char ConvertFontOffset(unsigned char offset) { switch (offset) { case 0: return 1; // Sub Script case 1: return 0; // normal case 2: return 2; // Super Script } return 0; } // CC Font Color Ʈ Font Color ٲ۴. // 0=Auto 1=Solid 2=TransParent 3=translucent 4=flashing // opacity 0 = solid 1=flahing 2= translucent 4 = transparent unsigned char ConvertFontColor(unsigned char opacity, DST_708_Color color, bool bFlash) { switch (DST_CC_GetColor()) { case 1: color.red = 0; color.green = 0; color.blue = 0; break; // black case 2: color.red = 3; color.green = 3; color.blue = 3; break; // white case 3: color.red = 3; color.green = 0; color.blue = 0; break; // red case 4: color.red = 0; color.green = 3; color.blue = 0; break; // green case 5: color.red = 0; color.green = 0; color.blue = 3; break; // blue case 6: color.red = 3; color.green = 3; color.blue = 0; break; // yellow case 7: color.red = 3; color.green = 0; color.blue = 3; break; // magenta case 8: color.red = 0; color.green = 3; color.blue = 3; break; // cyan } switch (DST_CC_GetOpacity()) { case 0: // default switch (opacity) { case 0: return S_RGB(color); // Solid case 1: return (bFlash) ? COLOR_TRANSPARENT : S_RGB(color);// Flash case 2: return T_RGB(color);// TransLucent case 3: return COLOR_TRANSPARENT; } break; case 1: // Solid return S_RGB(color); case 2: // TransParent return COLOR_TRANSPARENT; case 3: // Translucent return T_RGB(color); case 4: // Flashing return (bFlash) ? COLOR_TRANSPARENT : S_RGB(color); } return S_RGB(color); } // CC edge Color Ʈ edge Color ٲ۴. // 0=Auto 1=Solid 2=TransParent 3=translucent 4=flashing // opacity 0 = solid 1=flahing 2= translucent 4 = transparent unsigned char ConvertFontEdgeColor(unsigned char opacity, DST_708_Color color, bool bFlash) { switch (DST_CC_GetEdgeColor()) { case 1: color.red = 0; color.green = 0; color.blue = 0; break; // black case 2: color.red = 3; color.green = 3; color.blue = 3; break; // white case 3: color.red = 3; color.green = 0; color.blue = 0; break; // red case 4: color.red = 0; color.green = 3; color.blue = 0; break; // green case 5: color.red = 0; color.green = 0; color.blue = 3; break; // blue case 6: color.red = 3; color.green = 3; color.blue = 0; break; // yellow case 7: color.red = 3; color.green = 0; color.blue = 3; break; // magenta case 8: color.red = 0; color.green = 3; color.blue = 3; break; // cyan } switch (DST_CC_GetOpacity()) { case 0: // default switch (opacity) { case 0: return S_RGB(color); // Solid case 1: return (bFlash) ? COLOR_TRANSPARENT : S_RGB(color);// Flash case 2: return T_RGB(color);// TransLucent case 3: return COLOR_TRANSPARENT; } break; case 1: // Solid return S_RGB(color); case 2: // TransParent return COLOR_TRANSPARENT; case 3: // Translucent return T_RGB(color); case 4: // Flashing return (bFlash) ? COLOR_TRANSPARENT : S_RGB(color); } return S_RGB(color); } // CC back Color Ʈ back Color ٲ۴. // 0=Auto 1=Solid 2=TransParent 3=translucent 4=flashing // opacity 0 = solid 1=flahing 2= translucent 4 = transparent unsigned char ConvertFontBackColor(unsigned char opacity, DST_708_Color color, bool bFlash) { switch (DST_CC_GetBackColor()) { case 1: color.red = 0; color.green = 0; color.blue = 0; break; // black case 2: color.red = 3; color.green = 3; color.blue = 3; break; // white case 3: color.red = 3; color.green = 0; color.blue = 0; break; // red case 4: color.red = 0; color.green = 3; color.blue = 0; break; // green case 5: color.red = 0; color.green = 0; color.blue = 3; break; // blue case 6: color.red = 3; color.green = 3; color.blue = 0; break; // yellow case 7: color.red = 3; color.green = 0; color.blue = 3; break; // magenta case 8: color.red = 0; color.green = 3; color.blue = 3; break; // cyan } switch (DST_CC_GetBackOpacity()) { case 0: // default switch (opacity) { case 0: return S_RGB(color); // Solid case 1: return (bFlash) ? COLOR_TRANSPARENT : S_RGB(color);// Flash case 2: return T_RGB(color);// TransLucent case 3: return COLOR_TRANSPARENT; } break; case 1: // Solid return S_RGB(color); case 2: // TransParent return COLOR_TRANSPARENT; case 3: // Translucent return T_RGB(color); case 4: // Flashing return (bFlash) ? COLOR_TRANSPARENT : S_RGB(color); } return S_RGB(color); } DS_U8 CalcColor(DS_U8 foreColor, DS_U8 backColor) { switch (foreColor & 0xC0) { case 0x40: // case 0x80: // return foreColor; } return backColor; // } FONT_CC ConvertCCStyleToFontStyle(DST_708_Char cc, bool bFlash) { FONT_CC font; font.nCode = cc.nCode; font.nSize = ConvertFontSize(cc.pen.pen_size); font.nStyle = ConvertFontStyle(cc.pen.font_style); font.bItalic = ConvertFontItalic(cc.pen.italics); font.nEdgeType = ConvertFontEdgeStyle(cc.pen.edge_type); font.bUnderLine = ConvertFontUnderLine(cc.pen.underline); font.nOffset = ConvertFontOffset(cc.pen.offset); DS_U8 backWindowColor = GetBackGroundColor(bFlash); DS_U8 foreGroundColor = ConvertFontColor(cc.pen.fg_opacity, cc.pen.fg_color, bFlash); DS_U8 edgeColor = ConvertFontEdgeColor(cc.pen.fg_opacity, cc.pen.edge_color, bFlash); DS_U8 backGroundColor = ConvertFontBackColor(cc.pen.bg_opacity, cc.pen.bg_color, bFlash); font.Color = ColorConvert(CalcColor(foreGroundColor, backWindowColor)); font.EdgeColor = ColorConvert(CalcColor(edgeColor, backWindowColor)); font.BackColor = ColorConvert(CalcColor(backGroundColor, backWindowColor)); return font; } // ȣڿ ޸ OSD_PIXEL_T * GetLineImage(int nLine, int *nWidth, int *nHeight, bool bFlash) { int nStrLen = GetStingLength(nLine); if (nStrLen == 0) { *nWidth = 0; *nHeight = 0; return 0; } static FONT_CC strFont[MAX_708_COL]; for (int x = 0; x < nStrLen; x++) { strFont[x] = ConvertCCStyleToFontStyle(strText[x][nLine], bFlash); } // ũ 鹮ڰ ƴ ù ڿ Ѵ. int nDefaultSize = strFont[0].nSize; for (int x = 0; x < nStrLen; x++) { if (strFont[x].nCode == 0) continue; nDefaultSize = strFont[x].nSize; break; } // ä for (int x = 0; x < nStrLen; x++) { if (strFont[x].nCode != 0) continue; strFont[x].nCode = ' '; strFont[x].nSize = nDefaultSize; strFont[x].nStyle = 0; strFont[x].bItalic = false; strFont[x].nEdgeType = 0; strFont[x].bUnderLine = false; strFont[x].nOffset = 0; strFont[x].Color = COLOR_TRANSPARENT; strFont[x].EdgeColor = COLOR_TRANSPARENT; strFont[x].BackColor = COLOR_TRANSPARENT; } *nWidth = DST_GetFontWidthCC(strFont, nStrLen); *nHeight = DST_GetFontHeightCC(strFont, nStrLen); OSD_PIXEL_T *LineBuff = (OSD_PIXEL_T *)DST_OS_Malloc(*nWidth * *nHeight * sizeof(OSD_PIXEL_T)); DST_GetFontImageCC(strFont, nStrLen, LineBuff); return LineBuff; } void Resize(bool bFlash) //  Ѵ. { // define window ⺻ ũ int default_width = GetCharWidth() * (window_data.column_count+1); int default_height = GetCharHeight() * (window_data.row_count+1); // ȭ鿡 ǥõ ڿ ũ int nMaxWidth = 0; int nTotalHeight = 0; int nOldHeight = GetCharHeight(); int nLines = GetStringLines(); bool bReachMaxColumn = false; // column count Ѿ // κ ̹ ׷. for (int y = 0; y < nLines; y++) { if (GetStingLength(y) >= window_data.column_count+1) bReachMaxColumn = true; OSD_PIXEL_T* LineBuff = GetLineImage(y, &nLineWidth[y], &nLineHeight[y], bFlash); DST_OS_Free(&LineBuff); if (nMaxWidth < nLineWidth[y]) nMaxWidth = nLineWidth[y]; if (nLineHeight[y] == 0) nLineHeight[y] = nOldHeight; // ̸ ̸ . nOldHeight = nLineHeight[y]; nTotalHeight += nLineHeight[y]; } if (bReachMaxColumn) { rect.w = nMaxWidth; } else { rect.w = (nMaxWidth > default_width) ? nMaxWidth : default_width; } if (rect.w == 0) return; rect.h = (nTotalHeight > default_height) ? nTotalHeight : default_height; if (rect.h == 0) return; int nScreenHeight = DST_GetCCScreenHeight(); int nScreenWidth = DST_GetCCScreenWidth(); if (rect.w > nScreenWidth) rect.w = nScreenWidth; if (rect.h > nScreenHeight) rect.h = nScreenHeight; // ̰ ļ Ǿٸ κε ̷ Ѵ. int nDataEmptyHeight = 0; int nDataHeight = 0; int nEmptyLineCount = 0; for (int y = 0; y < nLines; y++) { nDataEmptyHeight += nLineHeight[y]; if (nLineWidth[y] == 0) { nEmptyLineCount++; } else { nDataHeight += nLineHeight[y]; } } if (nDataHeight > rect.h) { DST_Printf("Error || OVER HEIGHT\n"); } else { if (nDataEmptyHeight > rect.h) { int nCompensation = (rect.h - nDataHeight) / nEmptyLineCount; DST_Printf("nCompensation = %d\n", nCompensation); for (int y = 0; y < nLines; y++) { if (nLineWidth[y] != 0) continue; nLineHeight[y] = nCompensation; } } } // ġ Ѵ. int default_x = 0; int default_y = 0; int max_x = nScreenWidth - 1; int max_y = nScreenHeight - 1; if (window_data.relative_positioning == 1) { default_x = max_x * window_data.anchor_horizontal / 99; default_y = max_y * window_data.anchor_vertical / 99; } else { if (bWideScreen) { default_x = max_x * window_data.anchor_horizontal / 209; default_y = max_y * window_data.anchor_vertical / 74; } else { default_x = max_x * (window_data.anchor_horizontal + 25) / 209; default_y = max_y * window_data.anchor_vertical / 74; } } if (default_x < 0) default_x = 0; if (default_y < 0) default_y = 0; if (default_x > max_x) default_x = max_x; if (default_y > max_y) default_y = max_y; switch (window_data.anchor_point) { case 0: break; case 1: default_x -= (rect.w/2); break; case 2: default_x -= rect.w; break; case 3: default_y -= (rect.h/2); break; case 4: default_y -= (rect.h/2); default_x -= (rect.w/2); break; case 5: default_y -= (rect.h/2); default_x -= rect.w; break; case 6: default_y -= rect.h; break; case 7: default_y -= rect.h; default_x -= (rect.w/2); break; case 8: default_y -= rect.h; default_x -= rect.w; break; } if (default_x + rect.w > nScreenWidth) default_x = nScreenWidth - rect.w; if (default_y + rect.h > nScreenHeight) default_y = nScreenHeight - rect.h; if (default_x < 0) default_x = 0; if (default_y < 0) default_y = 0; if (default_x >= nScreenWidth) default_x = nScreenWidth - 1; if (default_y >= nScreenHeight) default_y = nScreenHeight - 1; rect.x = default_x; rect.y = default_y; } void Draw(bool bFlash) { if (GetVisible() == false || GetNeedRedraw() == false) return; UpdateScreen(); Resize(bFlash); UpdateScreen(); if (imgBuff) DST_OS_Free(&imgBuff); imgBuff = 0; if (rect.w == 0 || rect.h == 0) return; imgBuff = (OSD_PIXEL_T*)DST_OS_Malloc(rect.w * rect.h * sizeof(OSD_PIXEL_T)); DrawBackGround(bFlash); DrawStrings(bFlash); SetNeedRedraw(false); } void UpdateScreen() { DST_UpdateRegionAdd(rect); } void UpdateScreen(int x, int y, int w, int h) { DST_RECT rectTemp; rectTemp.x = rect.x + x; rectTemp.y = rect.y + y; rectTemp.w = w; rectTemp.h = h; DST_UpdateRegionAdd(rectTemp); } // ÷ Ÿ̸ӿ ؼ ֱ ȣȴ. void OnFlash() { if (GetVisible() == false || bNeedDraw == true) return; if (window_data.fill_opacity == 1) // Flash Ӽ̶ ٽ ׸. { bNeedDraw = true; return; } // ߿ Flash Ӽ ִ ڰ 1ڶ ٽ ׸. int nLines = GetStringLines(); for (int y = 0; y < nLines; y++) { int nColumn = GetStingLength(y); for (int x = 0; x < nColumn; x++) { if (DST_CC_GetOpacity() == CC_FLASHING) bNeedDraw = true; if (DST_CC_GetBackOpacity() == CC_FLASHING) bNeedDraw = true; if (strText[x][y].pen.fg_opacity == 1) bNeedDraw = true; if (strText[x][y].pen.bg_opacity == 1) bNeedDraw = true; if (bNeedDraw == true) return; } } } }; // ڽ Ѵ. static bool DST_GetCommonRect(DST_RECT A, DST_RECT B, DST_RECT *C) { C->x= (A.x > B.x) ? A.x : B.x; C->y= (A.y > B.y) ? A.y : B.y; C->w= (A.x + A.w < B.x + B.w) ? (A.x + A.w - C->x) : (B.x + B.w - C->x); C->h= (A.y + A.h < B.y + B.h) ? (A.y + A.h - C->y) : (B.y + B.h - C->y); if (C->w <= 0 || C->h <= 0) return false; return true; } #if 0 ____CC_708_Decoder____() #endif // EIA 708 ɾ #define CW0 0x80 #define CW1 0x81 #define CW2 0x82 #define CW3 0x83 #define CW4 0x84 #define CW5 0x85 #define CW6 0x86 #define CW7 0x87 #define DF0 0x98 #define DF1 0x99 #define DF2 0x9A #define DF3 0x9B #define DF4 0x9C #define DF5 0x9D #define DF6 0x9E #define DF7 0x9F #define CLW 0x88 #define DLW 0x8C #define DSW 0x89 #define HDW 0x8A #define TGW 0x8B #define SWA 0x97 #define SPA 0x90 #define SPC 0x91 #define SPL 0x92 #define DLY 0x8D #define DLC 0x8E #define RST 0x8F #define EXT1 0x10 #define BS 0x08 #define CR 0x0D #define ETX 0x03 class CC708Decoder : public CWindow { private: int nCurrentWindow; CC708Window *win[8]; bool bKorean; bool bWideScreen; bool bUnicode; DS_U8 nServiceNumber; CCCircularQueue Queue; bool bFlashDraw; DS_U32 LastShowTime; public: CC708Decoder(SWinEventMsg event):CWindow(event) { LastShowTime = 0; //DST_Printf("CC708Decoder Create start\n"); bFlashDraw = false; nCurrentWindow = -1; nServiceNumber = event.data[2]; /*1~6 */ DST_CheckCCDescription(nServiceNumber, &bKorean, &bWideScreen, &bUnicode); //DST_Printf("!!!!!!!!![nServiceNumber: %d][bKorean: %d][bWideScreen: %d][bUnicode: %d]!!!!!!!!!\n",nServiceNumber, bKorean, bWideScreen, bUnicode); for (DS_U8 i = 0; i < 8; i++) { win[i] = new CC708Window(bKorean, bWideScreen); win[i]->SetID(i); } rect.w = DST_GetCCScreenWidth(); rect.h = DST_GetCCScreenHeight(); rect.x = (DST_GetScreenWidth() - rect.w) / 2; rect.y = (DST_GetScreenHeight() - rect.h) / 2; //DST_Printf("RECT %d %d %d %d\n", rect.x, rect.y, rect.w, rect.h); SetTimeOut(16); // 16 ȿ ο ٸ . TTAK.KO-07.0093 5.7.22. ڸ ڵ SetTimer(1, 500); // Flashing bTransparentWindow = false; //DST_Printf("CC708Decoder Create end\n"); } virtual ~CC708Decoder() { //DST_Printf("CC708Decoder Delete start\n"); for (DS_U8 i = 0; i < 8; i++) delete win[i]; //DST_Printf("CC708Decoder Delete end\n"); } virtual void OnTimer(char nID) { switch (nID) { case 1: // Flashing bFlashDraw = !bFlashDraw; OnFlash(); Show(); break; case 2: // ý ϸ ؼ Showϱ Show(); // Show ȿ Kill Ÿ̸簡 ȣ break; } } void Delay(unsigned char /*TenthsOfSeconds*/) { // TO DO } void DelayCancel() { // TO DO } void Reset() { for (int i = 0; i < 8; i++) win[i]->Reset(); nCurrentWindow = -1; } bool ProcessC01Byte(CCCircularQueue *Q) { switch (Q->GetByte()) { case 0x0C: PrintChar(0x0C); if (debug_cc) DST_Printf("FF\n"); break; // FF ó ġ ư. case 0x0E: PrintChar(0x0E); if (debug_cc) DST_Printf("HCR\n"); break;// HCR ó ġ ư. case 0x0D: PrintChar(0x0D); if (debug_cc) DST_Printf("CR\n"); break;// CR ͸ ø. case 0x08: PrintChar(0x08); if (debug_cc) DST_Printf("Back Space\n"); break; // Back Space case ETX: if (debug_cc) DST_Printf("End Of Text\n"); break;// End Of Text default: /*if (debug_cc) DST_Printf("Unknown C0 Code 0x%02X\n", Q->GetByte());*/ break; } Q->RemoveByte(); return true; } bool ProcessC2(CCCircularQueue *Q) { unsigned char ucNext = Q->GetNextByte(); unsigned char buff[5]; if (ucNext < 0x08) // C2 0-Additional bytes { Q->Get(buff, 2); if (debug_cc) { DST_Printf("C2 0-Additional bytes 0x%02X 0x%02X\n", buff[0], buff[1]); } return true; } if (ucNext < 0x10) // C2 1-Additional bytes { if (Q->GetSize() < 3) return false; Q->Get(buff, 3); if (debug_cc) { DST_Printf("C2 1-Additional bytes 0x%02X 0x%02X 0x%02X\n", buff[0], buff[1], buff[2]); } return true; } if (ucNext < 0x18) // C2 2-Additional bytes { if (Q->GetSize() < 4) return false; Q->Get(buff, 4); if (debug_cc) { DST_Printf("C2 2-Additional bytes 0x%02X 0x%02X 0x%02X 0x%02X\n", buff[0], buff[1], buff[2], buff[3]); } return true; } // C2 3-Additional bytes if (Q->GetSize() < 5) return false; Q->Get(buff, 5); if (debug_cc) { DST_Printf("C2 3-Additional bytes 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n", buff[0], buff[1], buff[2], buff[3], buff[4]); } return true; } bool ProcessG2(CCCircularQueue *Q) { switch (Q->GetNextByte()) { case 0x20: PrintChar(0); break; // TSP case 0x21: PrintChar(0); break; // NBTSP case 0x25: PrintChar(0x0125); break; case 0x2A: PrintChar(0x012A); break; case 0x2C: PrintChar(0x012C); break; case 0x30: PrintChar(0x0130); break; case 0x31: PrintChar(0x0131); break; case 0x32: PrintChar(0x0132); break; case 0x33: PrintChar(0x0133); break; case 0x34: PrintChar(0x0134); break; case 0x35: PrintChar(0x0135); break; case 0x39: PrintChar(0x0139); break; case 0x3A: PrintChar(0x013A); break; case 0x3C: PrintChar(0x013C); break; case 0x3D: PrintChar(0x013D); break; case 0x3F: PrintChar(0x013F); break; case 0x76: PrintChar(0x0176); break; case 0x77: PrintChar(0x0177); break; case 0x78: PrintChar(0x0178); break; case 0x79: PrintChar(0x0179); break; case 0x7A: PrintChar(0x017A); break; case 0x7B: PrintChar(0x017B); break; case 0x7C: PrintChar(0x017C); break; case 0x7D: PrintChar(0x017D); break; case 0x7E: PrintChar(0x017E); break; case 0x7F: PrintChar(0x017F); break; } unsigned char buff[2]; Q->Get(buff, 2); if (debug_cc) { DST_Printf("G2 0x%02X 0x%02X\n", buff[0], buff[1]); } return true; } bool ProcessC3(CCCircularQueue *Q) { unsigned char ucNext = Q->GetNextByte(); unsigned char buff[256]; if (ucNext < 0x88) // C3 4-Additional bytes { if (Q->GetSize() < 6) return false; Q->Get(buff, 6); if (debug_cc) { DST_Printf("C3 4-Additional bytes 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n", buff[0], buff[1], buff[2], buff[3], buff[4], buff[5]); } return true; } if (ucNext < 0x90) // C3 5-Additional bytes { if (Q->GetSize() < 7) return false; Q->Get(buff, 7); if (debug_cc) { DST_Printf("C3 5-Additional bytes 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n", buff[0], buff[1], buff[2], buff[3], buff[4], buff[5], buff[6]); } return true; } // C3 Variable Length Additional bytes if (Q->GetSize() < 3) return false; unsigned char ucNextNext = Q->GetNextNextByte() & 0x3F; // 6Ʈ Ʈ̴. if (Q->GetSize() < 3 + ucNextNext) return false; Q->Get(buff, 3 + ucNextNext); if (debug_cc) DST_Printf("C3 Variable Length Additional bytes\n"); return true; } bool ProcessG3(CCCircularQueue *Q) { if (Q->GetNextByte() == 0xA0) PrintChar(0x01A0); // [CC] unsigned char buff[2]; Q->Get(buff, 2); if (debug_cc) DST_Printf("G3 0x%02X 0x%02X\n", buff[0], buff[1]); return true; } bool ProcessExt1(CCCircularQueue *Q) { unsigned char ucData = Q->GetNextByte(); if (ucData < 0x20) { return ProcessC2(Q); } if (ucData < 0x80) { return ProcessG2(Q); } if (ucData < 0xA0) { return ProcessC3(Q); } return ProcessG3(Q); } // C0 ó bool ProcessC0(CCCircularQueue *Q) { unsigned char buff[4] = {0,0,0,0}; unsigned char ucData = Q->GetByte(); if (ucData < 0x10) // 1Ʈ ɾ { return ProcessC01Byte(Q); } if (ucData < 0x18) // 2Ʈ ɾ { if (Q->GetSize() < 2) return false; if (ucData == EXT1) { return ProcessExt1(Q); } Q->Get(buff, 2); if (debug_cc) DST_Printf("C0 0x%02X 0x%02X\n", buff[0], buff[1]); return true; } // 3Ʈ ɾ if (Q->GetSize() < 3) return false; Q->Get(buff, 3); if (ucData == 0x18 && bKorean == true) { // ASC ڿ Ѵ. if (buff[1] == 0 && (buff[2] < 0x20 || (buff[2] >= 0x80 && buff[2] < 0xA0))) { if (debug_cc) DST_Printf("P16 Not supported ascii 0x%02X\n", buff[2]); return true; } if (debug_cc) { if (buff[1] == 0) { DST_Printf("P16 0x%04X [%s]\n", (buff[1]*256)+buff[2], &buff[2]); } else { DST_Printf("P16 0x%04X [%s]\n", (buff[1]*256)+buff[2], &buff[1]); } } if (buff[1] == 0) // 0x007F 0x00A0 鹮ڷ ġȯѴ. { switch (buff[2]) { case 0x7F: case 0xA0: buff[2] = 0x20; break; } } PrintChar(bUnicode ? (DS_U16)(buff[1]*256+buff[2]) : DMW_KSX2UniSub(buff[1], buff[2])); return true; } return true; } bool ProcessC1(CCCircularQueue *Q) { unsigned char ucData = Q->GetByte(); unsigned char buff[10]; switch (ucData) { case CW0: // Current Window case CW1: case CW2: case CW3: case CW4: case CW5: case CW6: case CW7: nCurrentWindow = ucData & 0x07; Q->RemoveByte(); if (debug_cc) DST_Printf("CW%d 0x%02X\n", nCurrentWindow, ucData); return true; case DF0: // Define Window case DF1: case DF2: case DF3: case DF4: case DF5: case DF6: case DF7: if (Q->GetSize() < 7) return false; Q->Get(buff, 7); if (debug_cc) DST_Printf("DF 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n", buff[0], buff[1], buff[2], buff[3], buff[4], buff[5], buff[6]); nCurrentWindow = buff[0] & 0x07; // test code win[buff[0] & 0x07]->DefineWindow(// Window ID buff[1] & 0x07, // Priority (buff[4] >> 4) & 0x0F, // Anchor Point (buff[2] & 0x80) ? 1 : 0, // Relative Position buff[2] & 0x7F, // Anchor Vertical buff[3], // Anchor Horizontal buff[4] & 0x0F, // Row Count buff[5] & 0x3F, // Column Count (buff[1] & 0x10) ? 1 : 0, // Row Lock (buff[1] & 0x08) ? 1 : 0, // Column Lock (buff[1] & 0x20) ? 1 : 0, // Visible (buff[6] >> 3) & 0x07, // Window Style ID buff[6] & 0x07 // Pen Style ID ); return true; case CLW: // Clear Window if (Q->GetSize() < 2) return false; Q->Get(buff, 2); if (debug_cc) DST_Printf("CLW 0x%02X 0x%02X\n", buff[0], buff[1]); if (buff[1] & 0x01) win[0]->ClearWindow(); if (buff[1] & 0x02) win[1]->ClearWindow(); if (buff[1] & 0x04) win[2]->ClearWindow(); if (buff[1] & 0x08) win[3]->ClearWindow(); if (buff[1] & 0x10) win[4]->ClearWindow(); if (buff[1] & 0x20) win[5]->ClearWindow(); if (buff[1] & 0x40) win[6]->ClearWindow(); if (buff[1] & 0x80) win[7]->ClearWindow(); return true; case DLW: // Delete Window if (Q->GetSize() < 2) return false; Q->Get(buff, 2); if (debug_cc) DST_Printf("DLW 0x%02X 0x%02X\n", buff[0], buff[1]); if (buff[1] & 0x01) win[0]->DeleteWindow(); if (buff[1] & 0x02) win[1]->DeleteWindow(); if (buff[1] & 0x04) win[2]->DeleteWindow(); if (buff[1] & 0x08) win[3]->DeleteWindow(); if (buff[1] & 0x10) win[4]->DeleteWindow(); if (buff[1] & 0x20) win[5]->DeleteWindow(); if (buff[1] & 0x40) win[6]->DeleteWindow(); if (buff[1] & 0x80) win[7]->DeleteWindow(); return true; case DSW: // Display Window if (Q->GetSize() < 2) return false; Q->Get(buff, 2); if (debug_cc) DST_Printf("DSW 0x%02X 0x%02X\n", buff[0], buff[1]); if (buff[1] & 0x01) win[0]->DisplayWindow(); if (buff[1] & 0x02) win[1]->DisplayWindow(); if (buff[1] & 0x04) win[2]->DisplayWindow(); if (buff[1] & 0x08) win[3]->DisplayWindow(); if (buff[1] & 0x10) win[4]->DisplayWindow(); if (buff[1] & 0x20) win[5]->DisplayWindow(); if (buff[1] & 0x40) win[6]->DisplayWindow(); if (buff[1] & 0x80) win[7]->DisplayWindow(); return true; case HDW: // Hide Window if (Q->GetSize() < 2) return false; Q->Get(buff, 2); if (debug_cc) DST_Printf("HDW 0x%02X 0x%02X\n", buff[0], buff[1]); if (buff[1] & 0x01) win[0]->HideWindow(); if (buff[1] & 0x02) win[1]->HideWindow(); if (buff[1] & 0x04) win[2]->HideWindow(); if (buff[1] & 0x08) win[3]->HideWindow(); if (buff[1] & 0x10) win[4]->HideWindow(); if (buff[1] & 0x20) win[5]->HideWindow(); if (buff[1] & 0x40) win[6]->HideWindow(); if (buff[1] & 0x80) win[7]->HideWindow(); return true; case TGW: // Toggle Window if (Q->GetSize() < 2) return false; Q->Get(buff, 2); if (debug_cc) DST_Printf("TGW 0x%02X 0x%02X\n", buff[0], buff[1]); if (buff[1] & 0x01) win[0]->ToggleWindow(); if (buff[1] & 0x02) win[1]->ToggleWindow(); if (buff[1] & 0x04) win[2]->ToggleWindow(); if (buff[1] & 0x08) win[3]->ToggleWindow(); if (buff[1] & 0x10) win[4]->ToggleWindow(); if (buff[1] & 0x20) win[5]->ToggleWindow(); if (buff[1] & 0x40) win[6]->ToggleWindow(); if (buff[1] & 0x80) win[7]->ToggleWindow(); return true; case SWA: // Set Window Attributes if (Q->GetSize() < 5) return false; Q->Get(buff, 5); if (debug_cc) DST_Printf("SWA 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n", buff[0], buff[1], buff[2], buff[3], buff[4]); if (nCurrentWindow == -1) return true; win[nCurrentWindow]->SetWindowAttribute( buff[3] & 0x03, // Justify (buff[3] >> 4) & 0x03, // Print Direction (buff[3] >> 2) & 0x03, // Scroll Direction ((buff[3] >> 5) & 0x01) ? true : false, // Word Wrap buff[4] & 0x03, // Display Effect (buff[4] >> 2) & 0x03, // Effect Direction (buff[4] >> 4) & 0x0F, // Effect Speed (buff[1] >> 4) & 0x03, // Fill Color Red (buff[1] >> 2) & 0x03, // Fill Color Green buff[1] & 0x03, // Fill Color Blue (buff[1] >> 6) & 0x03, // Fill Color Opacity ((buff[3] >> 5) & 0x04) | ((buff[2] >> 6) & 0x03), // Border Type (buff[2] >> 4) & 0x03, // Border Color Red (buff[2] >> 2) & 0x03, // Border Color Green buff[2] & 0x03 // Border Color Blue ); return true; case SPA: // Set Pen Attributes if (Q->GetSize() < 3) return false; Q->Get(buff, 3); if (debug_cc) DST_Printf("SPA 0x%02X 0x%02X 0x%02X\n", buff[0], buff[1], buff[2]); if (nCurrentWindow < 0) return true; win[nCurrentWindow]->SetPenAttribute ( buff[1] & 0x03, // Pen Size buff[2] & 0x07, // Font Style (buff[1] >> 4) & 0x0F, // Text Tag (buff[1] >> 2) & 0x03, // Offset (buff[2] & 0x80) ? 1 : 0, // Italics (buff[2] & 0x40) ? 1 : 0, // UnderLine (buff[2] >> 3) & 0x07 // Edge Type ); return true; case SPC: // Set Pen Color if (Q->GetSize() < 4) return false; Q->Get(buff, 4); if (debug_cc) DST_Printf("SPC 0x%02X 0x%02X 0x%02X 0x%02X\n", buff[0], buff[1], buff[2], buff[3]); if (nCurrentWindow < 0) return true; win[nCurrentWindow]->SetPenColor ( (buff[1] >> 4) & 0x03, // Foreground Body Color Red (buff[1] >> 2) & 0x03, // Foreground Body Color Green (buff[1] >> 0) & 0x03, // Foreground Body Color Blue (buff[1] >> 6) & 0x03, // Foreground Body Opacity (buff[2] >> 4) & 0x03, // BackGround Body Color Red (buff[2] >> 2) & 0x03, // BackGround Body Color Green (buff[2] >> 0) & 0x03, // BackGround Body Color Blue (buff[2] >> 6) & 0x03, // BackGround Body Opacity (buff[3] >> 4) & 0x03, // Edgeground Body Color Red (buff[3] >> 2) & 0x03, // Edgeground Body Color Green (buff[3] >> 0) & 0x03 // Edgeground Body Color Blue ); return true; case SPL: // Set Pen Location if (Q->GetSize() < 3) return false; Q->Get(buff, 3); if (debug_cc) DST_Printf("SPL 0x%02X 0x%02X 0x%02X\n", buff[0], buff[1], buff[2]); if (nCurrentWindow == -1) return true; win[nCurrentWindow]->SetPenLocation( buff[2] & 0x3F, // Column buff[1] & 0x0F // Row ); if (debug_cc) DST_Printf("SPL %d %d\n", buff[2] & 0x3F, buff[1] & 0x0F); return true; case DLY: if (Q->GetSize() < 2) return false; Q->Get(buff, 2); if (debug_cc) DST_Printf("DLY 0x%02X 0x%02X\n", buff[0], buff[1]); Delay (buff[1]); return true; case DLC: if (debug_cc) DST_Printf("DLC 0x%02X\n", ucData); DelayCancel(); Q->RemoveByte(); DST_Printf("DLC\n"); return true; case RST: if (debug_cc) DST_Printf("RST 0x%02X\n", ucData); Q->RemoveByte(); Reset(); return true; } if (debug_cc) DST_Printf("Unknown C1 Command 0x%02X\n", ucData); Q->RemoveByte(); // Undefined Command. return true; } void PrintChar(DS_U16 code) { if (nCurrentWindow == -1) return; win[nCurrentWindow]->AddChar(code); } bool DecodeSub(CCCircularQueue *Q) { if (Q->GetSize() < 1) return false; unsigned char ucData = Q->GetByte(); if (ucData < 0x20) // C0 { return ProcessC0(Q); } if (ucData < 0x80) // G0 { if (debug_cc) DST_Printf("G0 %c 0x%02X\n", ucData, ucData); //if (bKorean == false) // JTBC G0 0x20 ϴ ⿡ G0 2013.03.13 { PrintChar((DS_U16)ucData); } Q->RemoveByte(); return true; } if (ucData < 0xA0) // C1 { return ProcessC1(Q); } // G1 if (debug_cc) DST_Printf("G1 %c0x%02X\n", ucData, ucData); if (bKorean == false) { PrintChar((DS_U16)ucData); } Q->RemoveByte(); return true; } virtual void Show() { if (imgBuff == 0) return; KillTimer(2); // ؼ ׸ Ÿ̸Ӹ . // EIT PMT CC description Ǿٸ ݴ´. bool _bKorean, _bWideScreen, _bUnicode; DST_CheckCCDescription(nServiceNumber, &_bKorean, &_bWideScreen, &_bUnicode); if (bKorean != _bKorean || bWideScreen != _bWideScreen) { Close(); return; } if (bKorean == true && bUnicode != _bUnicode) { Close(); return; } for (int i = 0; i < 8; i++) win[i]->Draw(bFlashDraw);// ִٸ ׸. // ׷ ȭ鿡 ׸. DST_RECT rectUpdate = DST_UpdateRegionGet(); if (rectUpdate.w == 0 || rectUpdate.h == 0) return; //DST_Printf("rectUpdate %d %d %d %d \n", rectUpdate.x, rectUpdate.y, rectUpdate.w, rectUpdate.h); UpdateScreen(rectUpdate.x, rectUpdate.y, rectUpdate.w, rectUpdate.h); //DrawBox(rectUpdate.x, rectUpdate.y, rectUpdate.w, rectUpdate.h, COLOR_TRANSPARENT); { // Ʈ ä OSD_PIXEL_T *tmp_buff = imgBuff + rect.w * rectUpdate.y + rectUpdate.x; int nSize = rectUpdate.w * sizeof(OSD_PIXEL_T); int y = rectUpdate.h; while (y--) { memset(tmp_buff, 0, nSize); tmp_buff += rect.w; } } bool bFirst = true; for (int priority = 7; priority >= 0; priority--) { // 2013.05.16 priority nCurrentWindow ׸ Ѵ. int order_table[8] = {0,1,2,3,4,5,6,7}; order_table[0] = (nCurrentWindow > -1) ? nCurrentWindow : 0; for (int i = 1; i < 8; i++) order_table[i] = (i <= order_table[0]) ? i-1 : i; for (int j = 7; j >= 0; j--) { int i = order_table[j]; if (priority != win[i]->GetPriority()) continue; if (win[i]->GetVisible() == false) continue; OSD_PIXEL_T *srcBuff = win[i]->GetImgBuff(); if (srcBuff == 0) continue; DST_RECT rectCommon; DST_RECT rectSrc = win[i]->GetSize(); if (DST_GetCommonRect(rectUpdate, rectSrc, &rectCommon ) == false) continue; int srcStartX = rectCommon.x - rectSrc.x; if (srcStartX < 0) srcStartX = 0; int srcStartY = rectCommon.y - rectSrc.y; if (srcStartY < 0) srcStartY = 0; //DS_U8* des1 = imgBuff + rect.w * rectCommon.y + rectCommon.x; //DS_U8* src1 = srcBuff + rectSrc.w * srcStartY + srcStartX; if (bFirst == true) { bFirst = false; OSD_PIXEL_T* src = srcBuff + rectSrc.w * srcStartY + srcStartX; OSD_PIXEL_T* des = imgBuff + rectCommon.y * rect.w + rectCommon.x; int y = rectCommon.h; int nSize = rectCommon.w * sizeof(OSD_PIXEL_T); while (y--) { memcpy(des, src, nSize); src += rectSrc.w; des += rect.w; } } else { OSD_PIXEL_T* src = srcBuff + rectSrc.w * srcStartY + srcStartX; OSD_PIXEL_T* des = imgBuff + rectCommon.y * rect.w + rectCommon.x; int src_delta = rectSrc.w-rectCommon.w; int des_delta = rect.w-rectCommon.w; int y = rectCommon.h; while (y--) { int x = rectCommon.w; while (x--) { if (*src) *des = *src; src++; des++; } src+=src_delta; des+=des_delta; } } } } DST_UpdateRegionReset(); LastShowTime = DST_OS_GetTickCount(); } void OnFlash() { for (int i = 0; i < 8; i++) win[i]->OnFlash(); // ÷ ° ٲ ׸ ִ ƮѴ. } virtual void OnMessage(SWinEventMsg event) { int i = 0; switch (event.cmd) { case WM_SEQ_ERROR: Close(); break; case WM_CS1: if (GetState() != 1) break; ResetTimer(0); // ŸӾƿ Ѵ. for (i = 0 ; i < event.data[0]; i++) { if (debug_cc) DST_Printf("%02X ", event.data[i+1]); Queue.Add(event.data[i+1]); } if (debug_cc) DST_Printf("\n"); while (1) { if (DecodeSub(&Queue)== false) break; } if (LastShowTime > DST_OS_GetTickCount()) LastShowTime = DST_OS_GetTickCount(); if (DST_OS_GetTickCount() - LastShowTime < DST_OS_GetTicksPerSecond()/10) { SetTimer(2, 100); // 100ms Ŀ ׸ } else { Show(); } break; case WM_CC_CLOSE: // T(); Close(); break; } } }; void DST_CreateCC708Win(SWinEventMsg event) { DST_AddWin((WinID)(event.data[0]), new CC708Decoder(event)); }