3gppttstructs.cpp

来自「symbian 下的helix player源代码」· C++ 代码 · 共 1,345 行 · 第 1/3 页

CPP
1,345
字号

        if(FAILED(hr))
        {
            HX_ASSERT(false);
            break;
        }

       
        // we should consume the box data size exactly
        HX_ASSERT( UINT32(pData - box.GetData()) == box.GetDataSize());

        // /If we found one, then use it if it's lowest so far:
        if (curEndCharOffset <
                uiLowestPotentialNextTCStartOffsetFound  &&
                // /Ignore if end is prior to our start:
                // /(Changed '>=' to '>' to prevent infinite loop)
                curEndCharOffset > m_uiUnpackedStartCharOffset)
        {
            uiLowestPotentialNextTCStartOffsetFound =
                    curEndCharOffset;
        }
    }

    if(SUCCEEDED(hr))
    {
        // we should always end up exactly at end of data
        HX_ASSERT(pData == pDataEnd);

        // /OK, our end char offset is one less than the lowest start
        // of the next T.C. found, above, (& not less than our start):
        HX_ASSERT(uiLowestPotentialNextTCStartOffsetFound > 0);
        if (HX_3GPPTT_MAX_CHAR_OFFSET !=
                uiLowestPotentialNextTCStartOffsetFound)
        {
            // /Don't add 1 here; it's end-point exclusive:
            m_uiUnpackedEndCharOffset = uiLowestPotentialNextTCStartOffsetFound;
        }
        else
        {
            m_uiUnpackedEndCharOffset = HX_3GPPTT_MAX_CHAR_OFFSET;
        }
    }

    return hr;
            
}

