Ejemplo n.º 1
0
        // Generate new items inheriting properties from the previous
        public MHTextItem NewItem()
        {
            MHTextItem pItem = new MHTextItem();

            pItem.m_Colour = m_Colour;
            return(pItem);
        }
Ejemplo n.º 2
0
        // UK MHEG specifies the use of the Tiresias font and broadcasters appear to
        // assume that all MHEG applications will lay the text out in the same way.

        // Recreate the image.
        protected void Redraw()
        {
            if (!RunningStatus || m_pDisplay == null)
            {
                return;
            }
            if (m_nBoxWidth == 0 || m_nBoxHeight == 0)
            {
                return;                                        // Can't draw zero sized boxes.
            }
            m_pDisplay.SetSize(m_nBoxWidth, m_nBoxHeight);
            m_pDisplay.Clear();

            MHRgba textColour = GetColour(m_textColour);
            // Process any escapes in the text and construct the text arrays.
            MHSequence <MHTextLine> theText = new MHSequence <MHTextLine>();
            // Set up the first item on the first line.
            MHTextItem pCurrItem = new MHTextItem();
            MHTextLine pCurrLine = new MHTextLine();

            pCurrLine.Items.Append(pCurrItem);
            theText.Append(pCurrLine);
            Stack <MHRgba> m_ColourStack = new Stack <MHRgba>(); // Stack to handle nested colour codes.

            m_ColourStack.Push(textColour);
            pCurrItem.Colour = textColour;

            int i = 0;

            while (i < m_Content.Size)
            {
                char ch = m_Content.GetAt(i++);

                if (ch == '\t')   // Tab - start a new item if we have any text in the existing one.
                {
                    if (pCurrItem.Text.Size != 0)
                    {
                        pCurrItem = pCurrItem.NewItem();
                        pCurrLine.Items.Append(pCurrItem);
                    }
                    pCurrItem.TabCount++;
                }

                else if (ch == '\r')   // CR - line break.
                // TODO: Two CRs next to one another are treated as </P> rather than <BR><BR>
                // This should also include the sequence CRLFCRLF.
                {
                    pCurrLine = new MHTextLine();
                    theText.Append(pCurrLine);
                    pCurrItem = pCurrItem.NewItem();
                    pCurrLine.Items.Append(pCurrItem);
                }

                else if (ch == 0x1b)   // Escape - special codes.
                {
                    if (i == m_Content.Size)
                    {
                        break;
                    }
                    char code = m_Content.GetAt(i);
                    // The only codes we are interested in are the start and end of colour.
                    // TODO: We may also need "bold" and some hypertext colours.

                    if (code >= 0x40 && code <= 0x5e)   // Start code
                    // Start codes are followed by a parameter count and a number of parameter bytes.
                    {
                        if (++i == m_Content.Size)
                        {
                            break;
                        }
                        char paramCount = m_Content.GetAt(i);
                        i++;
                        if (code == 0x43 && paramCount == 4 && i + paramCount <= m_Content.Size)
                        {
                            // Start of colour.
                            if (pCurrItem.Text.Size != 0)
                            {
                                pCurrItem = pCurrItem.NewItem(); pCurrLine.Items.Append(pCurrItem);
                            }
                            pCurrItem.Colour = new MHRgba(m_Content.GetAt(i), m_Content.GetAt(i + 1),
                                                          m_Content.GetAt(i + 2), 255 - m_Content.GetAt(i + 3));
                            // Push this colour onto the colour stack.
                            m_ColourStack.Push(pCurrItem.Colour);
                        }
                        else
                        {
                            Logging.Log(Logging.MHLogWarning, "Unknown text escape code " + code);
                        }
                        i += paramCount;                   // Skip the parameters
                    }
                    else if (code >= 0x60 && code <= 0x7e) // End code.
                    {
                        i++;
                        if (code == 0x63)
                        {
                            if (m_ColourStack.Count > 1)
                            {
                                m_ColourStack.Pop();
                                // Start a new item since we're using a new colour.
                                if (pCurrItem.Text.Size != 0)
                                {
                                    pCurrItem = pCurrItem.NewItem();
                                    pCurrLine.Items.Append(pCurrItem);
                                }
                                // Set the subsequent text in the colour we're using now.
                                pCurrItem.Colour = m_ColourStack.Peek();
                            }
                        }
                    }
                }

                else if (ch <= 0x1f)
                {
                    // Certain characters including LF and the marker codes between 0x1c and 0x1f are
                    // explicitly intended to be ignored.  Include all the other codes.
                }

                else   // Add to the current text.
                {
                    int nStart = i - 1;
                    while (i < m_Content.Size && m_Content.GetAt(i) >= 0x20)
                    {
                        i++;
                    }
                    pCurrItem.Text.Append(new MHOctetString(m_Content, nStart, i - nStart));
                }
            }


            // Set up the initial attributes.
            int style, size, lineSpace, letterSpace;

            InterpretAttributes(m_fontAttrs, out style, out size, out lineSpace, out letterSpace);
            // Create a font with this information.
            m_pDisplay.SetFont(size, (style & 2) != 0, (style & 1) != 0);

            // Calculate the layout of each section.
            for (i = 0; i < theText.Size; i++)
            {
                MHTextLine pLine = theText.GetAt(i);
                pLine.LineWidth = 0;
                for (int j = 0; j < pLine.Items.Size; j++)
                {
                    MHTextItem pItem = pLine.Items.GetAt(j);
                    // Set any tabs.
                    for (int k = 0; k < pItem.TabCount; k++)
                    {
                        pLine.LineWidth += TABSTOP - pLine.LineWidth % TABSTOP;
                    }

                    if (pItem.UnicodeLength == 0)
                    { // Convert UTF-8 to Unicode.
                        int s = pItem.Text.Size;
                        pItem.Unicode       = pItem.Text.ToString();
                        pItem.UnicodeLength = pItem.Unicode.Length;
                    }
                    // Fit the text onto the line.
                    int nFullText = pItem.UnicodeLength;
                    // Get the box size and update pItem.m_nUnicode to the number that will fit.
                    Rectangle rect = m_pDisplay.GetBounds(pItem.Unicode, ref nFullText, m_nBoxWidth - pLine.LineWidth);
                    if (nFullText == pItem.UnicodeLength || !m_fTextWrap)
                    {
                        // All the characters fit or we're not wrapping.
                        pItem.Width      = rect.Width;
                        pLine.LineWidth += rect.Width;
                    }

                    /*                   else if (m_fTextWrap)
                     *                 { // No, we have to word-wrap.
                     *                     int nTruncated = pItem.UnicodeLength; // Just in case.
                     *                     // Now remove characters until we find a word-break character.
                     *                     while (pItem.UnicodeLength > 0 && pItem.Unicode[pItem.UnicodeLength] != ' ') pItem.UnicodeLength--;
                     *                     // If there are now word-break characters we truncate the text.
                     *                     if (pItem.UnicodeLength == 0) pItem.UnicodeLength = nTruncated;
                     *                     // Special case to avoid infinite loop if the box is very narrow.
                     *                     if (pItem.UnicodeLength == 0) pItem.UnicodeLength = 1;
                     *
                     *                     // We need to move the text we've cut off this line into a new line.
                     *                     int nNewWidth = nFullText - pItem.UnicodeLength;
                     *                     int nNewStart = pItem.UnicodeLength;
                     *                     // Remove any spaces at the start of the new section.
                     *                     while (nNewWidth != 0 && pItem.Unicode[nNewStart] == ' ') { nNewStart++; nNewWidth--; }
                     *                     if (nNewWidth != 0) {
                     *                         // Create a new line from the extra text.
                     *                         MHTextLine pNewLine = new MHTextLine();
                     *                         theText.InsertAt(pNewLine, i+1);
                     *                         // The first item on the new line is the rest of the text.
                     *                         MHTextItem pNewItem = pItem.NewItem();
                     *                         pNewLine.Items.Append(pNewItem);
                     *                         pNewItem.Unicode = pItem.Unicode.Substring(nNewStart, nNewWidth);
                     *                         pNewItem.UnicodeLength = nNewWidth;
                     *                     }
                     *                     // Remove any spaces at the end of the old section.  If we don't do that and
                     *                     // we are centering or right aligning the text we'll get it wrong.
                     *                     while (pItem.UnicodeLength > 1 && pItem.Unicode[pItem.UnicodeLength - 1] == ' ') pItem.UnicodeLength--;
                     *                     int uniLength = pItem.UnicodeLength;
                     *                     rect = m_pDisplay.GetBounds(pItem.Unicode, ref uniLength, 0);
                     *                     pItem.Width = rect.Width;
                     *                     pLine.LineWidth += rect.Width;
                     *                 }
                     */}
            }

            // Now output the text.
            int yOffset = 0;
            // If there isn't space for all the lines we should drop extra lines.
            int nNumLines = theText.Size;

            do
            {
                if (m_VertJ == End)
                {
                    yOffset = m_nBoxHeight - nNumLines * lineSpace;
                }
                else if (m_VertJ == Centre)
                {
                    yOffset = (m_nBoxHeight - nNumLines * lineSpace) / 2;
                }
                if (yOffset < 0)
                {
                    nNumLines--;
                }
            } while (yOffset < 0);

            for (i = 0; i < nNumLines; i++)
            {
                MHTextLine pLine   = theText.GetAt(i);
                int        xOffset = 0;
                if (m_HorizJ == End)
                {
                    xOffset = m_nBoxWidth - pLine.LineWidth;
                }
                else if (m_HorizJ == Centre)
                {
                    xOffset = (m_nBoxWidth - pLine.LineWidth) / 2;
                }
                //ASSERT(xOffset >= 0);

                for (int j = 0; j < pLine.Items.Size; j++)
                {
                    MHTextItem pItem = pLine.Items.GetAt(j);
                    // Tab across if necessary.
                    for (int k = 0; k < pItem.TabCount; k++)
                    {
                        xOffset += TABSTOP - xOffset % TABSTOP;
                    }
                    if (pItem.Unicode.Length != 0)           // We may have blank lines.
                    {
                        m_pDisplay.AddText(xOffset, yOffset, // Jas removed this cos it doesn't make sense yOffset + lineSpace
                                           pItem.Unicode.Substring(0, pItem.UnicodeLength), pItem.Colour);
                    }
                    xOffset += pItem.Width;
                }
                yOffset += lineSpace;
                if (yOffset + lineSpace > m_nBoxHeight)
                {
                    break;
                }
            }
        }