Exemplo n.º 1
0
        /// <summary>
        /// Renders a teletext page to a bitmap using the designated
        /// default charset and second G0 charset designation.
        /// If either designation is -1 use the corresponding
        /// preselected designation.
        /// </summary>
        /// <param name="byPage">Teletext page data</param>
        /// <param name="mPage">Pagenumber</param>
        /// <param name="sPage">Subpagenumber</param>
        /// <returns>Rendered teletext page as bitmap</returns>
        public void RenderPage(ref Bitmap pageBitmap, byte[] byPage, int mPage, int sPage, bool waiting)
        {
            int  col;
            int  hold;
            int  foreground, background, doubleheight, charset, mosaictype;
            byte held_mosaic;
            bool flag    = false;
            bool isBoxed = false;

            byte[] pageChars   = new byte[31 * 40];
            int[]  pageAttribs = new int[31 * 40];
            bool   row24       = false;

            if (pageBitmap == null)
            {
                return;
            }

            Graphics renderGraphics = Graphics.FromImage(pageBitmap);

            // Decode the page data (Hamming 8/4 or odd parity)
            for (int rowNr = 0; rowNr < MAX_ROWS; rowNr++)
            {
                if (rowNr * 42 >= byPage.Length)
                {
                    break;
                }
                int packetNumber = Hamming.GetPacketNumber(rowNr * 42, ref byPage);
                // Only the packets 0-25 are accepted
                if (packetNumber < 0 || packetNumber > 25)
                {
                    continue;
                }
                bool stripParity = true;
                // Packets 0 and 25 are hamming 8/4 encoded
                if (packetNumber == 25 || packetNumber == 0)
                {
                    stripParity = false;
                }
                // Decode the whole row and remove the first two bytes
                for (col = 2; col < 42; col++)
                {
                    // After pageheader in packet 0 (Bit 10) odd parity is used
                    if (col >= 10 && packetNumber == 0)
                    {
                        stripParity = true;
                    }
                    byte kar = byPage[rowNr * 42 + col];
                    if (stripParity)
                    {
                        kar &= 0x7f;
                    }
                    pageChars[packetNumber * 40 + col - 2] = kar;
                }
                // Exists a packet 24 (Toptext line)
                if (packetNumber == 24)
                {
                    row24 = true;
                }
            }
            int row;
            int txtLanguage;
            // language detection. Extract the bit C12-C14 from the teletext header and set the language code
            int  languageCode;
            byte byte1 = Hamming.Decode[byPage[9]];

            if (byte1 == 0xFF)
            {
                languageCode = 0;
            }
            else
            {
                languageCode = ((byte1 >> 3) & 0x01) | (((byte1 >> 2) & 0x01) << 1) | (((byte1 >> 1) & 0x01) << 2);
            }

            switch (languageCode)
            {
            case 0:
                txtLanguage = 1;
                break;

            case 1:
                txtLanguage = 4;
                break;

            case 2:
                txtLanguage = _isRegionalDKorNO ? 13 : 11;
                break;

            case 3:
                txtLanguage = 5;
                break;

            case 4:
                txtLanguage = 3;
                break;

            case 5:
                txtLanguage = 8;
                break;

            case 6:
                txtLanguage = 0;
                break;

            default:
                txtLanguage = 1;
                break;
            }
            // Detect if it's a boxed page. Boxed Page = subtitle and/or newsflash bit is set
            bool isSubtitlePage = Hamming.IsSubtitleBitSet(0, ref byPage);
            bool isNewsflash    = Hamming.IsNewsflash(0, ref byPage);

            isBoxed = isNewsflash | isSubtitlePage;
            MediaPortal.GUI.Library.Log.Debug("Newsflash: " + isNewsflash);
            MediaPortal.GUI.Library.Log.Debug("Subtitle: " + isSubtitlePage);
            MediaPortal.GUI.Library.Log.Debug("Boxed: " + isBoxed);

            // Determine if the header or toptext line sould be displayed.
            bool displayHeaderAndTopText = !_fullscreenMode || !isBoxed || (isBoxed && _selectedPageText.IndexOf("-") != -1)
                                           ||
                                           (isBoxed && _selectedPageText.IndexOf("-") == -1 &&
                                            !_selectedPageText.Equals(Convert.ToString(mPage, 16)));

            // Iterate over all lines of the teletext page and prepare the rendering
            for (row = 0; row <= 24; row++)
            {
                // If row 24 and no toptext exists, then skip this row
                if (row == 24 && !row24)
                {
                    continue;
                }
                // If not display the header and toptext line, then clear these two rows
                if ((row == 0 || row == 24) && !displayHeaderAndTopText)
                {
                    for (int i = 0; i < 40; ++i)
                    {
                        pageChars[row * 40 + i]   = 32;
                        pageAttribs[row * 40 + i] = ((int)TextColors.Trans1 << 4) | ((int)TextColors.White);
                    }
                }
                else
                {
                    // Otherwise, analyse the information. First set the forground to white and the background to:
                    // - Transparent, if transparent mode or boxed and fullscreen and not display the header and toptext line
                    // - Black otherwise
                    foreground = (int)TextColors.White;
                    if ((isBoxed || _transparentMode) && _fullscreenMode && !displayHeaderAndTopText)
                    {
                        background = (int)TextColors.Trans1;
                    }
                    else
                    {
                        background = (int)TextColors.Black;
                    }

                    // Reset the attributes
                    doubleheight = 0;
                    charset      = 0;
                    mosaictype   = 0;
                    hold         = 0;
                    held_mosaic  = 32;
                    // Iterate over all columns in the row and check if a box starts
                    for (int loop1 = 0; loop1 < 40; loop1++)
                    {
                        // Box starts in this row
                        if (pageChars[(row * 40) + loop1] == (int)Attributes.StartBox)
                        {
                            flag = true;
                            break;
                        }
                    }

                    // If boxed page and box doesn't start in this line, than set foreground and background to black or transparent
                    // depending on the mode (fullscreen <-> windowed)
                    if (isBoxed && flag == false)
                    {
                        if (_fullscreenMode)
                        {
                            foreground = (int)TextColors.Trans1;
                            background = (int)TextColors.Trans1;
                        }
                        else
                        {
                            foreground = (int)TextColors.Black;
                            background = (int)TextColors.Black;
                        }
                    }

                    // Iterate over all columns in the row again and now analyse every byte
                    for (col = 0; col < 40; col++)
                    {
                        int index = row * 40 + col;

                        // Set the attributes
                        pageAttribs[index] = (doubleheight << 10 | charset << 8 | background << 4 | foreground);
                        // Boxed and no flag and not row 24 than delete the characters
                        if (isBoxed && !flag && row != 24)
                        {
                            pageChars[index] = 32;
                        }
                        // Analyse the attributes
                        if (pageChars[index] < 32)
                        {
                            switch (pageChars[index])
                            {
                            case (int)Attributes.AlphaBlack:
                                foreground = (int)TextColors.Black;
                                charset    = 0;
                                break;

                            case (int)Attributes.AlphaRed:
                                foreground = (int)TextColors.Red;
                                charset    = 0;
                                break;

                            case (int)Attributes.AlphaGreen:
                                foreground = (int)TextColors.Green;
                                charset    = 0;
                                break;

                            case (int)Attributes.AlphaYellow:
                                foreground = (int)TextColors.Yellow;
                                charset    = 0;
                                break;

                            case (int)Attributes.AlphaBlue:
                                foreground = (int)TextColors.Blue;
                                charset    = 0;
                                break;

                            case (int)Attributes.AlphaMagenta:
                                foreground = (int)TextColors.Magenta;
                                charset    = 0;
                                break;

                            case (int)Attributes.AlphaCyan:
                                foreground = (int)TextColors.Cyan;
                                charset    = 0;
                                break;

                            case (int)Attributes.AlphaWhite:
                                foreground = (int)TextColors.White;
                                charset    = 0;
                                break;

                            case (int)Attributes.Flash:
                                break;

                            case (int)Attributes.Steady:
                                break;

                            case (int)Attributes.EndBox:
                                if (isBoxed)
                                {
                                    if (_fullscreenMode)
                                    {
                                        foreground = (int)TextColors.Trans1;
                                        background = (int)TextColors.Trans1;
                                    }
                                    else
                                    {
                                        foreground = (int)TextColors.Black;
                                        background = (int)TextColors.Black;
                                    }
                                }
                                break;

                            case (int)Attributes.StartBox:
                                if (isBoxed)
                                {
                                    // Clear everything until this position in the line
                                    if (col > 0)
                                    {
                                        for (int loop1 = 0; loop1 < col; loop1++)
                                        {
                                            pageChars[(row * 40) + loop1] = 32;
                                        }
                                    }
                                    // Clear also the page attributes
                                    for (int clear = 0; clear < col; clear++)
                                    {
                                        if (_fullscreenMode)
                                        {
                                            pageAttribs[row * 40 + clear] = doubleheight << 10 | charset << 8 | (int)TextColors.Trans1 << 4 |
                                                                            (int)TextColors.Trans1;
                                        }
                                        else
                                        {
                                            pageAttribs[row * 40 + clear] = doubleheight << 10 | charset << 8 | (int)TextColors.Black << 4 |
                                                                            (int)TextColors.Black;
                                        }
                                    }
                                    // Set the standard background color
                                    if (background == (int)TextColors.Trans1)
                                    {
                                        background = (int)TextColors.Black;
                                    }
                                }
                                break;

                            case (int)Attributes.NormalSize:
                                doubleheight       = 0;
                                pageAttribs[index] = (doubleheight << 10 | charset << 8 | background << 4 | foreground);
                                break;

                            case (int)Attributes.DoubleHeight:
                                if (row < 23)
                                {
                                    doubleheight = 1;
                                }
                                break;

                            case (int)Attributes.MosaicBlack:
                                foreground = (int)TextColors.Black;
                                charset    = 1 + mosaictype;
                                break;

                            case (int)Attributes.MosaicRed:
                                foreground = (int)TextColors.Red;
                                charset    = 1 + mosaictype;
                                break;

                            case (int)Attributes.MosaicGreen:
                                foreground = (int)TextColors.Green;
                                charset    = 1 + mosaictype;
                                break;

                            case (int)Attributes.MosaicYellow:
                                foreground = (int)TextColors.Yellow;
                                charset    = 1 + mosaictype;
                                break;

                            case (int)Attributes.MosaicBlue:
                                foreground = (int)TextColors.Blue;
                                charset    = 1 + mosaictype;
                                break;

                            case (int)Attributes.MosaicMagenta:
                                foreground = (int)TextColors.Magenta;
                                charset    = 1 + mosaictype;
                                break;

                            case (int)Attributes.MosaicCyan:
                                foreground = (int)TextColors.Cyan;
                                charset    = 1 + mosaictype;
                                break;

                            case (int)Attributes.MosaicWhite:
                                foreground = (int)TextColors.White;
                                charset    = 1 + mosaictype;
                                break;

                            case (int)Attributes.Conceal:
                                if (_hiddenMode == false)
                                {
                                    foreground         = background;
                                    pageAttribs[index] = (doubleheight << 10 | charset << 8 | background << 4 | foreground);
                                }
                                break;

                            case (int)Attributes.ContiguousMosaic:
                                mosaictype = 0;
                                if (charset > 0)
                                {
                                    charset            = 1;
                                    pageAttribs[index] = (doubleheight << 10 | charset << 8 | background << 4 | foreground);
                                }
                                break;

                            case (int)Attributes.SeparatedMosaic:
                                mosaictype = 1;
                                if (charset > 0)
                                {
                                    charset            = 2;
                                    pageAttribs[index] = (doubleheight << 10 | charset << 8 | background << 4 | foreground);
                                }
                                break;

                            case (int)Attributes.Esc:
                                break;

                            case (int)Attributes.BlackBackground:
                                background         = (int)TextColors.Black;
                                pageAttribs[index] = (doubleheight << 10 | charset << 8 | background << 4 | foreground);
                                break;

                            case (int)Attributes.NewBackground:
                                background         = foreground;
                                pageAttribs[index] = (doubleheight << 10 | charset << 8 | background << 4 | foreground);
                                break;

                            case (int)Attributes.HoldMosaic:
                                hold = 1;
                                break;

                            case (int)Attributes.ReleaseMosaic:
                                hold = 2;
                                break;
                            }

                            if (hold > 0 && charset > 0)
                            {
                                pageChars[index] = held_mosaic;
                            }
                            else
                            {
                                pageChars[index] = 32;
                            }

                            if (hold == 2)
                            {
                                hold = 0;
                            }
                        }
                        else
                        {
                            if (charset > 0)
                            {
                                held_mosaic = pageChars[index];
                            }
                            // If doubleheight is selected than delete the following line
                            if (doubleheight > 0)
                            {
                                pageChars[index + 40] = 0xFF;
                            }
                        }
                    }
                    // Check, if there is double height selected in than set the attributes for the next row and skip it
                    for (int count = (row + 1) * 40; count < ((row + 1) * 40) + 40; count++)
                    {
                        if (pageChars[count] == 255)
                        {
                            for (int loop1 = 0; loop1 < 40; loop1++)
                            {
                                pageAttribs[(row + 1) * 40 + loop1] = ((pageAttribs[(row * 40) + loop1] & 0xF0) |
                                                                       ((pageAttribs[(row * 40) + loop1] & 0xF0) >> 4));
                            }

                            row++;
                            break;
                        }
                    }
                }
            } //for (int rowNr = 0; rowNr < 24; rowNr++)

            // Generate header line, if it should be displayed
            if (IsDecimalPage(mPage) && displayHeaderAndTopText)
            {
                int    i;
                string pageNumber;
                int    lineColor;
                // Determine the state, of the header line.
                // Red=Incomplete page number
                // Yellow=Waiting for page
                // Green=Page is displayed
                if (_selectedPageText.IndexOf("-") == -1)
                {
                    if (waiting)
                    {
                        lineColor  = (int)TextColors.Yellow;
                        pageNumber = _selectedPageText + (_selectedSubPageText == string.Empty ? "" : ("/" + _selectedSubPageText));
                    }
                    else
                    {
                        lineColor  = (int)TextColors.Green;
                        pageNumber = Convert.ToString(mPage, 16) + "/" + Convert.ToString(sPage + 1, 16);
                    }
                }
                else
                {
                    lineColor  = (int)TextColors.Red;
                    pageNumber = _selectedPageText;
                }
                string headline = "MediaPortal P." + pageNumber;
                headline += new string((char)32, 32 - headline.Length);
                byte[] mpText = Encoding.ASCII.GetBytes(headline);
                Array.Copy(mpText, 0, pageChars, 0, mpText.Length);
                for (i = 0; i < 11; i++)
                {
                    pageAttribs[i] = ((int)TextColors.Black << 4) | lineColor;
                }
                for (i = 12; i < 40; i++)
                {
                    pageAttribs[i] = ((int)TextColors.Black << 4) | ((int)TextColors.White);
                }
            }

            // Now we generate the bitmap
            int   y = 0;
            int   x;
            int   width       = _pageRenderWidth / 40;
            int   height      = _pageRenderHeight / 25;
            float fntSize     = height; //Math.Min(width, height);
            float nPercentage = ((float)_percentageOfMaximumHeight / 100);

            _fontTeletext = new Font("Lucida Console", fntSize, FontStyle.Regular, GraphicsUnit.Pixel);
            float fntHeight = _fontTeletext.GetHeight(renderGraphics);

            while (fntHeight > nPercentage * height) // || fntHeight > nPercentage * width)
            {
                fntSize      -= 0.1f;
                _fontTeletext = new Font("Lucida Console", fntSize, FontStyle.Bold, GraphicsUnit.Pixel);
                fntHeight     = _fontTeletext.GetHeight(renderGraphics);
            }
            MediaPortal.GUI.Library.Log.Debug("FONT SIZE OF TELETEXT: " + fntSize);

            try
            {
                // Select the brush, depending on the page and mode
                // Draw the base rectangle
                if ((isBoxed || _transparentMode) && _fullscreenMode)
                {
                    renderGraphics.Clear(Transparent);
                }
                else
                {
                    renderGraphics.FillRectangle(new SolidBrush(Color.Black), 0, 0, _pageRenderWidth, _pageRenderHeight);
                }

                // Fill the rectangle with the teletext page informations
                for (row = 0; row < 25; row++)
                {
                    // If not display a toptext line than abort
                    if (!displayHeaderAndTopText && row == 24)
                    {
                        break;
                    }
                    x = 0;
                    // Draw a single point
                    for (col = 0; col < 40; col++)
                    {
                        Render(ref renderGraphics, ref pageBitmap, pageChars[row * 40 + col], pageAttribs[row * 40 + col], ref x,
                               ref y, width, height,
                               txtLanguage);
                    }

                    y += height + (row == 23 ? 2 : 0);
                }
            }
            finally
            {
                _fontTeletext.Dispose();
                _fontTeletext = null;
            }
        }