HX_RESULT C3GPPTextContainer::Init
(
    IHXPacket* pPacket,
    UINT32 ulPacketContentsBeginTime,
    UINT32 ulMaxEndTime,
    UINT16 uiStartCharOffset, 
    /*OUT*/ UINT16& uiREFIndexOfLastChar)
{
    HX_RESULT hxr = HXR_OK;

    HX_ASSERT(pPacket);
    m_pPacket = pPacket;
    m_pPacket->AddRef();
    m_ulEndTime = ulMaxEndTime; // /Initialize for now to this
    m_ulBeginTime = ulPacketContentsBeginTime;
    m_uiUnpackedStartCharOffset = uiStartCharOffset;

    uiREFIndexOfLastChar = HX_3GPPTT_INVALID_INDEX;

    BOOL bNeedToBreakTCsUpAtNewlines = FALSE;

    

    // /Go through the textModifiers of the packet and figure out what our
    // end index is in the text buffer based on where the end of same-
    // attributed continguous text ends.  Return the end index in
    // uiREFIndexOfLastChar so, if there's any text remaining, another
    // C3GPPTextContainer can be created knowing where to start:
//-----------------------------------------------------------------------------
    IHXBuffer* pBuff = m_pPacket->GetBuffer();
    if (pBuff)
    {
        BOOL bTextIsUTF16ReverseEncoded = FALSE;
        BOOL bTextIsUTF16Encoded = FALSE;

        m_pTextSample = new C3GPPTextSample(pBuff);
        HX_ASSERT(m_pTextSample);
        if (!m_pTextSample)
        {
            hxr = HXR_OUTOFMEMORY;
            goto cleanup;
        }

        bTextIsUTF16Encoded = IsUTF16Encoded(
                (UCHAR*)(m_pTextSample->GetText()),
                m_pTextSample->GetTextLenInBytes(),
                bTextIsUTF16ReverseEncoded);

        hxr = BuildSampleModifiers(bNeedToBreakTCsUpAtNewlines);
        if(FAILED(hxr))
        {
            goto cleanup;
        }


        // /XXXEH- TODO: this is not UTF-8 friendly code (when 2-byte
        // \000r or \000n chars are present)!  Also, \r or \n may be 2nd
        // byte of a 2-byte value and not meant as a newline (CR or LF,
        // respectively) char!
        // /Before patting ourselves on the back for finding the start &
        // end offsets of this text container, we need to look for
        // newline characters and break up TC's at each new-line
        // character, but only if m_pTextSample->m_pTextModifiers exists
        // and modified individual parts of the text and not just the
        // entire thing, e.g., as 'tbox' does.  Otherwise it's OK to
        // leave entire packet's text as one TextContainer even if it
        // has newline chars:

        // /Note: these are the supported UNICODE text wrap controls:
        //  \u000a (LF)
        //  \u000d (CR)
        //  \u000d\u000a (CRLF)
        //  \u0085 (NEXT LINE)
        //  \u2028 (LINE SEP)
        //  \u2029 (PARA SEP)

#if defined(_SYMBIAN) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
        // /Convert to UTF-16 then go through and start a new
        // TextContainer wherever a newline char is found that
        // does not immediately follow another newline:
        HX_RESULT hxrsltCnvrtChars = HXR_OK;
        HBufC16* pHBufUTF16Text = NULL;
        HBufC8*  pHBufUTF8Text = NULL;
        const char* pUnconvertedText = m_pTextSample->GetText() + m_uiUnpackedStartCharOffset;
        INT32 lUnconvertedTextLen = (INT32)
                ((UINT32)GetTextByteLength());
        HX_ASSERT(m_uiUnpackedEndCharOffset >= (UINT32)lUnconvertedTextLen);

        BOOL bDummyVar = FALSE;
        BOOL bTextContainerTextStartsWithUTF16EncodeFlag =
                IsUTF16Encoded((UCHAR*)pUnconvertedText,
                lUnconvertedTextLen,
                bDummyVar);
        INT32 lTextLenInChars = lUnconvertedTextLen;
        if (bTextIsUTF16Encoded)
        {
            HX_ASSERT(!(lTextLenInChars & 0x1)); // /Shouldn't be odd
            lTextLenInChars >>= 1; // /Divide by 2: 2 bytes/char
            if (bTextContainerTextStartsWithUTF16EncodeFlag)
            {
                // /Skip past 0xfffe UTF-16 flag at start:
                pUnconvertedText += 2;
                lTextLenInChars--;
            }
        }
        if (hxrsltCnvrtChars==HXR_OK  &&  pUnconvertedText  &&
                lUnconvertedTextLen > 0)
        {
            pHBufUTF16Text = HBufC16::NewMax((TInt)lTextLenInChars);
            if (pHBufUTF16Text)
            {
                TInt tiNumLinesOfText = 1;
                // /UTF-8 to UTF-16 translation:
                if (bTextIsUTF16Encoded)
                {
                    TInt leadByteOffset = 0;
                    TInt trailingByteOffset = 1;
                    if (bTextIsUTF16ReverseEncoded)
                    {
                        leadByteOffset = 1;
                        trailingByteOffset = 0;
                    }
                    for (TInt i = 0; i < (TInt)lTextLenInChars ; i++)
                    {
                        pHBufUTF16Text->Des()[i] =
                                ((UINT16)(pUnconvertedText[
                                    (i*2)+leadByteOffset])) <<8 |
                                pUnconvertedText[
                                    (i*2)+trailingByteOffset];
                    }
                }
                else
                {
                    pHBufUTF8Text = HBufC8::NewMax((TInt)lTextLenInChars);
                    for (TInt i = 0; i < (TInt)lTextLenInChars ; i++) 
                    {
                        pHBufUTF8Text->Des()[i] =
                                (UINT8)(pUnconvertedText[i]);
                    }
                    TInt kErr =
                            CnvUtfConverter::ConvertToUnicodeFromUtf8(
                            pHBufUTF16Text->Des(),
                            pHBufUTF8Text->Des() );

                    delete pHBufUTF8Text;
                }

                // /Now step through UTF-16 chars in pHBufUTF16Text:
                const TInt iStrLen16 = pHBufUTF16Text->Length();
                HX_ASSERT(iStrLen16);
                if (iStrLen16)
                {
                    TInt tiChars = 0;
                    TInt tiNewlines = 0;
                    UINT16 ch16 =
                            pHBufUTF16Text->Des()[tiChars];
                    BOOL bPriorCharWasCarriageReturn = FALSE;
                    BOOL bCurCharIsCarriageReturn = FALSE;
                    BOOL bCurCharIsAtomicNewline = FALSE;
                    // /First, skip newline chars at the start:
                    while (tiChars < iStrLen16  &&
                            isUTF16NewlineChar(ch16,
                            bPriorCharWasCarriageReturn,
                            /*REF*/ bCurCharIsCarriageReturn,
                            /*REF*/ bCurCharIsAtomicNewline) )
                    {
                        tiChars++;
                        // /If it's not LF of CRLF, then ++ newlines:
                        if (bCurCharIsAtomicNewline)
                        {
                            tiNewlines++;
                        }
                        if (tiChars >= iStrLen16)
                        {
                            break;
                        }
                        ch16 = pHBufUTF16Text->Des()[tiChars];
                        bPriorCharWasCarriageReturn =
                                bCurCharIsCarriageReturn;
                    }

                    m_lNumUTF16NewlinesAtStart = (INT16)tiNewlines;
                    m_lNumUTF16NewlineCharsAtStart = (INT16)tiChars;

                    // /Next, find any newline chars in the middle:
                    bPriorCharWasCarriageReturn = FALSE;
                    while (tiChars < iStrLen16)
                    {
                        ch16 = pHBufUTF16Text->Des()[tiChars];
                        if (isUTF16NewlineChar(ch16,
                                bPriorCharWasCarriageReturn,
                                /*REF*/ bCurCharIsCarriageReturn,
                                /*REF*/ bCurCharIsAtomicNewline))
                        {
                            // /Start a new TextContainer at this
                            // newline char:
                            m_uiUnpackedEndCharOffset = tiChars +
                                    // /Add offset to get it back into
                                    // proper coords:
                                    m_uiUnpackedStartCharOffset;
                            break;
                        }
                        bPriorCharWasCarriageReturn =
                                bCurCharIsCarriageReturn;
                        tiChars++;
                    }

                }
            }
        }
#else  // / else not _SYMBIAN                                                  ------------------------------------
        if (bNeedToBreakTCsUpAtNewlines)
        {
            const char* pTextOfThis = m_pTextSample->GetText() + m_uiUnpackedStartCharOffset;
            HX_ASSERT(pTextOfThis); // /Asserted? notify ehodge@real.com w/.3gp content
            if (pTextOfThis)
            {
                UINT16 uiLen = GetTextByteLength();
#pragma message("&&&& XXXEH- 20031027- check for UTF8 or UTF16; if 16, step by 2's. If 8... &&&&")
                BOOL bIsReverseUTF16 = FALSE;
                BOOL bIsUTF16 = IsUTF16Encoded(pTextOfThis,
                        (INT32)uiLen, bIsReverseUTF16);
                const UCHAR* pStepper = pTextOfThis;
                // /First, skip newline chars at the start:
                while (('\r' == *pStepper  ||  '\n' == *pStepper)  &&
                        pStepper < pTextOfThis + uiLen)
                {
                    pStepper++;
                }
                // /Next, find any newline chars in the middle:
                do
                {
                    if ('\r' == *pStepper  ||  '\n' == *pStepper)
                    {
                        // /Start a new TextContainer at this newline char:
                        m_uiUnpackedEndCharOffset = pStepper - pTextOfThis +
                                // /Need offset to get back into proper coords:
                                m_uiUnpackedStartCharOffset;
                        break;
                    }
                } while (++pStepper < pTextOfThis + uiLen);
            }
        }
#endif // /if _SYMBIAN else...                                                 _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
    }
//-----------------------------------------------------------------------------
    

cleanup:

    uiREFIndexOfLastChar = m_uiUnpackedEndCharOffset;

    return hxr;
}


