3gppttrenderer.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:167k
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: RCSL 1.0/RPSL 1.0
- *
- * Portions Copyright (c) 1995-2003 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file, are
- * subject to the current version of the RealNetworks Public Source License
- * Version 1.0 (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the RealNetworks Community Source License Version 1.0
- * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
- * in which case the RCSL will apply. You may also obtain the license terms
- * directly from RealNetworks. You may not use this file except in
- * compliance with the RPSL or, if you have a valid RCSL with RealNetworks
- * applicable to this file, the RCSL. Please see the applicable RPSL or
- * RCSL for the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the portions
- * it created.
- *
- * This file, and the files included with this file, is distributed and made
- * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- /****************************************************************************
- * Defines
- */
- #define INITGUID /* Interface ID's */
- #if !defined(STRICT)
- #define STRICT
- #endif
- /****************************************************************************
- * Includes
- */
- #include "hxtypes.h"
- #include <stdlib.h>
- #include <ctype.h>
- #include <stdio.h>
- #include <string.h> // /for memset, strncmp, stricmp
- #if defined(_SYMBIAN) // / -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
- #include <gdi.h> // /For CFont, TFontSpec, CGraphicsDevice, ...etc.
- #include <utf.h> // /For CnvUtfConverter::ConvertToUnicodeFromUtf8();
- #include <coecntrl.h>
- #include <fbs.h> // /For CFbsBitmap
- #include <eikenv.h>
- #endif // /_SYMBIAN _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
- #if defined(_WINDOWS) // / -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
- #include <windows.h>
- #include "platform\win\resource.h"
- #endif // /_WINDOWS _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
- #if defined(_UNIX) && (!(defined(_BEOS)))
- #include <stdlib.h>
- #include <unistd.h>
- #include <X11/Intrinsic.h>
- #include <X11/StringDefs.h>
- #include <X11/Shell.h>
- #include <X11/Xaw/Label.h>
- #endif
- #include "hxwintyp.h"
- #include "hxevent.h"
- #include "hxcom.h"
- #include "hxcomm.h"
- #include "chxpckts.h"
- #include "baseobj.h"
- #include "hxfiles.h"
- #include "hxcore.h"
- #include "hxrendr.h"
- #include "hxhyper.h"
- #include "hxplugn.h"
- #include "hxwin.h"
- #include "hxasm.h"
- #include "hxver.h"
- #include "hxvsurf.h"
- #include "hxslist.h"
- #include "hxtick.h" //for HX_GET_BETTERTICKCOUNT()
- #include "rule2flg.h" // /For RuleToFlagMap
- #include "3gppttstructs.h"
- #include "3gppttutils.h"
- #include "3gppttrenderer.h"
- #include "3gppttrenderer.ver"
- #include "hxheap.h"
- #ifdef _DEBUG
- #undef HX_THIS_FILE
- static const char HX_THIS_FILE[] = __FILE__;
- #endif
- // /#define XXXEH_DEBUGOUT_DRAW_3GPPTT
- #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
- #pragma message("====##### THIS CODE SHOULD NOT BE ENABLED IN SOURCE REPOSITORY #####====")
- static UINT32 ulCount;
- FILE* pFile = NULL;
- #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
- #if defined(_WINDOWS) // / -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
- extern HINSTANCE g_hInstance;
- COLORREF convertARGBtoWinBGRColor(UINT32 ulARGBVal)
- {
- COLORREF winColor = 0L;
- UCHAR red, green, blue;
- red = (UCHAR)(ulARGBVal>>16); //red is bytes 4,5
- green = (UCHAR)(ulARGBVal>>8); //green is 2,3
- blue = (UCHAR)ulARGBVal; //and blue is bytes 0,1
- winColor = (COLORREF)red | (COLORREF(green)<<8) |
- (COLORREF(blue)<<16);
- return winColor;
- }
- #endif // /_WINDOWS. _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
- //
- #if defined(_SYMBIAN) // / -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
- TRgb rgbBgColor;
- void convertARGBtoSymbianTrgbColor(TRgb& rgbColor,
- UINT32 ulARGBVal)
- {
- UCHAR red, green, blue;
- red = (UCHAR)(ulARGBVal>>16); //red is bytes 4,5
- green = (UCHAR)(ulARGBVal>>8); //green is 2,3
- blue = (UCHAR)ulARGBVal; //and blue is bytes 0,1
- // /TRgb is: 0x00bbggrr :
- rgbColor = (UINT32)red | (UINT32(green)<<8) |
- (UINT32(blue)<<16);
- }
- #endif // /_SYMBIAN. _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
- /****************************************************************************
- * HXCreateInstance ref: hxplugn.h
- *
- * This routine creates a new instance of the C3GPPTimedTextRenderer class.
- * It is called when the Helix core application is launched, and whenever
- * a stream associated with this plug-in needs to be rendered.
- */
- STDAPI
- ENTRYPOINT(HXCREATEINSTANCE)(IUnknown** ppIUnknown)
- {
- *ppIUnknown = (IUnknown*)(IHXPlugin*)new C3GPPTimedTextRenderer();
- if (*ppIUnknown)
- {
- (*ppIUnknown)->AddRef();
- return HXR_OK;
- }
- return HXR_OUTOFMEMORY;
- }
- /****************************************************************************
- *
- * Function:
- *
- * CanUnload2()
- *
- * Purpose:
- *
- * Function implemented by all plugin DLL's if it returns HXR_OK
- * then the pluginhandler can unload the DLL
- *
- */
- STDAPI ENTRYPOINT(CanUnload2)(void)
- {
- return ((CHXBaseCountingObject::ObjectsActive() > 0) ?
- HXR_FAIL : HXR_OK);
- }
- /****************************************************************************
- * C3GPPTimedTextRenderer static variables ref: 3gppttrender.h
- *
- * These variables are passed to the Helix core to provide information about
- * this plug-in. They are required to be static in order to remain valid
- * for the lifetime of the plug-in.
- */
- const char* const C3GPPTimedTextRenderer::zm_pDescription = "3GPP Timed Text Renderer Plugin";
- const char* const C3GPPTimedTextRenderer::zm_pCopyright = HXVER_COPYRIGHT;
- const char* const C3GPPTimedTextRenderer::zm_pMoreInfoURL = HXVER_MOREINFO;
- const char* const C3GPPTimedTextRenderer::zm_pStreamMimeTypes[] = {"video/X-RN-3GPP-TEXT", NULL};
- /****************************************************************************
- * IHXPlugin::GetPluginInfo ref: hxplugn.h
- *
- * This routine returns descriptive information about the plug-in, most
- * of which is used in the About box of the user interface. It is called
- * when the Helix core application is launched.
- */
- STDMETHODIMP
- C3GPPTimedTextRenderer::GetPluginInfo
- (
- REF(BOOL) /*OUT*/ bLoadMultiple,
- REF(const char*) /*OUT*/ pDescription,
- REF(const char*) /*OUT*/ pCopyright,
- REF(const char*) /*OUT*/ pMoreInfoURL,
- REF(UINT32) /*OUT*/ ulVersionNumber
- )
- {
- bLoadMultiple = TRUE;
- pDescription = zm_pDescription;
- pCopyright = zm_pCopyright;
- pMoreInfoURL = zm_pMoreInfoURL;
- ulVersionNumber = TARVER_ULONG32_VERSION;
- return HXR_OK;
- }
- /****************************************************************************
- * IHXRenderer::GetRendererInfo ref: hxrendr.h
- *
- * This routine returns crucial information required to associate this
- * plug-in with a given stream MIME type. This information tells the Helix
- * core which Renderer to use to display a particular type of stream. This
- * method is called when the Helix core application is launched.
- */
- STDMETHODIMP
- C3GPPTimedTextRenderer::GetRendererInfo
- (
- REF(const char**) /*OUT*/ pStreamMimeTypes,
- REF(UINT32) /*OUT*/ unInitialGranularity
- )
- {
- pStreamMimeTypes = (const char**)zm_pStreamMimeTypes;
- // /XXXEH- todo: adjust this on the fly when scrolling is happening;
- // scrollrate can change over time:
- unInitialGranularity = 50; // OnTimeSync() every 50ms
- return HXR_OK;
- }
- /****************************************************************************
- * IHXPlugin::InitPlugin ref: hxplugn.h
- *
- * This routine performs initialization steps such as determining if
- * required interfaces are available. It is called when the Helix core
- * application is launched, and whenever a stream associated with this
- * plug-in needs to be rendered.
- */
- STDMETHODIMP
- C3GPPTimedTextRenderer::InitPlugin(IUnknown* /*IN*/ pContext)
- {
- m_pContext = pContext;
- m_pContext->AddRef();
- m_pContext->QueryInterface(IID_IHXHyperNavigate, (void**) &m_pHyperNavigate);
- m_pContext->QueryInterface(IID_IHXCommonClassFactory,(void**)&m_pCommonClassFactory);
- #if defined(HELIX_3GPPTT_USE_STATUS_BAR)
- m_pContext->QueryInterface(IID_IHXStatusMessage, (void**)&m_pStatusMessage);
- #endif /* HELIX_3GPPTT_USE_STATUS_BAR */
- return HXR_OK;
- }
- /****************************************************************************
- * IHXRenderer::StartStream ref: hxrendr.h
- *
- * The Helix core calls this routine to provide access to the stream and
- * player. It is called when the plug-in is being initialized.
- */
- STDMETHODIMP
- C3GPPTimedTextRenderer::StartStream
- (
- IHXStream* pStream,
- IHXPlayer* pPlayer
- )
- {
- m_pStream = pStream;
- m_pPlayer = pPlayer;
- if (m_pStream ) m_pStream->AddRef();
- if (m_pPlayer ) m_pPlayer->AddRef();
- #if defined (HELIX_FEATURE_MISU)
- m_pCommonClassFactory->CreateInstance(CLSID_IHXMultiInstanceSiteUserSupplier,
- (void**)&m_pMISUS);
- if (m_pMISUS)
- {
- m_pMISUS->SetSingleSiteUser((IUnknown*)(IHXSiteUser*) this);
- }
- #endif //HELIX_FEATURE_MISU
- if (m_pStream)
- {
- IHXStreamSource* pSource = 0;
- if (m_pStream->GetSource(pSource) == HXR_OK)
- {
- /* It is OK if the source does not support backchannel. Reasons:
- *
- * 1. This stream may not be coming from the MP4/3GPP fileformat.
- * It may instead be merged into a container fileformat which
- * maybe does not support BackChannel.
- *
- * 2. The protocol used to serve this stream may not support
- * BackChannel.
- */
- pSource->QueryInterface(IID_IHXBackChannel, (void**) &m_pBackChannel);
-
- pSource->Release();
- }
- /* Is ASM supported on this stream? */
- m_pStream->QueryInterface(IID_IHXASMStream, (void**) &m_pASMStream);
- }
- return HXR_OK;
- }
- /****************************************************************************
- * IHXRenderer::OnHeader ref: hxrendr.h
- *
- * This routine is passed the stream header object created by the associated
- * file format plug-in. Use the methods defined in the IHXValues interface
- * to access the stream header data. This method is called from the Helix
- * core when the plug-in is being initialized.
- */
- STDMETHODIMP
- C3GPPTimedTextRenderer::OnHeader(IHXValues* pHeader)
- {
- HX_RESULT hxrslt = HXR_OK;
- IHXBuffer* pRuleToFlagMapValue = NULL;
- UINT32 ulRegionWidth = 0;
- UINT32 ulRegionHeight = 0;
- UINT32 ulTransformX = 0;
- UINT32 ulTransformY = 0;
- // Keep this for later use...
- m_pHeader = pHeader;
- m_pHeader->AddRef();
- m_pHeader->GetPropertyULONG32("duration", m_ulDuration);
- HX_RESULT hxGetPropRslt = HXR_OK;
- // /Get this from numEntries of RuleToFlagMap that is "OpaqueData" buffer (below)
- if (HXR_OK == pHeader->GetPropertyBuffer(HX_3GPPTT_RULE_TO_FLAG_MAP_PROPERTY,
- pRuleToFlagMapValue))
- {
- m_pRuleToFlagMap = new RuleToFlagMap;
- if (m_pRuleToFlagMap)
- {
- m_pRuleToFlagMap->unpack(pRuleToFlagMapValue->GetBuffer(),
- pRuleToFlagMapValue->GetSize());
- }
- }
- HX_RELEASE(pRuleToFlagMapValue);
- hxGetPropRslt = m_pHeader->GetPropertyBuffer("OpaqueData",
- m_p3GPPTextSampleEntryPackedArray);
- HX_ASSERT(HXR_OK==hxGetPropRslt && m_p3GPPTextSampleEntryPackedArray);
- if (HXR_OK == hxGetPropRslt && m_p3GPPTextSampleEntryPackedArray)
- {
- const UINT8* pData = m_p3GPPTextSampleEntryPackedArray->GetBuffer();
-
- // /The first byte is the 'stsd's version, the next 3 bytes are the
- // 'stsd's flags, and the next 4 bytes are the entryCount
- pData+=(1+3); // /Skip past the version and the flags.
- m_ulNumTextSampleEntries = ReadUL32(pData);
-
- HX_ASSERT(m_ulNumTextSampleEntries > 0);
- HX_ASSERT(0 == m_textSampleEntries.GetCount());
- hxrslt = m_textSampleEntries.Reset(m_ulNumTextSampleEntries);
- if(SUCCEEDED(hxrslt))
- {
- // create table of sample entries
- for (UINT32 ulSampleIndx = 0; ulSampleIndx < m_ulNumTextSampleEntries; ulSampleIndx++)
- {
- C3GPPTextSampleEntry* pEntry = new C3GPPTextSampleEntry();
- if( !pEntry )
- {
- hxrslt = HXR_OUTOFMEMORY;
- goto cleanup;
- }
- hxrslt = pEntry->Build(pData);
- if(FAILED(hxrslt))
- {
- HX_DELETE(pEntry);
- goto cleanup;
- }
- m_textSampleEntries[ulSampleIndx] = pEntry;
- }
- }
- }
- // /_______________________________________________________________
- // /
- // /Get the media's native width and height:
- m_pHeader->GetPropertyULONG32("3GPPTextTrackWidth", ulRegionWidth);
- m_pHeader->GetPropertyULONG32("3GPPTextTrackHeight", ulRegionHeight);
- // /This is the offset from the text window's origin:
- m_pHeader->GetPropertyULONG32("3GPPTextTrackTransformX", ulTransformX);
- m_pHeader->GetPropertyULONG32("3GPPTextTrackTransformY", ulTransformY);
- m_originTransformXY.x = (INT32)ulTransformX;
- m_originTransformXY.y = (INT32)ulTransformY;
- m_size.cx = (INT32)ulRegionWidth;
- m_size.cy = (INT32)ulRegionHeight;
-
- // /_______________________________________________________________
- // /
- // /Set up the offscreen draw buffer:
- hxrslt = CreateOffscreenBuffer(m_size);
- // /_______________________________________________________________
- // /
-
- cleanup:
- return hxrslt;
- }
- /****************************************************************************
- * IHXRenderer::OnBegin ref: hxrendr.h
- *
- * This routine is called by the Helix core to inform the Renderer that
- * playback has just begun or has been resumed. The stream's time value just
- * after resuming the playback is provided.
- */
- STDMETHODIMP
- C3GPPTimedTextRenderer::OnBegin(UINT32 ulTime)
- {
- return HXR_OK;
- }
- /****************************************************************************
- * IHXRenderer::GetDisplayType ref: hxrendr.h
- *
- * This routine returns the preferred display type of the Renderer. Any
- * other additional information necessary for the display can also be
- * provided. This method is called by the Helix core when the plug-in is being
- * initialized.
- */
- STDMETHODIMP
- C3GPPTimedTextRenderer::GetDisplayType
- (
- REF(HX_DISPLAY_TYPE) ulFlags,
- REF(IHXBuffer*) pBuffer
- )
- {
- ulFlags = HX_DISPLAY_WINDOW;
- return HXR_OK;
- }
- /****************************************************************************
- * IHXRenderer::OnPacket ref: hxrendr.h
- *
- * This routine is passed the packet object streamed by the associated
- * file format plug-in. It is called by the Helix core when a packet is due
- * to be delivered. In most cases, the actual rendering of the packet is
- * done in this method. The stream's time offset with respect to the master
- * timeline is provided.
- */
- STDMETHODIMP
- C3GPPTimedTextRenderer::OnPacket
- (
- IHXPacket* pPacket,
- INT32 lTimeOffset
- )
- {
- #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
- pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
- if (pFile)
- {
- fprintf(pFile, "[OnPacket] at %ldtlTimeOffset=%ldtpktContentTime=%ldtpktTime=%ldt%st%sn",
- HX_GET_BETTERTICKCOUNT(), lTimeOffset,
- pPacket? GetPacketContentTime(pPacket):0xFFFFFFFF,
- pPacket?pPacket->GetTime():0xFFFFFFFF,
- m_bInSeekMode?"Skipped: m_bInSeekMode=TRUE":"",
- m_bGotAllPacketsAlready?"Skipped: m_bGotAllPacketsAlready=TRUE":"");
- fclose(pFile);
- }
- ulCount++;
- #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
- HX_RESULT hxrslt = HXR_OK;
- /* Ignore pre-seek packets. Some renderers may want to use them though */
- if (m_bInSeekMode)
- {
- return hxrslt;
- }
- // /If we have all packets already, then we're receiving resends after a
- // seek and we don't need the data resent because we store it all:
- if (m_bGotAllPacketsAlready)
- {
- return hxrslt;
- }
- // Release the last packet if we had one...
- if (m_pLatestPacket)
- {
- HX_RELEASE(m_pLatestPacket);
- }
- // Keep this one for later use...
- m_pLatestPacket = pPacket;
- BOOL bFirstPkt = FALSE;
- if (m_pLatestPacket)
- {
- m_pLatestPacket->AddRef();
- if (!m_pTextContainerList)
- {
- bFirstPkt = TRUE;
- m_pTextContainerList = new CHXSimpleList();
- if (!m_pTextContainerList)
- {
- hxrslt = HXR_OUTOFMEMORY;
- }
- }
- if (HXR_OK == hxrslt)
- {
- LISTPOSITION plistPosOfFirstTxtCntnr = NULL;
- HandleNewText(m_pLatestPacket, plistPosOfFirstTxtCntnr);
- if (bFirstPkt)
- {
- m_pTextContainerListFutureTimePos =
- m_pTextContainerList->GetHeadPosition();
- }
- else
- {
- // /Not first packet, but it points past end of list,
- // so point it to last in list:
- if (!m_pTextContainerListFutureTimePos)
- {
- HX_ASSERT(plistPosOfFirstTxtCntnr);
- // /Use first of HandleNewText()'s TC's, not last:
- m_pTextContainerListFutureTimePos = plistPosOfFirstTxtCntnr;
- if (NULL == m_pTextContainerListFutureTimePos)
- {
- // /Use tail if no T.C. was created from this new pkt:
- m_pTextContainerListFutureTimePos =
- m_pTextContainerList->GetTailPosition();
- }
- }
- // /Now go through prior packet's T.C.'s and establish their
- // end times (which == m_pLatestPacket->GetRTPTime() ):
- SetPriorPacketTCsEndTimes();
- }
- }
- // /#define DUMP_3GPPTEXT_PACKET_CONTENTS
- #if defined(DUMP_3GPPTEXT_PACKET_CONTENTS)
- #if !defined(_DEBUG)
- #pragma message("====##### ***RELEASE BUILD: THIS TEST CODE SHOULD BE #####====")
- #pragma message("====##### ifdef'd OUT BEFORE BEING CHECKED IN #####====")
- #endif
- {
- static UINT32 ulPktNum = 0;
- FILE* pFile = fopen("c:\3gppttdump.txt", ulPktNum?"a+":"w");
- if (pFile)
- {
- IHXBuffer* pBuff = pPacket->GetBuffer();
- char* pText = pBuff? (char*)pBuff->GetBuffer() : "[NULL]";
- fprintf(pFile, "packet t%lunpkt timet%lunpacket content timet"
- "%luncur time%lunsize t%dncontentst{{{[len=%u]%s}}}nn",
- ulPktNum, pPacket->GetTime(), GetPacketContentTime(
- m_pLatestPacket), m_ulTimeOfLastTimeSync,
- pPacket->GetBuffer()->GetSize(),
- ((*pText)<< 8)|(*(pText+1)), &pText[2]);
- fclose(pFile);
- }
- ulPktNum++;
- }
- #endif
- }
- // NOTE: If this stream has been offset in time due to start, end, or
- // groupstart properties on the stream, packets will need to be adjusted
- // before comparing against the time line. The following code determines
- // the offset of this packet's delivery time in the real timeline.
- UINT32 ulPacketContentTime = GetPacketContentTime(pPacket);
- UINT32 ulRealContentTime;
-
- if ((UINT32)lTimeOffset > ulPacketContentTime)
- {
- ulRealContentTime = 0;
- }
- else
- {
- ulRealContentTime = ulPacketContentTime - lTimeOffset;
- }
- m_ulLastPacketTime = ulPacketContentTime;
- m_ulLastRealPacketTime = ulRealContentTime;
- return hxrslt;
- }
- /****************************************************************************
- * IHXRenderer::OnTimeSync ref: hxrendr.h
- *
- * This routine is called by the Helix core periodically passing the current
- * playback time. The Renderer should use this time value to synchronize the
- * playback of various streams.
- */
- STDMETHODIMP
- C3GPPTimedTextRenderer::OnTimeSync(UINT32 ulTime)
- {
- // Here's a good time to actually render the data!
- // Remember the time we are!
- m_ulTimeOfLastTimeSync = ulTime;
- BOOL bForceDraw = FALSE;
- C3GPPTextContainer* pTextContainer = NULL;
- // /Find out if any begin time was hit:
- if (m_pTextContainerList && m_pTextContainerListFutureTimePos)
- {
- pTextContainer = (C3GPPTextContainer*)
- m_pTextContainerList->GetAt(m_pTextContainerListFutureTimePos);
- #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
- pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
- if (pFile)
- {
- fprintf(pFile, "[OnTimeSync - 1] T.C. = %p, begin time=%lu, at time %lu, "
- "m_pTextContainerListFutureTimePos=%xn", pTextContainer,
- pTextContainer->GetBeginTime(), ulTime, m_pTextContainerListFutureTimePos);
- fclose(pFile);
- }
- ulCount++;
- #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
- if (pTextContainer &&
- // /XXXEH- handle possible time-offset!:
- pTextContainer->GetBeginTime() <= ulTime &&
- pTextContainer->GetEndTime() > ulTime)
- {
- bForceDraw = TRUE;
- }
- }
- // /No new ones need drawing? Then see if any current ones need redrawing
- // due to scrolling or blinking:
- if (!bForceDraw && m_pTextContainerRedrawList &&
- m_pTextContainerRedrawList->GetCount())
- {
- pTextContainer = (C3GPPTextContainer*)
- m_pTextContainerRedrawList->GetHead();
- #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
- pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
- if (pFile)
- {
- fprintf(pFile, "[OnTimeSync - 2] T.C. = %p (begin=%lu,tend=%lu,t"
- "nextActive=%lu)tat time %lutm_pTextContainerListFutureTimePos=%pn",
- pTextContainer, pTextContainer->GetBeginTime(),
- pTextContainer->GetEndTime(), pTextContainer->GetNextActivityTime(),
- m_ulTimeOfLastTimeSync, m_pTextContainerListFutureTimePos);
- fclose(pFile);
- }
- ulCount++;
- #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
- if (pTextContainer &&
- // /XXXEH- handle possible time-offset!
- pTextContainer->GetNextActivityTime() <= ulTime)
- {
- bForceDraw = TRUE;
- }
- }
- if (bForceDraw)
- {
- UpdateDisplay(ulTime);
- // Draw the new text by damaging the entire area of our data
- HXxRect damageRect = {0, 0, m_size.cx, m_size.cy };
- m_pMISUSSite->DamageRect(damageRect);
- m_pMISUSSite->ForceRedraw();
- }
- return HXR_OK;
- }
- /****************************************************************************
- * IHXRenderer::OnPreSeek ref: hxrendr.h
- *
- * This routine is called by the Helix core before a seek is about to occur.
- * The stream's time value just before the seek, and the time value just
- * after the seek are provided.
- */
- STDMETHODIMP
- C3GPPTimedTextRenderer::OnPreSeek(UINT32 ulOldTime, UINT32 ulNewTime)
- {
- #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
- pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
- if (pFile)
- {
- fprintf(pFile, "[OnPreSeek] at %ldtulNewTime=%lu,tulOldTime=%lu,n",
- HX_GET_BETTERTICKCOUNT(), ulOldTime, ulNewTime);
- fclose(pFile);
- }
- ulCount++;
- #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
- m_bInSeekMode = TRUE;
- return HXR_OK;
- }
- /****************************************************************************
- * IHXRenderer::OnPostSeek ref: hxrendr.h
- *
- * This routine is called by the Helix core just after a seek has occured.
- * The stream's time value just before the seek, and the time value just
- * after the seek are provided.
- */
- STDMETHODIMP
- C3GPPTimedTextRenderer::OnPostSeek(UINT32 ulOldTime, UINT32 ulNewTime)
- {
- #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
- pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
- if (pFile)
- {
- fprintf(pFile, "[OnPostSeek] at %ldtulNewTime=%lu,tulOldTime=%lu,n",
- HX_GET_BETTERTICKCOUNT(), ulOldTime, ulNewTime);
- fclose(pFile);
- }
- ulCount++;
- #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
- RecomputeTextContainerDrawList(ulNewTime);
- m_bInSeekMode = FALSE;
- return HXR_OK;
- }
- /****************************************************************************
- * IHXRenderer::OnPause ref: hxrendr.h
- *
- * This routine is called by the Helix core just after a pause has occured.
- * The stream's time value just before pausing is provided.
- */
- STDMETHODIMP
- C3GPPTimedTextRenderer::OnPause(UINT32 ulTime)
- {
- return HXR_OK;
- }
- /****************************************************************************
- * IHXRenderer::OnBuffering ref: hxrendr.h
- *
- * This routine is called by the Helix core to inform the Renderer that
- * buffering of data is occuring. The reason for buffering (e.g. start-up
- * of stream, seek has occured, network congestion, etc.), as well as the
- * percentage of the buffering process complete are provided.
- */
- STDMETHODIMP
- C3GPPTimedTextRenderer::OnBuffering(UINT32 ulFlags, UINT16 unPercentComplete)
- {
- #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
- pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
- if (pFile)
- {
- fprintf(pFile, "[OnBuffering] at %ldtunPercentComplete=%u",
- HX_GET_BETTERTICKCOUNT(), unPercentComplete);
- fclose(pFile);
- }
- ulCount++;
- #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
- return HXR_OK;
- }
- /****************************************************************************
- * IHXRenderer::OnEndofPackets ref: hxrendr.h
- *
- * Called by client engine to inform the renderer that all the
- * packets have been delivered. However, if the user seeks before
- * EndStream() is called, renderer may start getting packets again
- * and the client engine will eventually call this function again.
- */
- STDMETHODIMP
- C3GPPTimedTextRenderer::OnEndofPackets(void)
- {
- m_bGotAllPacketsAlready = TRUE;
- return HXR_OK;
- }
- /****************************************************************************
- * IHXRenderer::EndStream ref: hxrendr.h
- *
- * This routine is called by the Helix core when the rendering of the stream
- * has completed. Deallocation of any resources should be done here.
- */
- STDMETHODIMP
- C3GPPTimedTextRenderer::EndStream()
- {
- /* Send report of a mouse click to the fileformat if backchannel
- * is supported
- */
- if (m_pBackChannel && m_pCommonClassFactory && m_pStream)
- {
- IHXPacket* pPacket = 0;
- IHXBuffer* pBuffer = 0;
- char tmpStr[100];
- if ((HXR_OK == m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer,
- (void**)&pBuffer)) &&
- (HXR_OK == m_pCommonClassFactory->CreateInstance(CLSID_IHXPacket,
- (void**)&pPacket)))
- {
- ::sprintf(tmpStr, "Number of clicks = %lun", m_ulNumberOfClicks);
- pBuffer->Set((UCHAR*) tmpStr, ::strlen(tmpStr) + 1);
- pPacket->Set(pBuffer,0,m_pStream->GetStreamNumber(),
- HX_ASM_SWITCH_ON, 0);
- pBuffer->Release();
- m_pBackChannel->PacketReady(pPacket);
- pPacket->Release();
- }
- }
- // You can't use IHXStream, IHXSourceStream, IHXBackChannel, or
- // IHXASMStream after EndStream has been called.
- HX_RELEASE(m_pStream);
- HX_RELEASE(m_pBackChannel);
- HX_RELEASE(m_pASMStream);
- return HXR_OK;
- }
- /****************************************************************************
- * C3GPPTimedTextRenderer::ClearTextContainerLists ref: 3gppttrender.h
- *
- * Removes all contents of the list of text packets
- */
- void
- C3GPPTimedTextRenderer::ClearTextContainerLists(BOOL bDeleteListPtrWhenCleared)
- {
- if (m_pTextContainerRedrawList)
- {
- // /We don't need to delete the text containers inside since they are
- // owned by (& will be cleaned up by) the m_pTextContainerList, below:
- m_pTextContainerRedrawList->RemoveAll();
- }
- if (m_pTextContainerList)
- {
- LISTPOSITION pos = m_pTextContainerList->GetHeadPosition();
- while (pos)
- {
- C3GPPTextContainer* pTextContainer =
- (C3GPPTextContainer*)m_pTextContainerList->GetNext(pos);
- HX_ASSERT(pTextContainer);
- if (pTextContainer)
- {
- HX_DELETE(pTextContainer);
- }
- }
- m_pTextContainerList->RemoveAll();
- }
- if (bDeleteListPtrWhenCleared)
- {
- HX_DELETE(m_pTextContainerList);
- HX_DELETE(m_pTextContainerRedrawList);
- }
- }
- /****************************************************************************
- * C3GPPTimedTextRenderer::C3GPPTimedTextRenderer ref: 3gppttrender.h
- *
- * Constructor
- */
- C3GPPTimedTextRenderer::C3GPPTimedTextRenderer()
- : m_lRefCount(0)
- , m_pContext(NULL)
- , m_pStream(NULL)
- , m_pPlayer(NULL)
- , m_pHeader(NULL)
- , m_pLatestPacket(NULL)
- , m_bGotAllPacketsAlready(FALSE)
- , m_ulTimeOfLastTimeSync(HX_3GPPTT_INVALID_TIME)
- , m_ulLastPacketTime(HX_3GPPTT_INVALID_TIME)
- , m_ulLastRealPacketTime(HX_3GPPTT_INVALID_TIME)
- , m_pHyperNavigate(NULL)
- , m_pBackChannel(NULL)
- , m_pASMStream(NULL)
- , m_pCommonClassFactory(NULL)
- , m_ulNumberOfClicks(0)
- , m_bIsSubscribed(TRUE)
- , m_pMISUS(NULL)
- , m_pMISUSSite(NULL)
- , m_bInSeekMode(FALSE)
- , m_bRTPPacketTested(FALSE)
- , m_bUsesRTPPackets(FALSE)
- , m_ulDuration(0)
- , m_ulNumTextSampleEntries(0)
- , m_p3GPPTextSampleEntryPackedArray(NULL)
- , m_pTextContainerList(NULL)
- , m_pTextContainerListFutureTimePos(NULL)
- , m_pTextContainerRedrawList(NULL)
- , m_nLastMouseMoveXPos(0)
- , m_nLastMouseMoveYPos(0)
- , m_pEvent(NULL)
- , m_pDrawOutputBuffer(NULL)
- , m_ulDrawOutputBufferSizeInBytes(0)
- , m_ulBitsPerPixel(HX_3GPPTT_DEFAULT_bits_PER_PIXEL)
- , m_lXScrollOffset(0)
- , m_lYScrollOffset(0)
- , m_dScrollFactor(0.0)
- , m_bDrawInNonTextScrollArea(FALSE)
- , m_pRuleToFlagMap(NULL)
- #if defined(HELIX_3GPPTT_USE_STATUS_BAR)
- , m_pStatusMessage(NULL)
- , m_bStatusMsgWillNeedErasing(FALSE)
- , m_pszHLinkToDisplay(NULL)
- #endif // /HELIX_3GPPTT_USE_STATUS_BAR
- #if defined(_WINDOWS) // / -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
- , m_bNeedToSetHyperlinkHandCursor(FALSE)
- , m_hPreHyperlinkCursor(NULL)
- , m_hHyperlinkCursor(NULL)
- , m_pDeviceContextMemory(NULL)
- , m_pFont(NULL)
- , m_pFontOld(NULL)
- #if defined(USE_DIB_SECTION)
- , m_hBitmap(NULL)
- , m_hOldBitmap(NULL)
- , m_LPBITMAPINFO(NULL)
- #endif /* USE_DIB_SECTION */
- #elif defined(_MACINTOSH)
- , m_CurrentCursor(CURSOR_ARROW)
- , m_pOffScreenWorld(NULL)
- #elif defined(_UNIX) && (!(defined(_BEOS)))
- , m_hHyperlinkCursor(0)
- , m_bHandActivated(FALSE)
- , m_pdisp(NULL)
- , m_window(NULL)
- , m_gc(NULL)
- #elif defined(_SYMBIAN)
- , m_pBitMap(NULL)
- , m_pFont(NULL)
- , m_pScreenDevice(NULL)
- , m_pGCSite(NULL)
- , m_pGCOffscreen(NULL)
- #endif // /_WINDOWS -else- _MACINTOSH -else- (_UNIX && !_BEOS) _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
- {
- m_originTransformXY.x = m_originTransformXY.y = 0;
- m_size.cx = 0;
- m_size.cy = 0;
- memset(&m_BitmapInfoHeader, 0, sizeof(HXBitmapInfoHeader));
- #if defined(_WINDOWS) // / -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
- m_pDeviceContextMemory = (void*)CreateCompatibleDC(NULL);
- #endif // /_WINDOWS _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
- #if defined(_MACINTOSH)
- const short HAND_CURSOR = 1313;
- m_pResourceLoader = CResourceLoader::CreateInstance(g_DLLFSpec);
- m_hHyperlinkCursor = (CursHandle)m_pResourceLoader->LoadResource('CURS', HAND_CURSOR);
- #endif // /_MACINTOSH
- }
- /****************************************************************************
- * C3GPPTimedTextRenderer::~C3GPPTimedTextRenderer ref: 3gppttrender.h
- *
- * Destructor
- */
- C3GPPTimedTextRenderer::~C3GPPTimedTextRenderer()
- {
- for ( UINT32 idx = 0; idx != m_textSampleEntries.GetCount(); ++idx )
- {
- C3GPPTextSampleEntry*& pEntry = (C3GPPTextSampleEntry*&)(m_textSampleEntries[idx]);
- delete pEntry;
- }
- m_textSampleEntries.Reset(0);
- // /TRUE = delete m_pTextContainerList & m_pTextContainerRedrawList:
- ClearTextContainerLists(TRUE);
- /* Free the draw output buffer (but not w/DIB section) */
- #if !defined(USE_DIB_SECTION) && !defined(_SYMBIAN)
- if (m_pDrawOutputBuffer) // /Note: in Symbian, this points into m_pBitMap:
- {
- HX_VECTOR_DELETE(m_pDrawOutputBuffer);
- m_pDrawOutputBuffer = NULL;
- m_ulDrawOutputBufferSizeInBytes = 0;
- }
- #endif // /!USE_DIB_SECTION.
- #if defined(_WINDOWS) // / -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
- // /Free the DIB-section-only data:
- #if defined(USE_DIB_SECTION)
- if(m_hBitmap)
- {
- DeleteObject(m_hBitmap);
- }
- if(m_hOldBitmap && m_pDeviceContextMemory)
- {
- SelectObject((HDC)m_pDeviceContextMemory, m_hOldBitmap);
- }
- m_hOldBitmap = NULL;
-
- if(m_LPBITMAPINFO)
- {
- delete m_LPBITMAPINFO;
- m_LPBITMAPINFO = NULL;
- }
- #endif // /USE_DIB_SECTION.
- if(m_pDeviceContextMemory)
- {
- DeleteDC((HDC)m_pDeviceContextMemory);
- }
- #elif defined(_MACINTOSH)
- if(m_pOffScreenWorld)
- {
- DisposeGWorld(m_pOffScreenWorld);
- m_pOffScreenWorld=NULL;
- }
- #elif defined(_SYMBIAN)
- if (m_pBitMap)
- {
- HX_DELETE(m_pBitMap);
- m_pDrawOutputBuffer = NULL;
- }
- // /Discard and destroy the font:
- if (m_pFont)
- {
- if (m_pGCOffscreen)
- {
- m_pGCOffscreen->DiscardFont();
- HX_DELETE(m_pGCOffscreen);
- }
- // /m_pGCSite is not ours to delete.
- if (m_pScreenDevice)
- {
- m_pScreenDevice->ReleaseFont(m_pFont);
- }
- m_pFont = NULL;
- }
- #endif // /_WINDOWS elif _MACINTOSH elif _SYMBIAN _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
- HX_RELEASE(m_pHeader);
- HX_RELEASE(m_pLatestPacket);
- HX_RELEASE(m_pContext);
- HX_RELEASE(m_pHyperNavigate);
- #if defined(HELIX_3GPPTT_USE_STATUS_BAR)
- HX_RELEASE(m_pStatusMessage);
- HX_VECTOR_DELETE(m_pszHLinkToDisplay);
- #endif /* HELIX_3GPPTT_USE_STATUS_BAR */
- HX_RELEASE(m_pCommonClassFactory);
- HX_RELEASE(m_pPlayer);
- }
- // IHXSiteUser Interface Methods
- /****************************************************************************
- * IHXSiteUser::AttachSite ref: hxwin.h
- *
- */
- STDMETHODIMP
- C3GPPTimedTextRenderer::AttachSite(IHXSite* /*IN*/ pSite)
- {
- if (m_pMISUSSite)
- {
- return HXR_UNEXPECTED;
- }
- m_pMISUSSite = pSite;
- m_pMISUSSite->AddRef();
- m_pMISUSSite->SetSize(m_size);
-
- #if defined(_SYMBIAN) // / -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
- IHXSiteWindowed* pSiteWindowed = NULL;
- if (m_pMISUSSite->QueryInterface(IID_IHXSiteWindowed,
- (void**) &pSiteWindowed)
- == HXR_OK)
- {
- HXxWindow* pHXxWindow = pSiteWindowed->GetWindow();
- HX_ASSERT(pHXxWindow);
- if (pHXxWindow)
- {
- CDirectScreenAccess* pDirectScreen = pHXxWindow->iDSA;
- if (pDirectScreen)
- {
- m_pScreenDevice = pDirectScreen->ScreenDevice();
- if(m_pScreenDevice)
- {
- m_pGCSite = pDirectScreen->Gc();
- }
- }
- }
- }
- HX_RELEASE(pSiteWindowed);
- HX_ASSERT(m_pScreenDevice);
- HX_ASSERT(m_pGCSite);
- #endif /* _SYMBIAN */ // / _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
-
- // /XXXEH- once we get text site to same postion as video site, we can QI
- // site for IHXSite2 and then call MoveSiteToTop() to make sure it's on
- // top of the video.
- /* // /XXXEH- We need to use a site watcher to watch for TLC moving our window
- // because in RealOne player, the TLC tiles multiple sites if no explicit
- // layout exists. On mobile players, the TLC leaves everyt site at (0,0).
- HXxPoint point;
- m_pMISUSSite->GetPosition(point);
- // /XXXEH- we need to move the video to client area (0,0) so text can
- // appear on top of video as well as below. Coords of display rect of
- // 3GPP TT assumes origin of region (this site) is same as video's, but
- // our default site-layout code puts our origin at (0, video's bottom):
- point.x -= ulTransformX;
- point.y -= ulTransformY; // /XXXEH- this doesn't work; it's still Blt'ing
- // in the same place, below the vid.
- HX_RESULT hxr = m_pMISUSSite->SetPosition(point);
- m_pMISUSSite->GetPosition(point); // /TESTING: [X] returns changed-position point
- */
- return HXR_OK;
- }
- /****************************************************************************
- * IHXSiteUser::DetachSite ref: hxwin.h
- *
- */
- STDMETHODIMP
- C3GPPTimedTextRenderer::DetachSite()
- {
- HX_RELEASE(m_pMISUSSite);
- // We're done with these...
- if (m_pMISUS) m_pMISUS->ReleaseSingleSiteUser();
- HX_RELEASE(m_pMISUS);
- return HXR_OK;
- }
- /****************************************************************************
- * IHXSiteUser::NeedsWindowedSites ref: hxwin.h
- *
- */
- STDMETHODIMP_(BOOL)
- C3GPPTimedTextRenderer::NeedsWindowedSites()
- {
- return FALSE;
- };
- /****************************************************************************
- * IHXSiteUser::HandleEvent ref: hxwin.h
- *
- */
- STDMETHODIMP
- C3GPPTimedTextRenderer::HandleEvent(HXxEvent* /*IN*/ pEvent)
- {
- HX_RESULT hxrslt = HXR_OK;
- pEvent->handled = FALSE;
- pEvent->result = 0;
- #if defined(_UNIX) && (!(defined(_BEOS)))
- // XEvent* xevent = (XEvent*)pEvent->param1;
- // what is pEvent->window?
- #endif
- #if defined(_UNIX) && (!(defined(_BEOS)))
- //XXX: This assumes a single window for the duration
- if( !m_window )
- {
- m_window = (Window)pEvent->window;
- if( !m_window )
- return HXR_OK;
- }
- if( !m_gc )
- {
- XGCValues vals;
- HXxWindow *pWnd = (HXxWindow*)pEvent->param2;
- m_pdisp = (Display*)pWnd->display;
- if( !m_pdisp ) return HXR_OK;
- XFontStruct* pfs = XLoadQueryFont( m_pdisp, "6x10" );
- if( !pfs ) return HXR_OK;
- //XXX: Could use WhitePixel() and BlackPixel()
- vals.foreground = 0xffffffff;
- vals.background = 0;
- vals.font = pfs->fid;
- m_gc = XCreateGC( m_pdisp, m_window, (GCForeground|GCBackground|GCFont), &vals );
- if( !m_gc ) return HXR_OK;
- }
- #endif /* _UNIX && !_BEOS */
- switch (pEvent->event)
- {
- case HX_MOUSE_ENTER:
- case HX_MOUSE_LEAVE:
- case HX_MOUSE_MOVE:
- {
- pEvent->handled = TRUE;
- m_pEvent = pEvent;
- HXxPoint* mousePt = (HXxPoint*) pEvent->param1;
- OnMouseMove (0, (INT16)mousePt->x, (INT16)mousePt->y);
- }
- break;
- case HX_PRIMARY_BUTTON_UP:
- {
- HXxPoint* mousePt = (HXxPoint*) pEvent->param1;
- hxrslt = HandleClick(0, (INT16)mousePt->x, (INT16)mousePt->y);
- pEvent->handled = TRUE;
- }
- break;
- case HX_SURFACE_UPDATE:
- {
- m_pEvent = pEvent;
- IHXVideoSurface *pSurface = (IHXVideoSurface*) (pEvent->param1);
- HX_ASSERT(pSurface);
- if (pSurface)
- {
- hxrslt = Draw(pSurface);
- }
- pEvent->handled = TRUE;
- m_pEvent = NULL;
- }
- break;
- #if defined(_WINDOWS) // / -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
- case WM_SETCURSOR:
- {
- pEvent->handled = TRUE;
- if(m_bNeedToSetHyperlinkHandCursor)
- {
- m_hPreHyperlinkCursor = SetCursor(m_hHyperlinkCursor);
- }
- else
- {
- // /set the cursor back to arrow cursor:
- SetCursor(LoadCursor(NULL, IDC_ARROW));
- }
- }
- break;
- #endif // /_WINDOWS _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
- }
- return hxrslt;
- }
- //
- // Called to ensure cached output buffer pointer is valid before
- // we use it. On most platforms this remains constant. On Symbian
- // this can change (e.g., when menus go up).
- //
- void C3GPPTimedTextRenderer::SetDrawOutputBuffer()
- {
- #if defined(_SYMBIAN)
- m_pDrawOutputBuffer = m_pBitMap ? (UCHAR*)m_pBitMap->DataAddress() : 0;
- #endif
- }
- /****************************************************************************
- * C3GPPTimedTextRenderer::Draw ref: 3gppttrender.h
- *
- */
- HX_RESULT
- C3GPPTimedTextRenderer::UpdateDisplay(UINT32 ulTime)
- {
- HX_RESULT hxrslt = HXR_OK;
- C3GPPTextContainer* pTextContainer = NULL;
- const C3GPPTextSampleEntry* pLastHandledTextSampleEntry = NULL;
- INT32 lXScrollOffset = 0;
- INT32 lYScrollOffset = 0;
- BOOL bIsScrollingOut = FALSE;
- double dScrollFactor = 0.0;
- UINT32 ulBgColorARGB = 0x0;
- BOOL bHasNonOpaqueAlpha = FALSE;
- SetDrawOutputBuffer();
- #if defined(_WINDOWS) // / -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
- HDC hDC = (HDC)m_pDeviceContextMemory;
- #endif // /_WINDOWS _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
- #if defined(_SYMBIAN) // / -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
- HBufC16* pHBufUTF16Text = NULL;
- HBufC8* pHBufUTF8Text = NULL;
- HX_ASSERT(m_pGCSite && m_pGCOffscreen);
- if (!m_pGCSite || !m_pGCOffscreen)
- {
- hxrslt = HXR_UNEXPECTED;
- goto cleanup;
- }
- #endif // /_SYMBIAN _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
- #if !defined(USE_DIB_SECTION) /* else DIB_SECTION code below will create it */ // /-----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
- HX_ASSERT(m_pDrawOutputBuffer); // /Should have been created in OnHeader().
- if (m_pDrawOutputBuffer &&
- #else // /else USE_DIB_SECTION
- if (
- #endif // /(else of) !USE_DIB_SECTION // /_____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
- (m_pTextContainerList && m_pTextContainerListFutureTimePos)
- // /Or, maybe we're done with new text and we need to redraw
- // current text:
- || (m_pTextContainerRedrawList &&
- m_pTextContainerRedrawList->GetCount()) )
- {
- //------------- TEXT DRAWING CODE -- MOVE OUT TO X-PLAT CALL! -------
- //------------------ START TEXT PUT-GLYPHS-TO-cANVAS CODE: ---------
- INT32 liCursorX = INITIAL_CURSOR_X;
- INT32 liCursorY = INITIAL_CURSOR_Y;
- BOOL bFinishedWithCurTimeTCs = FALSE;
- UINT32 ulTextContainersHandled = 0;
- // /If we haven't yet gotten an OnTimeSync(), then don't draw anything:
- if (HX_3GPPTT_INVALID_TIME == m_ulTimeOfLastTimeSync)
- {
- goto cleanup;
- }
- // /If we find that all T.C.s from the main list (at or beyond the
- // future list pos) are all still in the future, then we might be here
- // because of some T.C. needing redrawing (for scrolling or blinking):
- BOOL bGetTextContainersFromRedrawList = FALSE;
- BOOL bTextContainerIsFromMainList = FALSE;
- BOOL bATextContainerFromMainListWasHandled = FALSE;
- UINT32 ulKaraokeHighlightStartTimeInGlobalTime = HX_3GPPTT_INVALID_TIME;
- UINT32 ulKaraokeHighlightEndTimeInGlobalTime = HX_3GPPTT_INVALID_TIME;
- do // /Go through textContainers and draw all that are valid @ present:
- {
- BOOL bReuseTCsPriorDrawRect = FALSE;
- if (!bGetTextContainersFromRedrawList &&
- NULL != m_pTextContainerListFutureTimePos)
- {
- pTextContainer = (C3GPPTextContainer*)
- m_pTextContainerList->GetAt(
- m_pTextContainerListFutureTimePos);
- HX_ASSERT(pTextContainer);
- bTextContainerIsFromMainList = TRUE;
- }
- else if (m_pTextContainerRedrawList &&
- m_pTextContainerRedrawList->GetCount())
- {
- pTextContainer = (C3GPPTextContainer*)
- m_pTextContainerRedrawList->GetHead();
- bTextContainerIsFromMainList = FALSE;
- if (pTextContainer &&
- pTextContainer->GetEndTime() <= m_ulTimeOfLastTimeSync)
- {
- // /It's too old to be redrawn (next time) so remove it
- // from the list:
- pTextContainer = NULL;
- m_pTextContainerRedrawList->RemoveHead();
- }
- }
- else
- {
- break; // /None from either list need drawing
- }
- #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
- FILE* pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
- if (pFile)
- {
- fprintf(pFile, "[step -1] T.C. = %p at time %lu (text containers "
- "handled = %ld), m_pTextContainerListFutureTimePos=%pn",
- pTextContainer, m_ulTimeOfLastTimeSync, ulTextContainersHandled,
- m_pTextContainerListFutureTimePos);
- fclose(pFile);
- }
- ulCount++;
- #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
- if (!pTextContainer || !pTextContainer->m_pPacket)
- {
- // /There should always be something to draw at any given time
- // (unless the 3GPP-TT docs are incomplete) since one packet's
- // begin time sets the end of the prior packet. (There is one
- // exception, and that is when we're drawing off the main list
- // and the next T.C. in the redraw list has been removed when
- // found (above) to be past its end time):
- HX_ASSERT(pTextContainer || !bTextContainerIsFromMainList);
- HX_ASSERT(pTextContainer? NULL!=pTextContainer->m_pPacket : 1);
- goto cleanup; // /Something's not right
- }
- /*
- #if 0 // /For testing/debugging:
- {
- IHXPacket* pTextPkt = pTextContainer->m_pPacket;
- static UINT32 ulDrawCount = 0;
- FILE* pFile = fopen("c:\3gppttdump.txt", ulDrawCount?"a+":"w");
- if (pFile)
- {
- IHXBuffer* pBuff = pTextPkt?pTextPkt->GetBuffer():NULL;
- char* pText = pBuff? (char*)pBuff->GetBuffer() : "99[NULL]";
- fprintf(pFile, "Drawct t%lunpkt timet%luncur time%lun"
- "m_pTextContainerListFutureTimePos = %pn"
- "size t%dncontentst{{{[len=%u]%s}}}nn",
- ulDrawCount, pTextPkt? pTextPkt->GetTime():9999999, m_ulTimeOfLastTimeSync,
- m_pTextContainerListFutureTimePos,
- pTextPkt? pTextPkt->GetBuffer()->GetSize():9999999,
- ((*pText)<< 8)|(*(pText+1)), &pText[2]);
- fclose(pFile);
- }
- ulDrawCount++;
- }
- #endif
- */
- #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
- pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
- if (pFile)
- {
- fprintf(pFile, "[step 0] T.C. = %p (begin=%lu,tend=%lu,tnextActive=%lu)t"
- "at time %lut(text containers handled = %ld),t"
- "m_pTextContainerListFutureTimePos=%pn", pTextContainer,
- pTextContainer->GetBeginTime(), pTextContainer->GetEndTime(),
- pTextContainer->GetNextActivityTime(), m_ulTimeOfLastTimeSync,
- ulTextContainersHandled, m_pTextContainerListFutureTimePos);
- fclose(pFile);
- }
- ulCount++;
- #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
- // /The sample entry associated with the text sample:
- const C3GPPTextSampleEntry* pCurTextSampleEntry = NULL;
- // /XXXEH- handle possible time-offset w/m_ulTimeOfLastTimeSync!
- if ( pTextContainer->GetNextActivityTime() <= m_ulTimeOfLastTimeSync &&
- pTextContainer->GetEndTime() > m_ulTimeOfLastTimeSync &&
- pTextContainer->m_pTextSample &&
- pTextContainer->m_pTextSample->GetText() &&
- pTextContainer->m_pTextSample->GetTextLenInBytes())
- {
- #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
- pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
- if (pFile)
- {
- fprintf(pFile, "[step 1] T.C. = %p at time %lu (text containers handled = "
- "%ld), m_pTextContainerListFutureTimePos=%pn", pTextContainer,
- m_ulTimeOfLastTimeSync, ulTextContainersHandled,
- m_pTextContainerListFutureTimePos);
- fclose(pFile);
- }
- ulCount++;
- #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
- bATextContainerFromMainListWasHandled =
- bTextContainerIsFromMainList;
- ulTextContainersHandled++;
- // /The sample entry associated with the text sample:
- pCurTextSampleEntry = NULL;
- // /XXXEH- todo: Maybe replace the following ~15 lines w/new pTextContainer->GetSampleDescIndex() method:
- // /Find out which sample description to associate with a text
- // sample (one per packet):
- UINT32 ulPktRuleNum = pTextContainer->GetASMRuleNumber();
- // /Initialize it to rule # (which may be wrong index), then
- // find the correct index value in the ruleToFlagMap:
- UINT32 ulAssocSampleDescIndex = ulPktRuleNum;
- HX_ASSERT(m_pRuleToFlagMap &&
- ulAssocSampleDescIndex < m_pRuleToFlagMap->num_rules);
- if (m_pRuleToFlagMap && ulAssocSampleDescIndex <
- m_pRuleToFlagMap->num_rules)
- {
- ulAssocSampleDescIndex =
- m_pRuleToFlagMap->rule_to_flag_map[ulPktRuleNum];
- }
- pCurTextSampleEntry = (const C3GPPTextSampleEntry*)
- m_textSampleEntries.GetItem(ulAssocSampleDescIndex);
- HX_ASSERT(pCurTextSampleEntry);
- ulBgColorARGB = pCurTextSampleEntry->GetBGColor();
- // /Fill background, but only if desc. differs from prev:
- if (pCurTextSampleEntry != pLastHandledTextSampleEntry
- // /...and also only if this is 1st one at this time:
- && 1 == ulTextContainersHandled
- // /...and also only if this is not a redraw due to
- // blinking; if it is, only redraw it and leave the
- // rest of the (non-blinking) text that's already
- // drawn (and still time-valid) alone:
- && bTextContainerIsFromMainList)
- {
- FillRectangle(ulBgColorARGB);
- }
- if (bTextContainerIsFromMainList)
- {
- // /This one is now in the past (hendled), so move past it:
- m_pTextContainerList->GetNext(
- m_pTextContainerListFutureTimePos);
- }
- const C3GPPStyleRecord& defStyle = pCurTextSampleEntry->GetDefaultStyle();
- UINT32 ulScaledHeight = defStyle.GetFontSize();
- UINT32 defFaceStyleFlags = defStyle.GetFaceStyleFlags();
- BOOL bIsBolded = (defFaceStyleFlags & HX_3GPPTT_FACE_STYLE_BOLD);
- BOOL bIsItalicized = (defFaceStyleFlags & HX_3GPPTT_FACE_STYLE_ITALIC);
- BOOL bIsUnderlined = (defFaceStyleFlags & HX_3GPPTT_FACE_STYLE_UNDERLINE);
- BOOL bIsStruckThrough = FALSE;
- char* pCurFontFaceString = NULL;
- UINT32 ulTextColorARGB = defStyle.GetTextColor();
- UINT32 ulTextColorARGBOld = 0;
- UINT16 uiFontID_override = HX_3GPPTT_INVALID_INDEX;
-
- // /Init to totally transparent (which means ignore it):
- UINT32 ulHighlightColorARGB = HX_3GPPTT_FULLY_TRANSPARENT;
- BOOL bHasHighlightColor = FALSE;
- if (pTextContainer->IsHyperlinked())
- {
- // /Draw text in red w/underline:
- bIsUnderlined = TRUE;
- // /Keep the alpha value but clear RGB part to red:
- ulTextColorARGB = (ulTextColorARGB & HX_3GPPTT_FULLY_TRANSPARENT) |
- HX_3GPPTT_HYPERLINK_RGB_COLOR;
- }
- if (pTextContainer->m_pTextHilightColorBox)
- {
- ulHighlightColorARGB =
- pTextContainer->m_pTextHilightColorBox->GetHighlightColor();
- if (pTextContainer->m_pTextHighlightBox)
- {
- // /Has highlight unless highlight color is fully transparent:
- bHasHighlightColor = (ulHighlightColorARGB < HX_3GPPTT_FULLY_TRANSPARENT);
- }
- }
- // /Use style overrides, if any, for this time container:
- if (HX_3GPPTT_INVALID_INDEX != pTextContainer->m_uiTextStyleBoxIndex &&
- pTextContainer->m_pTextStyleBox)
- {
-
- const C3GPPStyleRecord* pStyleRecordOverride =
- pTextContainer->m_pTextStyleBox->GetStyleRecord(
- pTextContainer->m_uiTextStyleBoxIndex);
- HX_ASSERT(pStyleRecordOverride);
- if (pStyleRecordOverride)
- {
- UINT32 flags = pStyleRecordOverride->GetFaceStyleFlags();
- bIsUnderlined = (flags & HX_3GPPTT_FACE_STYLE_UNDERLINE);
- bIsBolded = (flags & HX_3GPPTT_FACE_STYLE_BOLD);
- bIsItalicized = (flags & HX_3GPPTT_FACE_STYLE_ITALIC);
- ulTextColorARGB = pStyleRecordOverride->GetTextColor();
- ulScaledHeight = pStyleRecordOverride->GetFontSize();
- uiFontID_override = pStyleRecordOverride->GetFontID();
- }
- }
- if (HX_3GPPTT_INVALID_INDEX != pTextContainer->m_uiTextKaraokeBoxIndex &&
- pTextContainer->m_pTextKaraokeBox)
- {
- const C3GPPTextKaraokeBox::C3GPPTextKaraokeControlEntry*
- pCurKaraokeCtrlEntry =
- pTextContainer->m_pTextKaraokeBox->GetKaraokeControlEntry(
- pTextContainer->m_uiTextKaraokeBoxIndex);
- HX_ASSERT(pCurKaraokeCtrlEntry);
- if (pCurKaraokeCtrlEntry)
- {
- // /Reuse position info from last draw if this is a redraw:
- bReuseTCsPriorDrawRect = !bTextContainerIsFromMainList;
- // /Start time is end of prior highlight span; if
- // that's invalid, use highlightstart time of
- // TextKaraokeBox:
- ulKaraokeHighlightStartTimeInGlobalTime =
- ulKaraokeHighlightEndTimeInGlobalTime;
- //#error: should be: if (0 == pTextContainer->m_uiTextKaraokeBoxIndex ...(||?)
- if (HX_3GPPTT_INVALID_TIME ==
- ulKaraokeHighlightStartTimeInGlobalTime)
- {
- ulKaraokeHighlightStartTimeInGlobalTime =
- pTextContainer->GetBeginTime() +
- pTextContainer->m_pTextKaraokeBox->
- Get1stHighlightStartTime();
- }
- ulKaraokeHighlightEndTimeInGlobalTime =
- pTextContainer->GetBeginTime() +
- pCurKaraokeCtrlEntry->GetHighlightEndTime();
- // /Set text color to hightlightColor unless curtime
- // is outside of this TC's begin-end range:
- if (m_ulTimeOfLastTimeSync >=
- ulKaraokeHighlightStartTimeInGlobalTime &&
- m_ulTimeOfLastTimeSync <
- ulKaraokeHighlightEndTimeInGlobalTime)
- {
- ulTextColorARGB = ulHighlightColorARGB;
- pTextContainer->m_ulNextDrawUpdateTimeOffset =
- ulKaraokeHighlightEndTimeInGlobalTime -
- pTextContainer->GetBeginTime();
- InsertInRedrawListInTemporalOrder(pTextContainer);
- }
- else // /We're (not yet | no longer) in the highlight period:
- {
- UINT32 ulPrvActTime = pTextContainer->GetPrevActivityTime();
- // /However, if highlight has been performed
- // and then undone, remove it from redraw list
- // then skip this TC and get next...
- if (HX_3GPPTT_INVALID_TIME != ulPrvActTime)
- {
- if (m_ulTimeOfLastTimeSync >=
- ulKaraokeHighlightEndTimeInGlobalTime)
- {
- #if defined(_DEBUG)
- HX_RESULT hxrRemove =
- #endif // /_DEBUG
- RemoveFromRedrawList(pTextContainer);
- #if defined(_DEBUG)
- HX_ASSERT(HXR_OK == hxrRemove);
- #endif // /_DEBUG
- // /If we've already returned it to pre-
- // highlight color by drawing after its
- // highlight end time, then skip it now:
- if (ulPrvActTime >=
- ulKaraokeHighlightEndTimeInGlobalTime)
- {
- continue;
- }
- }
- // /...else if highlight has been done but not
- // undone yet, set next activity time to highlight
- // end time and then skip drawing this TC @ now:
- else if (ulPrvActTime >
- ulKaraokeHighlightStartTimeInGlobalTime)
- {
- // /Set next activity time in local (offset) time:
- #if defined(XXXEH_SHOW_TODO_MESSAGES)
- #pragma message("====##### XXXEH- todo: replace w/ ->setDrawUpdateTimeOffset() method #####====")
- #endif // /XXXEH_SHOW_TODO_MESSAGES.
- pTextContainer->m_ulNextDrawUpdateTimeOffset =
- ulKaraokeHighlightEndTimeInGlobalTime -
- pTextContainer->GetBeginTime();
- InsertInRedrawListInTemporalOrder(pTextContainer);
- continue;
- }
- }
- else // /Not yet drawn, so next draw will be highlight:
- // if (m_ulTimeOfLastTimeSync <
- // ulKaraokeHighlightStartTimeInGlobalTime &&
- // pTextContainer->m_ulNextDrawUpdateTimeOffset +
- // pTextContainer->GetBeginTime() !=
- // ulKaraokeHighlightStartTimeInGlobalTime)
- {
- // /Set next activity time in local (offset) time:
- #if defined(XXXEH_SHOW_TODO_MESSAGES)
- #pragma message("====##### XXXEH- todo: replace w/ ->setDrawUpdateTimeOffset() method #####====")
- #endif // /XXXEH_SHOW_TODO_MESSAGES.
- pTextContainer->m_ulNextDrawUpdateTimeOffset =
- ulKaraokeHighlightStartTimeInGlobalTime -
- pTextContainer->GetBeginTime();
- // /Call this even if pT.C.'s end is exceeded because this
- // method will remove & not reinsert it in that case:
- InsertInRedrawListInTemporalOrder(pTextContainer);
- }
- }
- }
- } // /end KaraokeBox handling.
-
- // /First see if we have a scroll offset:
- TextSampleScrollDirection scrolldir =
- pCurTextSampleEntry->getScrollDirection();
- if (scrollDirNone != scrolldir)
- {
- UINT32 ulScrollDelay = 0;
- if (pTextContainer->m_pTextScrollDelayBox)
- {
- ulScrollDelay = pTextContainer->m_pTextScrollDelayBox->GetScrollDelay();
- }
- HX_ASSERT(m_ulTimeOfLastTimeSync >= pTextContainer->GetBeginTime());
- UINT32 ulDurForThisScroll = pTextContainer->GetDuration();
- HX_ASSERT(ulDurForThisScroll > ulScrollDelay);
- if (ulDurForThisScroll <= ulScrollDelay)
- {
- ulDurForThisScroll = 1; // /Avoid div by zero, below.
- }
- else
- {
- ulDurForThisScroll -= ulScrollDelay;
- }
- UINT32 ulLocalTime = m_ulTimeOfLastTimeSync -
- pTextContainer->GetBeginTime();
- // /Handle in & out when both are active on this entry:
- bIsScrollingOut = pCurTextSampleEntry->hasScrollOut();
- if (pCurTextSampleEntry->hasScrollIn() && bIsScrollingOut)
- {
- ulDurForThisScroll /= 2; // /Use only half dur in all calcs:
- // /Find out if we're in the scroll-in (1st half) or
- // the scroll-out (2nd half) part:
- if (ulLocalTime < ulDurForThisScroll)
- {
- bIsScrollingOut = FALSE; // /In 1st half.
- }
- else
- {
- // /Get local time into 2nd-half-only coordinate space:
- ulLocalTime -= ulDurForThisScroll;
- }
- }
- if (ulScrollDelay && bIsScrollingOut)
- {
- // /Adjust local time to zero to await end of scroll delay:
- if (ulLocalTime <= ulScrollDelay)
- {
- ulLocalTime = 0;
- }
- else
- {
- ulLocalTime -= ulScrollDelay;
- }
- }
- double dTCDurationRemaining = 1.0 - (
- double(ulLocalTime) / double(ulDurForThisScroll) );
- if (dTCDurationRemaining < 0.0)
- {
- dTCDurationRemaining = 0.0;
- }
- dScrollFactor = dTCDurationRemaining;
- switch (scrolldir)
- {
- case scrollDirLeftToRight:
- dScrollFactor = 1.0 - dScrollFactor;
- case scrollDirRightToLeft:
- lXScrollOffset = INT32(dScrollFactor * m_size.cx);
- break;
- case scrollDirDown:
- dScrollFactor = 1.0 - dScrollFactor;
- case scrollDirUp:
- lYScrollOffset = INT32(dScrollFactor * m_size.cy);
- break;
- }
- #if defined(XXXEH_SCROLLING_TRY1_BUT_BUG_IN_CORE)
- #else
- if (!bIsScrollingOut) // /Scrolling in:
- {
- switch (scrolldir)
- {
- case scrollDirLeftToRight:
- lXScrollOffset -= m_size.cx;
- break;
- case scrollDirRightToLeft:
- break;
- case scrollDirDown:
- lYScrollOffset -= m_size.cy;
- break;
- case scrollDirUp:
- break;
- }
- }
- else // /Is scrolling out:
- {
- switch (scrolldir)
- {
- case scrollDirLeftToRight:
- break;
- case scrollDirRightToLeft:
- lXScrollOffset -= m_size.cx;
- break;
- case scrollDirDown:
- break;
- case scrollDirUp:
- lYScrollOffset -= m_size.cy;
- break;
- }
- }
- #endif // /End else of defined(XXXEH_SCROLLING_TRY1_BUT_BUG_IN_CORE)
- #if defined(XXXEH_SHOW_TODO_MESSAGES)
- #pragma message("====##### XXXEH- todo: SCROLLING OPTIMIZATION NEEDED; increment #####====")
- #pragma message("====##### by an amount that will make for smoothest motion: #####====")
- #endif // /XXXEH_SHOW_TODO_MESSAGES.
- pTextContainer->m_ulNextDrawUpdateTimeOffset += 50;
- // /Call this even if pT.C.'s end is exceeded because this
- // method will remove & not reinsert it in that case:
- InsertInRedrawListInTemporalOrder(pTextContainer);
- // /Reuse position info from last draw if this is a redraw:
- bReuseTCsPriorDrawRect = !bTextContainerIsFromMainList;
- } // /end scroll-offset handling.
-
- if (pTextContainer->m_pTextBlinkBox)
- {
- // /Set this text to ON if drawTime is even # seconds,
- // otherwise to OFF:
- if ((pTextContainer->m_ulNextDrawUpdateTimeOffset /
- HX_3GPPTT_BLINK_HALFINTERVAL_TIME) % 2)
- {
- ulTextColorARGB = ulBgColorARGB;
- }
- pTextContainer->m_ulNextDrawUpdateTimeOffset +=
- HX_3GPPTT_BLINK_HALFINTERVAL_TIME;
- // /Call this even if pT.C.'s end is exceeded because this
- // method will remove & not reinsert it in that case:
- InsertInRedrawListInTemporalOrder(pTextContainer);
- // /Reuse position info from last draw if this is a redraw:
- bReuseTCsPriorDrawRect = !bTextContainerIsFromMainList;
- // /#define XXXEH_TESTING_BLINK_REDRAW
- #if defined(XXXEH_TESTING_BLINK_REDRAW) // /XXXEH- DON'T CHECK THIS IN!
- static UINT32 ulTmpCount = 0;
- FILE* pTmpFile = fopen("c:\3gppttBlinkDump.txt", ulTmpCount?"a+":"w");
- if (pTmpFile)
- {
- fprintf(pTmpFile, "T.C. = %x at time %lu (new draw time = %lu, T.C.'s end "
- "time= %ld) ulTextColorARGB=%p (text containers handled = %ld)n",
- pTextContainer, m_ulTimeOfLastTimeSync,
- pTextContainer->GetNextActivityTime(), pTextContainer->GetEndTime(),
- ulTextColorARGB, ulTextContainersHandled, m_pTextContainerListFutureTimePos);
- fclose(pTmpFile);
- }
- ulTmpCount++;
- #endif
- } // / end blinkBox handling.
- #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
- pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
- if (pFile)
- {
- fprintf(pFile, "[step 2] T.C. = %p at time %lu (text containers handled = "
- "%ld), m_pTextContainerListFutureTimePos=%pn", pTextContainer,
- m_ulTimeOfLastTimeSync, ulTextContainersHandled,
- m_pTextContainerListFutureTimePos);
- fclose(pFile);
- }
- ulCount++;
- #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
- // /Use ARGB instead of RGB if the background color, text color, or
- // highlight color is not fully opaque:
- bHasNonOpaqueAlpha = (ulTextColorARGB & HX_3GPPTT_FULLY_TRANSPARENT) |
- (ulBgColorARGB & HX_3GPPTT_FULLY_TRANSPARENT);
- if (bHasHighlightColor && !bHasNonOpaqueAlpha)
- {
- bHasNonOpaqueAlpha = (ulHighlightColorARGB & HX_3GPPTT_FULLY_TRANSPARENT);
- }
- // /Windows needs to have UTF-8 converted to UTF-16
- // and then from that to native Windows. The result
- // is Japanese showing up on a Japanese OS, Korean
- // showing up on a Korean OS, ...etc.
- #if defined(_WINDOWS) // / -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
- char* pConvertedText = NULL;
- INT32 lConvertedTextLen = 0;
- #else // /else of: _WINDOWS ------------------------------------
- const char* pConvertedText = pTextContainer->m_pTextSample->GetText() +
- pTextContainer->m_uiUnpackedStartCharOffset;
- INT32 lConvertedTextLen = (INT32)
- ((UINT32)pTextContainer->GetTextByteLength());
- #endif // /end else of: _WINDOWS _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
- HX_RESULT hxrsltCnvrtChars = HXR_OK;
-
- #if defined(_WINDOWS) // / -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
- DWORD fdwCharSet = ANSI_CHARSET;
- // /Moved this call up to here so the charset is established
- // prior to the CreateFont() call; fixes Japanese (and others)
- // not displaying (Helix Issue 666):
- hxrsltCnvrtChars =
- ConvertToOSRenderableChars(pTextContainer,
- fdwCharSet, //(REF)
- pConvertedText, lConvertedTextLen); //(REF,REF)
- int bkModeOld;
- int bkModeCur = TRANSPARENT;
- // /If highlight is set for the text, use OPAQUE, not TRANSPARENT,
- // and set bk color to highlight color:
- if (bHasHighlightColor)
- {
- bkModeCur = OPAQUE;
- SetBkColor(hDC, convertARGBtoWinBGRColor(ulHighlightColorARGB));
- }
- bkModeOld = SetBkMode(hDC, bkModeCur);
- ulTextColorARGBOld = SetTextColor(
- hDC, convertARGBtoWinBGRColor(ulTextColorARGB) );
- if(CLR_INVALID == ulTextColorARGBOld)
- {
- #if !defined(USE_DIB_SECTION)
- SelectObject(hDC, hbmpOld);
- #endif // /USE_DIB_SECTION.
- DeleteObject(m_pFont);
- hxrslt = HXR_UNEXPECTED;
- goto cleanup;
- }
- SetMapMode(hDC, MM_TEXT); // /1 logical unit mapped to 1 device pixel
- #elif defined(_SYMBIAN)
- // /If highlight is set for the text, set bk color to
- // highlight color:
- if (bHasHighlightColor)
- {
- TRgb rgbBgColor;
- convertARGBtoSymbianTrgbColor(rgbBgColor, ulHighlightColorARGB);
- m_pGCOffscreen->SetBrushStyle(CGraphicsContext::ESolidBrush);
- m_pGCOffscreen->SetBrushColor(rgbBgColor);
- }
- // /Set foreground color (i.e., pen color):
- TRgb rgbFgColor;
- convertARGBtoSymbianTrgbColor(rgbFgColor, ulTextColorARGB);
- m_pGCOffscreen->SetPenColor(rgbFgColor);
- #else // /end else of: #if _WINDOWS, #elif _SYMBIAN
- #pragma message("====##### This OS needs code that sets text/bg colors #####====")
- #endif // /end else of _WINDOWS. _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
- // /XXXEH- todo: optimization would be to keep current m_pFont
- // if it's determined to be identical in all respects to prior
- // TextContainer's font; if so, don't call SetFont(), below:
- hxrslt = SetFont(pCurTextSampleEntry,
- uiFontID_override,
- pCurFontFaceString,
- bIsBolded, bIsItalicized, bIsUnderlined, bIsStruckThrough,
- ulScaledHeight
- #if defined(_WINDOWS) // / -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
- , fdwCharSet
- #endif // /_WINDOWS _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
- );
- if (HXR_OK != hxrslt)
- {
- goto cleanup;
- }
- // /In case the loaded font's size differs from the requested
- // size, we have to just go with the font's size for all
- // further calculations otherwise text lines may overlap:
- #if defined(_SYMBIAN) // / -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
- ulScaledHeight = m_pFont->HeightInPixels();
- #endif // /_SYMBIAN _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
- // /If a newline(s) starts this TextContainer, reset liCursorX
- // to initial (post-carriage-return) position and bump
- // liCursorY by this's scaled height times number of newlines:
- const char* pTxt = pTextContainer->m_pTextSample->GetText() +
- pTextContainer->m_uiUnpackedStartCharOffset;
- if (HX_3GPPTT_INVALID_INT16 ==
- pTextContainer->m_lNumUTF16NewlinesAtStart)
- {
- if ('r' == *pTxt || 'n' == *pTxt)
- {
- // /XXXEH- I don't think we should ever get here;
- // remove this assert if content is valid and trips
- // this, i.e., it has 'r' or 'n' which was not
- // counted in T.C.'s m_lNumUTF16NewlinesAtStart:
- HX_ASSERT(0);
- liCursorX = INITIAL_CURSOR_X;
- liCursorY += ulScaledHeight;
- }
- }
- else if (pTextContainer->m_lNumUTF16NewlinesAtStart > 0)
- {
- // /Perform carriage return:
- liCursorX = INITIAL_CURSOR_X;
- liCursorY += pTextContainer->m_lNumUTF16NewlinesAtStart *
- ulScaledHeight;
- }
- // /XXXEH- todo: revisit with UTF8 in mind:
- // /XXXEH- todo: We need to use m_originTransformXY.(x,y); (0,0)
- // puts it at top-left of video, so we need to move our site's
- // origin to client-area(0,0) in calculating the draw location:
- HXxRect drawRect;
- if (bReuseTCsPriorDrawRect)
- {
- drawRect.left =
- pTextContainer->m_BoundingRectOfInitialDraw.left;
- drawRect.top =
- pTextContainer->m_BoundingRectOfInitialDraw.top;
- drawRect.right =
- pTextContainer->m_BoundingRectOfInitialDraw.right;
- drawRect.bottom =
- pTextContainer->m_BoundingRectOfInitialDraw.bottom;
- }
- else
- {
- const C3GPPTextboxBox& box = pCurTextSampleEntry->GetDefaultTextBox();
- drawRect.top = liCursorY + (INT32)box.Top();
- drawRect.left = liCursorX + (INT32)box.Left();
- // /XXXEH- ? don't add liCursorY here (for slightly quicker
- // DrawText() performance) but need to test heavily first:
- drawRect.bottom = liCursorY + (INT32)box.Bottom();
- // /XXXEH- ? don't add liCursorX here (for slightly quicker
- // DrawText() performance) but need to test heavily first:
- drawRect.right = liCursorX + (INT32)box.Right();
- if (pTextContainer->m_pTextboxBox)
- {
- // /Override with 'tbox's rect:
- // /XXXEH- keep track if this TC has same m_pTextboXBox as prior TC; if not, don't add liCursor[X|Y] to any of these!
-
- drawRect.top = liCursorY + (INT32)
- pTextContainer->m_pTextboxBox->Top();
- drawRect.left = liCursorX + (INT32)
- pTextContainer->m_pTextboxBox->Left();
- drawRect.right = liCursorY + (INT32)
- pTextContainer->m_pTextboxBox->Bottom();
- drawRect.bottom = liCursorX + (INT32)
- pTextContainer->m_pTextboxBox->Right();
- }
- }
- UINT32 ulTextFormatFlags =
- SetJustificationFlags(pCurTextSampleEntry);
- // /This T.C. will be drawn, below, so set time of
- // last draw to cur time:
- pTextContainer->SetPrevActivityTime(m_ulTimeOfLastTimeSync);
- BOOL bTextContainerTextIsUTF16ReverseEncoded = FALSE;
- BOOL bTextContainerTextIsUTF16Encoded =
- IsUTF16Encoded((UCHAR*)pConvertedText,
- lConvertedTextLen,
- bTextContainerTextIsUTF16ReverseEncoded);
- INT32 lTextLenInChars = lConvertedTextLen;
- if (bTextContainerTextIsUTF16Encoded)
- {
- HX_ASSERT(!(lTextLenInChars & 0x1)); // /Shouldn't be odd
- lTextLenInChars >>= 1; // /Divide by 2: 2 bytes/char
- // /Skip past 0xfffe UTF-16 flag at start:
- pConvertedText += 2;
- lTextLenInChars--;
- }
- #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
- pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
- if (pFile)
- {
- fprintf(pFile, "[step 5] T.C. = %x at time %lu (text containers "
- "handled = %ld), m_pTextContainerListFutureTimePos=%p, prevActivityTime "
- "was just set to%lun", pTextContainer, m_ulTimeOfLastTimeSync,
- ulTextContainersHandled, m_pTextContainerListFutureTimePos,
- pTextContainer->GetPrevActivityTime());
- fclose(pFile);
- }
- ulCount++;
- #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
- if (hxrsltCnvrtChars==HXR_OK && pConvertedText &&
- lConvertedTextLen > 0)
- {
- #if defined(_SYMBIAN) // / -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
- TInt iCharsToSkipOver = 0;
- TInt iNumLinesOfTextAtStart = 0;
- #else // / ------------------------------------