C3GPPTextContainer::C3GPPTextContainer() 
: m_pPacket(NULL)
, m_pTextSample(NULL)
, m_uiUnpackedStartCharOffset(HX_3GPPTT_INVALID_INDEX)
, m_uiUnpackedEndCharOffset(HX_3GPPTT_INVALID_INDEX)
, m_uiTextStyleBoxIndex(HX_3GPPTT_INVALID_INDEX)
, m_uiTextKaraokeBoxIndex(HX_3GPPTT_INVALID_INDEX)
, m_pTextStyleBox(NULL)
, m_pTextHighlightBox(NULL)
, m_pTextHilightColorBox(NULL)
, m_pTextKaraokeBox(NULL)
, m_pTextScrollDelayBox(NULL)
, m_pTextHyperTextBox(NULL)
, m_pTextboxBox(NULL)
, m_pTextBlinkBox(NULL)
, m_ulBeginTime(HX_3GPPTT_INVALID_TIME)
, m_ulEndTime(HX_3GPPTT_INVALID_TIME) 
, m_ulNextDrawUpdateTimeOffset(0)
, m_ulPrevDrawUpdateTimeOffset(HX_3GPPTT_INVALID_TIME)
, m_lNumUTF16NewlineCharsAtStart(HX_3GPPTT_INVALID_INT16)
, m_lNumUTF16NewlinesAtStart(HX_3GPPTT_INVALID_INT16)
{
    m_BoundingRectOfInitialDraw.left = m_BoundingRectOfInitialDraw.right = 0;
    m_BoundingRectOfInitialDraw.top = m_BoundingRectOfInitialDraw.bottom = 0;

    
}

C3GPPTextContainer::~C3GPPTextContainer()
{
    HX_RELEASE(m_pPacket);
    HX_DELETE(m_pTextSample);
    HX_DELETE(m_pTextStyleBox);
    HX_DELETE(m_pTextHighlightBox);
    HX_DELETE(m_pTextHilightColorBox);
    HX_DELETE(m_pTextKaraokeBox);
    HX_DELETE(m_pTextScrollDelayBox);
    HX_DELETE(m_pTextHyperTextBox);
    HX_DELETE(m_pTextboxBox);
    HX_DELETE(m_pTextBlinkBox);
}


BOOL
C3GPPTextContainer::ContainsPoint(INT16 iX, INT16 iY) const
{
    return (   iX >= m_BoundingRectOfInitialDraw.left   &&
           iX <= m_BoundingRectOfInitialDraw.right  &&
           iY >= m_BoundingRectOfInitialDraw.top    &&
           iY <= m_BoundingRectOfInitialDraw.bottom);
}


HX_RESULT
C3GPPTextContainer::UpdateLowestPotentialNextTCStartOffset(
        UINT16 uiCurStartCharOffset, UINT16 uiCurEndCharOffset,
        UINT16& /*REF IN-&-OUT*/ uiLowestPotentialNextTCStartOffsetFound,
        BOOL&   /*REF OUT*/ bAssignBoxToCurrent)
{
    bAssignBoxToCurrent = FALSE; // /Initialize.

    // /Error if start is after end or even if they are equal since indices
    // are end-point exclusive:
    if (uiCurStartCharOffset >= uiCurEndCharOffset)
    {
        // /Don't bother asserting; it's a bad test file (3GPPtext-e-06-00.3gp)
        return HXR_UNEXPECTED; // /BAD DATA!
    }

    // /To avoid crash @ draw time w/corrupt data, make sure these don't
    // exceed the complete buffer's size:
    if (uiCurStartCharOffset > m_pTextSample->GetTextLenInBytes()  ||
            uiCurEndCharOffset > m_pTextSample->GetTextLenInBytes())
    {
        HX_ASSERT(uiCurStartCharOffset > m_pTextSample->GetTextLenInBytes());
        HX_ASSERT(uiCurEndCharOffset > m_pTextSample->GetTextLenInBytes());
        return HXR_UNEXPECTED; // /Ignore this entry.
    }
    if (m_uiUnpackedStartCharOffset >= uiCurStartCharOffset  &&
            uiCurEndCharOffset > // /(end-pt exclusive)
            m_uiUnpackedStartCharOffset)
    {
        bAssignBoxToCurrent = TRUE; // /this's begin is within current range

        HX_ASSERT(uiLowestPotentialNextTCStartOffsetFound >= uiCurEndCharOffset);
        if (uiLowestPotentialNextTCStartOffsetFound > uiCurEndCharOffset)
        {
            // /Don't add 1 here; it's end-point exclusive:
            uiLowestPotentialNextTCStartOffsetFound = uiCurEndCharOffset;
        }
    }
    // /Use start as potential end if lowest so far:
    else if (uiCurStartCharOffset < uiLowestPotentialNextTCStartOffsetFound  &&
            // /Ignore if prior to our start:
            uiCurStartCharOffset >= m_uiUnpackedStartCharOffset)
    {
        uiLowestPotentialNextTCStartOffsetFound = uiCurStartCharOffset;
        // /I think the logic of the if(), above,
        // handles this but I'm too lazy to check:
        HX_ASSERT(0 != uiLowestPotentialNextTCStartOffsetFound);
    }

    return HXR_OK;
}


UINT32
C3GPPTextContainer::GetNextActivityTime() const
{
    UINT32 ulBegin = GetBeginTime();
    if (HX_3GPPTT_INVALID_TIME == ulBegin)
    {
        return ulBegin;
    }
    return (m_ulNextDrawUpdateTimeOffset + ulBegin);
}


UINT32
C3GPPTextContainer::GetPrevActivityTime() const
{
    UINT32 ulBegin = GetBeginTime();
    if (HX_3GPPTT_INVALID_TIME == ulBegin  ||
            HX_3GPPTT_INVALID_TIME == m_ulPrevDrawUpdateTimeOffset)
    {
        return HX_3GPPTT_INVALID_TIME;
    }
    return (m_ulPrevDrawUpdateTimeOffset + ulBegin);
}

void
C3GPPTextContainer::SetPrevActivityTime(UINT32 ulAbsoluteTime)
{
    UINT32 ulBegin = GetBeginTime();
    if (HX_3GPPTT_INVALID_TIME == ulBegin  ||  ulBegin > ulAbsoluteTime)
    {
        m_ulPrevDrawUpdateTimeOffset = HX_3GPPTT_INVALID_TIME;
    }
    else
    {
        m_ulPrevDrawUpdateTimeOffset = ulAbsoluteTime - ulBegin;
    }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?