pxgifrnd.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:82k
- /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: pxgifrnd.cpp,v 1.10.6.2 2004/07/09 12:55:11 pankajgupta Exp $
- *
- * Portions Copyright (c) 1995-2004 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 (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the current version of the RealNetworks Community
- * Source License (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.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL") in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your version of
- * this file only under the terms of the GPL, and not to allow others
- * to use your version of this file under the terms of either the RPSL
- * or RCSL, indicate your decision by deleting the provisions above
- * and replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient may
- * use your version of this file under the terms of any one of the
- * RPSL, the RCSL or the GPL.
- *
- * 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 ***** */
- // include
- #include "hxtypes.h"
- #include "hxwintyp.h"
- #include "hxcom.h"
- #include "hxassert.h"
- #include <stdio.h>
- #ifdef _WINDOWS
- #include <windows.h>
- #include "platform/win/resource.h"
- #endif
- #if defined(_UNIX) && defined(USE_XWINDOWS)
- #include <X11/cursorfont.h>
- #include <X11/Intrinsic.h>
- #endif
- #ifdef _MACINTOSH
- #include <ctype.h>
- #include "platform/mac/cresload.h"
- extern FSSpec g_DLLFSpec;
- //CResourceLoader* CResourceLoader::zm_theResourceLoader = NULL;
- #endif
- //Mini sites don't support ARGB blt'ing.
- //Should break this out into a ALPHA_SUPPORTED feature.
- #if !defined(HELIX_FEATURE_MINI_SITE)
- # define ARGB_CID HX_ARGB
- #else
- # define ARGB_CID HX_RGB
- #endif
- #include "hxcomm.h"
- #include "ihxpckts.h"
- #include "hxfiles.h"
- #include "hxcore.h"
- #include "hxrendr.h"
- #include "hxhyper.h"
- #include "hxplugn.h"
- #include "hxwin.h"
- #include "hxasm.h"
- #include "hxevent.h"
- #include "hxvsurf.h"
- #include "hxver.h"
- #include "hxupgrd.h"
- #include "hxengin.h"
- #include "hxmon.h"
- #include "hxerror.h"
- #include "hxclsnk.h"
- #include "hxprefs.h"
- #include "addupcol.h"
- #include "hxstrutl.h"
- #include "netbyte.h"
- #include "unkimp.h"
- #include "baseobj.h"
- #include "hxparse.h"
- #include "hxtick.h"
- #include "hxbuffer.h"
- #include "hxstring.h"
- #include "gstring.h"
- #include "glist.h"
- #include "pxutil.h"
- #include "pxrect.h"
- #include "pxcolor.h"
- #include "pxeffect.h"
- #include "parseurl.h"
- #include "pxcallbk.h"
- #include "pximage.h"
- #include "makebomb.h"
- #include "pxtransp.h"
- #include "cladvsnk.h"
- #include "baseobj.h"
- #include "unkimp.h"
- #include "lzw.h"
- #include "gifimage.h"
- #include "gifcodec.h"
- #include "gifrmlog.h"
- #include "pxgifrnd.h"
- #include "gifrdll.ver"
- #include "debugout.h"
- #include "hxheap.h"
- #ifdef _DEBUG
- #undef HX_THIS_FILE
- static const char HX_THIS_FILE[] = __FILE__;
- #endif
- #include "errdbg.h"
- #ifdef _AIX
- #include "dllpath.h"
- ENABLE_MULTILOAD_DLLACCESS_PATHS(Pxgifrnd);
- #endif
- const char * const CGIFRenderer::m_pszName = "GIF";
- const char * const CGIFRenderer::m_pszDescription = "Helix GIF Renderer Plugin";
- const char * const CGIFRenderer::m_pszCopyright = HXVER_COPYRIGHT;
- const char * const CGIFRenderer::m_pszMoreInfoURL = HXVER_MOREINFO;
- const char * const CGIFRenderer::m_ppszStreamMimeType[] = {"application/vnd.rn-gifstream",
- "application/vnd.rn-gifstream2",
- "application/vnd.rn-gifstream3",
- NULL};
- const UINT32 CGIFRenderer::m_ulHighestSupportedContentVersion = HX_ENCODE_PROD_VERSION(0, 0, 0, 0);
- const UINT32 CGIFRenderer::m_ulHighestSupportedStreamVersion = HX_ENCODE_PROD_VERSION(0, 1, 0, 0);
- #ifdef _WINDOWS
- extern HINSTANCE g_hInstance;
- #endif
- CGIFRenderer::CGIFRenderer()
- {
- MLOG_LEAK("CON CGIFRenderer this=0x%08xn", this);
- m_lRefCount = 0;
- m_pContext = NULL;
- m_pStream = NULL;
- m_cSize.cx = 0;
- m_cSize.cy = 0;
- m_pMISUS = NULL;
- m_pMISUSSite = NULL;
- m_pCommonClassFactory = NULL;
- m_pHyperNavigate = NULL;
- m_pStatusMessage = NULL;
- m_pGIFCodec = NULL;
- m_ulPadWidth = 0;
- m_bDecompressFinished = FALSE;
- m_ulCurImg = 0;
- m_ulCurImgRenderTime = 0;
- m_pOutputBuffer = NULL;
- m_ucTarget = kTargetBrowser;
- m_cURL = "";
- m_ulBackgroundColor = 0x00FFFFFF;
- m_pScheduler = NULL;
- m_ulDataWidth = 0;
- m_ulLoopsDone = 0;
- m_ulBitsPerPixel = 32;
- m_ulBytesPerPixel = 4;
- m_bRGBOrdering = TestBigEndian();
- m_bFirstTimeSync = TRUE;
- m_bFirstDraw = TRUE;
- m_lLastImg = -1;
- m_bSiteAttached = FALSE;
- m_ulCurDelayTime = 0;
- m_pErrorMessages = NULL;
- #if defined(_WINDOWS)
- m_bRowsInverted = TRUE;
- #elif defined(_MACINTOSH)
- m_bRowsInverted = FALSE;
- #elif defined(_UNIX)
- m_bRowsInverted = FALSE;
- #endif
- m_bStatusMsgWillNeedErasing = FALSE;
- m_bSetHyperlinkCursor = FALSE;
- m_sOldMouseX = -1;
- m_sOldMouseY = -1;
- #if defined(_WINDOWS)
- m_hPreHyperlinkCursor = NULL;
- m_hHyperlinkCursor = NULL;
- #elif defined(_MACINTOSH)
- const short HAND_CURSOR = 1313;
- m_pResourceLoader = CResourceLoader::CreateInstance(g_DLLFSpec);
- m_hHyperlinkCursor = (CursHandle)m_pResourceLoader->LoadResource('CURS', HAND_CURSOR);
- m_eCurrentCursor = CURSOR_ARROW;
- #elif defined(_UNIX) && defined(USE_XWINDOWS)
- m_pDisplay = 0;
- m_Window = 0;
- m_hHyperlinkCursor = -1;
- m_hCurrentCursor = -1;
- #endif
- m_pStreamHeaderBuffer = NULL;
- m_ulStreamHeaderOffset = 0;
- m_bIgnorePackets = FALSE;
- m_pCallback = NULL;
- m_bImageBombed = FALSE;
- m_ulRendererFlags = 0;
- m_ulWidth = 0;
- m_ulHeight = 0;
- m_pValues = NULL;
- m_ulBackgroundOpacity = 255;
- m_ulMediaOpacity = 255;
- m_ulMediaChromaKey = 0;
- m_bMediaChromaKeySpecified = FALSE;
- m_ulMediaChromaKeyTolerance = 0;
- m_ulMediaChromaKeyOpacity = 0;
- m_bUsesAlphaChannel = FALSE;
- m_bPreserveMediaRepeat = TRUE;
- m_bPaused = FALSE;
- m_lTimeOffset = 0;
- m_tSchedulerTimeBase.tv_sec = 0;
- m_tSchedulerTimeBase.tv_usec = 0;
- m_ulTimeAtSchedulerTimeBase = 0;
- m_ulCurFrameIndex = 0xFFFFFFFF;
- m_pClientAdviseSink = NULL;
- m_ulEndTime = 0;
- m_bNoNativeSize = FALSE;
- m_bCanBltSubRects = FALSE;
- }
- CGIFRenderer::~CGIFRenderer()
- {
- MLOG_LEAK("DES CGIFRenderer this=0x%08xn", this);
- if (m_pCallback)
- {
- if (m_pCallback->IsCallbackPending())
- {
- m_pCallback->RemovePendingCallback();
- }
- }
- if (m_pClientAdviseSink)
- {
- m_pClientAdviseSink->Close();
- }
- HX_RELEASE(m_pStatusMessage);
- HX_RELEASE(m_pOutputBuffer);
- HX_RELEASE(m_pContext);
- HX_RELEASE(m_pCommonClassFactory);
- HX_RELEASE(m_pHyperNavigate);
- HX_DELETE(m_pGIFCodec);
- HX_RELEASE(m_pScheduler);
- HX_RELEASE(m_pErrorMessages);
-
- #if defined(_MACINTOSH)
- if (m_hHyperlinkCursor)
- {
- m_pResourceLoader->UnloadResource((Handle)m_hHyperlinkCursor);
- m_hHyperlinkCursor = NULL;
-
- HX_RELEASE(m_pResourceLoader);
- }
- #endif
- #if defined(_UNIX) && defined(USE_XWINDOWS)
- if ((m_hHyperlinkCursor != -1) && m_pDisplay)
- {
- XLockDisplay(m_pDisplay);
- XFreeCursor(m_pDisplay, m_hHyperlinkCursor);
- XUnlockDisplay(m_pDisplay);
- m_hHyperlinkCursor = -1;
- }
- #endif
- HX_RELEASE(m_pStreamHeaderBuffer);
- HX_RELEASE(m_pCallback);
- HX_RELEASE(m_pValues);
- HX_RELEASE(m_pClientAdviseSink);
- }
- STDMETHODIMP CGIFRenderer::QueryInterface(REFIID riid, void** ppvObj)
- {
- HX_RESULT retVal = HXR_OK;
- if (ppvObj)
- {
- // Set default
- *ppvObj = NULL;
- // Check for IID type
- if (IsEqualIID(riid, IID_IUnknown))
- {
- AddRef();
- *ppvObj = (IUnknown*) (IHXPlugin*) this;
- }
- else if (IsEqualIID(riid, IID_IHXPlugin))
- {
- AddRef();
- *ppvObj = (IHXPlugin*) this;
- }
- else if (IsEqualIID(riid, IID_IHXRenderer))
- {
- AddRef();
- *ppvObj = (IHXRenderer*) this;
- }
- else if (IsEqualIID(riid, IID_IHXSiteUser))
- {
- AddRef();
- *ppvObj = (IHXSiteUser*) this;
- }
- else if (IsEqualIID(riid, IID_IHXSiteUserSupplier))
- {
- if (m_pMISUS)
- {
- return m_pMISUS->QueryInterface(IID_IHXSiteUserSupplier, ppvObj);
- }
- else
- {
- retVal = HXR_UNEXPECTED;
- }
- }
- else if (IsEqualIID(riid, IID_IHXStatistics))
- {
- AddRef();
- *ppvObj = (IHXStatistics*) this;
- }
- else if (IsEqualIID(riid, IID_IHXValues))
- {
- AddRef();
- *ppvObj = (IHXValues*) this;
- }
- else if (IsEqualIID(riid, IID_IHXUpdateProperties))
- {
- AddRef();
- *ppvObj = (IHXUpdateProperties*) this;
- }
- else
- {
- retVal = HXR_NOINTERFACE;
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- return retVal;
- }
- STDMETHODIMP_(UINT32) CGIFRenderer::AddRef()
- {
- return InterlockedIncrement(&m_lRefCount);
- }
- STDMETHODIMP_(UINT32) CGIFRenderer::Release()
- {
- if (InterlockedDecrement(&m_lRefCount) > 0)
- {
- return m_lRefCount;
- }
- delete this;
- return 0;
- }
- STDMETHODIMP CGIFRenderer::GetPluginInfo(REF(BOOL) rbLoadMultiple,
- REF(const char *) rpszDescription,
- REF(const char *) rpszCopyright,
- REF(const char *) rpszMoreInfoURL,
- REF(UINT32) rulVersionNumber)
- {
- rbLoadMultiple = TRUE;
- rpszDescription = (const char*) m_pszDescription;
- rpszCopyright = (const char*) m_pszCopyright;
- rpszMoreInfoURL = (const char*) m_pszMoreInfoURL;
- rulVersionNumber = TARVER_ULONG32_VERSION;
- return HXR_OK;
- }
- STDMETHODIMP CGIFRenderer::InitPlugin(IUnknown* pContext)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pContext)
- {
- // Save a copy of the calling context
- HX_RELEASE(m_pContext);
- m_pContext = pContext;
- m_pContext->AddRef();
- // Get a IHXCommonClassFactory interface
- HX_RELEASE(m_pCommonClassFactory);
- retVal = m_pContext->QueryInterface(IID_IHXCommonClassFactory,
- (void**) &m_pCommonClassFactory);
- if (SUCCEEDED(retVal))
- {
- #if defined(HELIX_FEATURE_HYPER_NAVIGATE)
- // Get an IHXHyperNavigate interface
- HX_RELEASE(m_pHyperNavigate);
- m_pContext->QueryInterface(IID_IHXHyperNavigate,
- (void**) &m_pHyperNavigate);
- #endif /* #if defined(HELIX_FEATURE_HYPER_NAVIGATE) */
- // Get the IHXStatusMessage interface - it's OK if TLC doesn't support
- // this, so we won't check error return.
- HX_RELEASE(m_pStatusMessage);
- m_pContext->QueryInterface(IID_IHXStatusMessage,
- (void**) &m_pStatusMessage);
- // Get an IHXScheduler interface
- HX_RELEASE(m_pScheduler);
- retVal = m_pContext->QueryInterface(IID_IHXScheduler,
- (void**) &m_pScheduler);
- if (SUCCEEDED(retVal))
- {
- // Get the IHXErrorMessages interface - OK if
- // TLC doesn't support it
- HX_RELEASE(m_pErrorMessages);
- m_pContext->QueryInterface(IID_IHXErrorMessages,
- (void**) &m_pErrorMessages);
- // Create a PXCallback object
- HX_RELEASE(m_pCallback);
- m_pCallback = new PXCallback();
- if (m_pCallback)
- {
- // AddRef the object
- m_pCallback->AddRef();
- // Init the callback object
- retVal = m_pCallback->Init(m_pContext, this);
- if (SUCCEEDED(retVal))
- {
- // Create the IHXValues object
- HX_RELEASE(m_pValues);
- m_pCommonClassFactory->CreateInstance(CLSID_IHXValues,
- (void**) &m_pValues);
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- }
- }
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::GetRendererInfo(REF(const char **) rppszStreamMimeType,
- REF(UINT32) rulInitialGranularity)
- {
- rppszStreamMimeType = (const char**) m_ppszStreamMimeType;
- rulInitialGranularity = 1000;
- return HXR_OK;
- }
- STDMETHODIMP CGIFRenderer::StartStream(IHXStream* pStream, IHXPlayer* pPlayer)
- {
- HX_RESULT retVal = HXR_OK;
- if (pStream && pPlayer)
- {
- // Save a copy of the stream
- HX_RELEASE(m_pStream);
- m_pStream = pStream;
- m_pStream->AddRef();
- // Create a PXClientAdviseSink object
- HX_RELEASE(m_pClientAdviseSink);
- m_pClientAdviseSink = new PXClientAdviseSink();
- if (m_pClientAdviseSink)
- {
- // AddRef the object
- m_pClientAdviseSink->AddRef();
- // Init the object - this registers this renderer
- // as a client advise sink
- retVal = m_pClientAdviseSink->Init(pPlayer,
- (PXClientAdviseSinkResponse*) this);
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- #if defined(HELIX_FEATURE_MISU)
- if (SUCCEEDED(retVal))
- {
- // Create a IHXMultiInstanceSiteUserSupplier interface
- HX_RELEASE(m_pMISUS);
- retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXMultiInstanceSiteUserSupplier,
- (void**) &m_pMISUS);
- if (SUCCEEDED(retVal))
- {
- // Register ourselves as a site user
- retVal = m_pMISUS->SetSingleSiteUser((IUnknown*) (IHXSiteUser*) this);
- }
- }
- #endif
- }
- else
- {
- retVal = HXR_FAIL;
- }
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::OnHeader(IHXValues *pStreamHeaderObj)
- {
- // Check for input error
- if (pStreamHeaderObj == NULL)
- {
- return HXR_FAIL;
- }
- // Get content version from header
- UINT32 ulIncomingContentVersion;
- HX_RESULT retVal = pStreamHeaderObj->GetPropertyULONG32("ContentVersion", ulIncomingContentVersion);
- if (retVal != HXR_OK)
- {
- return HXR_FAIL;
- }
- // Get stream version from header
- UINT32 ulIncomingStreamVersion;
- retVal = pStreamHeaderObj->GetPropertyULONG32("StreamVersion", ulIncomingStreamVersion);
- if (retVal != HXR_OK)
- {
- return HXR_FAIL;
- }
- // Check the versions
- if (ulIncomingContentVersion > m_ulHighestSupportedContentVersion ||
- ulIncomingStreamVersion > m_ulHighestSupportedStreamVersion)
- {
- // Add to AU collection
- AddToAutoUpgradeCollection(m_ppszStreamMimeType[2], m_pContext);
- // Now we return an error, any error actually
- return HXR_NO_RENDERER;
- }
- // Get the opaque data from the stream header
- IHXBuffer *pBuffer = NULL;
- retVal = pStreamHeaderObj->GetPropertyBuffer("OpaqueData", pBuffer);
- if (retVal != HXR_OK)
- {
- return retVal;
- }
- // Unpack some info
- BYTE *pData = pBuffer->GetBuffer();
- UnPack8(pData, m_ucTarget);
- // These are no longer used by the renderer they are parsed in the new hypernavigate object in the core so all renderer
- // commands are consistent and parsed in one place. We do have to skip over them since the file format still puts them in.
- // UnPack8(pData, m_ucURLType);
- // UnPack32(pData, m_ulSeekTime);
- pData += 5; // Even though the 2 above members were removed we still need to increment the data pointer
- // Note that we don't get the alpha from the background color
- // in the opaque part of the stream header - we get that from
- // the "bgOpacity" CString property in the stream header
- BYTE ucBgRed = pData[0];
- BYTE ucBgGreen = pData[1];
- BYTE ucBgBlue = pData[2];
- m_ulBackgroundColor = (ucBgRed << 16) | (ucBgGreen << 8) | ucBgBlue;
- pData += 4;
- UnPackString(pData, m_cURL);
- // Get the current URL
- IHXStreamSource* pStreamSource = NULL;
- retVal = m_pStream->GetSource(pStreamSource);
- if (retVal != HXR_OK || !pStreamSource)
- {
- HX_RELEASE(pBuffer);
- return HXR_FAIL;
- }
- const char* pszURL = pStreamSource->GetURL();
- if (!pszURL)
- {
- HX_RELEASE(pBuffer);
- HX_RELEASE(pStreamSource);
- return HXR_FAIL;
- }
- CHXString cOriginalURL = pszURL;
- HX_RELEASE(pStreamSource);
- // Check the URL to see if it's relative
- if (m_cURL.length() > 0)
- {
- if (m_ucTarget == kTargetPlayer)
- {
- if (IsURLRelative(m_cURL.c_str()) &&
- !strstr(m_cURL.c_str(), "command:"))
- {
- CHXString cRelURL(m_cURL.c_str());
- CHXString cAbsURL;
- retVal = MakeAbsoluteURL(cOriginalURL, cRelURL, cAbsURL);
- if (retVal == HXR_OK)
- {
- m_cURL = (const char *) cAbsURL;
- }
- }
- }
- }
- // Get the renderer flags property
- m_ulRendererFlags = 0;
- pStreamHeaderObj->GetPropertyULONG32("RendererFlags", m_ulRendererFlags);
- // Check bit 0 to see if parsing failed
- m_ulWidth = 0;
- m_ulHeight = 0;
- UINT32 ulBytesUsed = 0;
- if (m_ulRendererFlags & GIF_RENDERER_FLAG_PARSEFAILED)
- {
- // Get the width and height from the stream header
- pStreamHeaderObj->GetPropertyULONG32("Width", m_ulWidth);
- pStreamHeaderObj->GetPropertyULONG32("Height", m_ulHeight);
- if (!m_ulWidth || !m_ulHeight)
- {
- m_ulWidth = 48;
- m_ulHeight = 48;
- m_bNoNativeSize = TRUE;
- }
- }
- else
- {
- // Create a CGIFCodec
- HX_DELETE(m_pGIFCodec);
- m_pGIFCodec = new CGIFCodec();
- if (!m_pGIFCodec)
- {
- HX_RELEASE(pBuffer);
- return HXR_OUTOFMEMORY;
- }
- // Initialize the CGIFCodec for decompression
- ulBytesUsed = pData - pBuffer->GetBuffer();
- retVal = m_pGIFCodec->InitDecompress(pData, pBuffer->GetSize() - ulBytesUsed);
- if (retVal != HXR_OK)
- {
- HX_RELEASE(pBuffer);
- HX_DELETE(m_pGIFCodec);
- return retVal;
- }
- // Set the width and height
- m_ulWidth = m_pGIFCodec->GetLogicalScreenWidth();
- m_ulHeight = m_pGIFCodec->GetLogicalScreenHeight();
- }
- // Get the mediaRepeat string
- IHXBuffer* pMediaRepeatStr = NULL;
- pStreamHeaderObj->GetPropertyCString("mediaRepeat",
- pMediaRepeatStr);
- if (pMediaRepeatStr)
- {
- if (!strcmp((const char*) pMediaRepeatStr->GetBuffer(), "strip"))
- {
- m_bPreserveMediaRepeat = FALSE;
- }
- }
- HX_RELEASE(pMediaRepeatStr);
- // Save the stream header's opaque buffer
- HX_RELEASE(m_pStreamHeaderBuffer);
- m_pStreamHeaderBuffer = pBuffer;
- m_pStreamHeaderBuffer->AddRef();
- // Init the stream header buffer offset
- m_ulStreamHeaderOffset = ulBytesUsed;
- // Now we can release the IHXBuffer
- HX_RELEASE(pBuffer);
- // Create an output buffer
- HX_RELEASE(m_pOutputBuffer);
- retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void **) &m_pOutputBuffer);
- if (retVal != HXR_OK)
- {
- HX_DELETE(m_pGIFCodec);
- return retVal;
- }
-
- // Compute the size of the output buffer
- m_ulDataWidth = m_ulWidth * m_ulBytesPerPixel;
- m_ulPadWidth = (m_ulDataWidth + 3) & ~3; // This rounds up to nearest multiple of 4
- UINT32 ulNumBytes = m_ulPadWidth * m_ulHeight;
-
- // Set the size of the output buffer
- retVal = m_pOutputBuffer->SetSize(ulNumBytes);
- if (retVal != HXR_OK)
- {
- HX_DELETE(m_pGIFCodec);
- HX_RELEASE(m_pOutputBuffer);
- return retVal;
- }
- // Initially draw the background color into the display buffer
- DrawBackgroundColor();
- // Initialize the rendering members
- m_ulCurImg = 0;
- m_ulCurImgRenderTime = 0;
- m_ulCurDelayTime = 0;
- m_lLastImg = -1;
- // Initialize the loop done count
- m_ulLoopsDone = 0;
- // Clear the ignore packets flag
- m_bIgnorePackets = FALSE;
- // Set the first time sync flag
- m_bFirstTimeSync = TRUE;
- // If the parsing failed, then fill in the image with a bomb image
- if (m_ulRendererFlags & GIF_RENDERER_FLAG_PARSEFAILED)
- {
- CopyBombImage();
- }
- else
- {
- // Send some debug info
- MLOG_MISC(m_pErrorMessages,
- "0x%08x::OnHeader() w=%lu h=%lu loopcount=%lun",
- this, m_pGIFCodec->GetLogicalScreenWidth(),
- m_pGIFCodec->GetLogicalScreenHeight(), m_pGIFCodec->GetLoopCount());
- }
- // Get the duration
- pStreamHeaderObj->GetPropertyULONG32("Duration", m_ulEndTime);
- return HXR_OK;
- }
- STDMETHODIMP CGIFRenderer::OnBegin(UINT32 ulTimeAfterBegin)
- {
- MLOG_MISC(m_pErrorMessages,
- "%lu OnBegin(%lu) this=0x%08xn",
- HX_GET_BETTERTICKCOUNT(), ulTimeAfterBegin, this);
- return HXR_OK;
- }
- STDMETHODIMP CGIFRenderer::GetDisplayType(REF(HX_DISPLAY_TYPE) rDisplayType,
- REF(IHXBuffer *) rpDisplayInfo)
- {
- rDisplayType = HX_DISPLAY_WINDOW |
- HX_DISPLAY_SUPPORTS_RESIZE |
- HX_DISPLAY_SUPPORTS_FULLSCREEN;
- return HXR_OK;
- }
- STDMETHODIMP CGIFRenderer::OnPacket(IHXPacket *pPacket, INT32 lTimeOffset)
- {
- MLOG_MISC(m_pErrorMessages,
- "%lu OnPacket(,%ld) this=0x%08xn",
- HX_GET_BETTERTICKCOUNT(), lTimeOffset, this);
- // Check for input error
- if (pPacket == NULL)
- {
- return HXR_INVALID_PARAMETER;
- }
- // Save the time offset
- m_lTimeOffset = lTimeOffset;
- // If we are in between OnPreSeek() and OnPostSeek(), we will ignore
- // packets
- if (m_bIgnorePackets || m_bImageBombed)
- {
- return HXR_OK;
- }
- // Check if the packet is lost
- if (pPacket->IsLost())
- {
- m_pGIFCodec->PacketLost();
- return HXR_OK;
- }
- // Get the IHXBuffer from the packet
- IHXBuffer *pBuffer = pPacket->GetBuffer();
- if (pBuffer == NULL)
- {
- return HXR_INVALID_PARAMETER;
- }
- BYTE* pData = pBuffer->GetBuffer();
- UINT32 ulDataSize = pBuffer->GetSize();
- // Retrieve the flags
- UINT32 ulFlags = 0;
- UnPack32(pData, ulFlags);
- // Is this packet the beginning of a new image?
- BOOL bFirstInImage = FALSE;
- if (ulFlags & 0x01)
- {
- bFirstInImage = TRUE;
- }
- // Comment extensions at the end of the file could mean we receive packets
- // after we are finished decoding. In this case, we just return
- if (m_pGIFCodec->DecompressFinished())
- {
- HX_RELEASE(pBuffer);
- return HXR_OK;
- }
- // Pass the data on to the CGIFCodec
- HX_RESULT retVal = m_pGIFCodec->Decompress(pBuffer->GetBuffer() + 4,
- pBuffer->GetSize() - 4,
- bFirstInImage);
- if (retVal != HXR_OK)
- {
- CopyBombImage();
- }
- // Release our reference to the IHXBuffer
- HX_RELEASE(pBuffer);
- return HXR_OK;
- }
- STDMETHODIMP CGIFRenderer::OnTimeSync(UINT32 ulTime)
- {
- MLOG_TIMING(m_pErrorMessages,
- "0x%08x::OnTimeSync(%lu)n",
- this, ulTime);
- HX_RESULT retVal = HXR_OK;
- if (m_bFirstTimeSync || m_bPaused)
- {
- // Clear the first timesync flag
- m_bFirstTimeSync = FALSE;
- // Clear the paused flag
- m_bPaused = FALSE;
- // Adjust the time according to the
- // offset passed in through OnPacket()
- INT32 lAdjustedTime = ((INT32) ulTime) + m_lTimeOffset;
- UINT32 ulAdjustedTime = (UINT32) (lAdjustedTime >= 0 ? lAdjustedTime : 0);
- // Set the current scheduler time base
- if (m_pScheduler)
- {
- // Compute time in milliseconds
- m_tSchedulerTimeBase = m_pScheduler->GetCurrentSchedulerTime();
- // m_ulSchedulerTimeBase = (cTime.tv_sec * 1000) + ((cTime.tv_usec + 500) / 1000);
- m_ulTimeAtSchedulerTimeBase = ulAdjustedTime;
- }
- // Update the display
- UpdateDisplay(ulAdjustedTime);
- }
- return retVal;
- }
- HX_RESULT CGIFRenderer::UpdateDisplay(UINT32 ulTime)
- {
- MLOG_MISC(m_pErrorMessages,
- "%lu UpdateDisplay(%lu) this=0x%08xn",
- HX_GET_BETTERTICKCOUNT(), ulTime, this);
- HX_RESULT retVal = HXR_OK;
- // Do we have a valid CGIFCodec?
- if (m_pGIFCodec && !m_bImageBombed)
- {
- // Reset the damage flag
- BOOL bDoDamage = FALSE;
- // Compute which frame we should be on at this time
- UINT32 ulFrameIndex = 0;
- if (m_pGIFCodec->GetNumImages() > 1)
- {
- // Get the modulo time
- UINT32 ulModTime = 0;
- UINT32 ulCycleTime = GetCycleTime();
- if (ulCycleTime)
- {
- UINT32 ulIter = ulTime / ulCycleTime;
- UINT32 ulIterStart = ulIter * ulCycleTime;
- ulModTime = ulTime - ulIterStart;
- }
- UINT32 ulRunSum = 0;
- UINT32 ulNumFrames = m_pGIFCodec->GetNumImages();
- for (UINT32 i = 0; i < ulNumFrames; i++)
- {
- // Get the delay for this frame
- UINT32 ulFrameDelay = 0;
- CGIFImage* pImage = m_pGIFCodec->GetImage(i);
- if (pImage)
- {
- ulFrameDelay = pImage->GetDelayTime() * 10;
- }
- // Check if our time is in this frame
- if (ulModTime >= ulRunSum &&
- ulModTime < ulRunSum + ulFrameDelay)
- {
- ulFrameIndex = i;
- break;
- }
- // Add the delay for this frame to the running sum
- ulRunSum += ulFrameDelay;
- }
- }
- // Is the frame currently in the buffer the same
- // as our computed frame? If it is, then we don't
- // need to update our buffer
- BOOL bFinished = FALSE;
- BOOL bWouldHaveSkipped = FALSE;
- if (ulFrameIndex != m_ulCurFrameIndex)
- {
- // Make sure we don't skip frames
- UINT32 ulFrameIndexNoSkip = ulFrameIndex;
- if (m_ulCurFrameIndex != 0xFFFFFFFF)
- {
- UINT32 ulFrameDiff = 0;
- if (ulFrameIndex >= m_ulCurFrameIndex)
- {
- ulFrameDiff = ulFrameIndex - m_ulCurFrameIndex;
- }
- else
- {
- ulFrameDiff = m_pGIFCodec->GetNumImages() -
- m_ulCurFrameIndex + ulFrameIndex;
- }
- if (ulFrameDiff > 1)
- {
- ulFrameIndexNoSkip = m_ulCurFrameIndex + 1;
- if (ulFrameIndexNoSkip >= m_pGIFCodec->GetNumImages())
- {
- ulFrameIndexNoSkip = 0;
- }
- }
- }
- // Enforce no skipping of frames, but set a flag if
- // we did have to change the frame, so that we can
- // use that to update our callback interval
- if (ulFrameIndexNoSkip != ulFrameIndex)
- {
- // Yes, we are having to force not to skip a frame
- bWouldHaveSkipped = TRUE;
- ulFrameIndex = ulFrameIndexNoSkip;
- }
- // Is the image we want to draw done? If it's not finished,
- // we DON'T want to draw but we DO want another callback
- CGIFImage* pCurImage = m_pGIFCodec->GetImage(ulFrameIndex);
- if (pCurImage)
- {
- bFinished = pCurImage->Finished();
- }
- // Do we need to update?
- if (bFinished)
- {
- // Yes, we need to update, so first we get the image
- m_pGIFCodec->GetRGBImageEx((m_ulCurFrameIndex == 0xFFFFFFFF ? -1 : (INT32) m_ulCurFrameIndex),
- ulFrameIndex,
- m_pOutputBuffer->GetBuffer(),
- m_pGIFCodec->GetLogicalScreenWidth(),
- m_pGIFCodec->GetLogicalScreenHeight(),
- m_ulPadWidth,
- m_ulBytesPerPixel,
- m_bRowsInverted,
- m_bRGBOrdering,
- m_ulBackgroundColor,
- (m_ulMediaOpacity == 255 ? FALSE : TRUE),
- m_ulMediaOpacity,
- m_bMediaChromaKeySpecified,
- m_ulMediaChromaKey,
- m_ulMediaChromaKeyTolerance,
- m_ulMediaChromaKeyOpacity);
- // XXXMEH - do dumb assignment for now. We should later check
- // chroma key to find if any colors were actually encountered.
- if (m_ulBackgroundOpacity < 255 ||
- m_ulMediaOpacity < 255 ||
- m_bMediaChromaKeySpecified)
- {
- m_bUsesAlphaChannel = TRUE;
- }
- // Set the damage flag
- bDoDamage = TRUE;
- // We need to damage the rect. If we are bltting off
- // of HX_SURFACE_UPDATE2, then we should damage the
- // rect of both the current frame and the previous frame.
- // If we are still bltting off of HX_SURFACE_UPDATE, then
- // we need to damage the whole logical screen area.
- if (m_bCanBltSubRects)
- {
- // Damage the rect of the previous frame
- DamageFrameRect(m_ulCurFrameIndex);
- // Damage the rect of the current frame
- DamageFrameRect(ulFrameIndex);
- // Force a redraw
- if (m_pMISUSSite)
- {
- m_pMISUSSite->ForceRedraw();
- }
- }
- else
- {
- // Damage entire site area
- if (m_pMISUSSite)
- {
- // Get the size of the site
- HXxSize cSize = {0, 0};
- m_pMISUSSite->GetSize(cSize);
- // Get the damage rect
- HXxRect cRect = {0, 0, cSize.cx, cSize.cy};
- MLOG_MISC(m_pErrorMessages,
- "%lu Damaging entire logical screen: "
- "(%ld,%ld,%ld,%ld) (%ld x %ld)n",
- HX_GET_BETTERTICKCOUNT(),
- cRect.left, cRect.top,
- cRect.right, cRect.bottom,
- HXxRECT_WIDTH(cRect),
- HXxRECT_HEIGHT(cRect));
- m_pMISUSSite->DamageRect(cRect);
- m_pMISUSSite->ForceRedraw();
- }
- }
- // Check if we just completed a loop. If the frame
- // index that we just drew into the buffer is LOWER
- // than the frame index that USED to be there, then
- // we will assume we just wrapped around
- if ((m_ulCurFrameIndex == 0xFFFFFFFF &&
- m_pGIFCodec->GetNumImages() == 1) ||
- (m_ulCurFrameIndex != 0xFFFFFFFF &&
- ulFrameIndex < m_ulCurFrameIndex))
- {
- m_ulLoopsDone++;
- }
- // Update the current frame index
- m_ulCurFrameIndex = ulFrameIndex;
- }
- }
- // Do we need to schedule another callback?
- if (m_bSiteAttached && // only schedule another callback if site is attached
- m_pCallback && // can't do it without a callback object
- (m_bPreserveMediaRepeat ||
- (!m_bPreserveMediaRepeat && m_ulLoopsDone == 0)) &&
- ((bFinished == FALSE) || // GIF isn't finished yet
- (m_pGIFCodec->GetLoopCount() == 0) || // GIF says to loop infinitely
- (m_pGIFCodec->GetLoopCount() > 0 && // GIF says to loop a finite number of
- m_ulLoopsDone < m_pGIFCodec->GetLoopCount()))) // times and we're not finished
- {
- // If we just drew the image, then don't schedule a callback until
- // the delay time from now. If we didn't draw, then schedule one
- // kCallbackInterval milliseconds from now
- BOOL bRelative = TRUE;
- UINT32 ulTimeFromNow = kCallbackInterval;
- HXTimeval cTime = {0, 0};
- // Was the frame finished?
- if (bFinished)
- {
- // Did we draw and would have skipped a frame?
- if (bDoDamage && bWouldHaveSkipped)
- {
- // Schedule a short relative callback
- bRelative = TRUE;
- ulTimeFromNow = kMinCallbackInterval;
- }
- else
- {
- // Get the time that the next frame would display
- UINT32 ulNextFrameTime = GetNextFrameTime(ulTime);
- // If the difference is small enough, then schedule
- // a short relative callback. Otherwise schedule
- // an absolute callback
- if (ulNextFrameTime - ulTime > kMinCallbackInterval)
- {
- // Get the time difference between the next frame
- // time and the time at the scheduler time base
- UINT32 ulDiff = 0;
- if (ulNextFrameTime >= m_ulTimeAtSchedulerTimeBase)
- {
- ulDiff = ulNextFrameTime - m_ulTimeAtSchedulerTimeBase;
- }
- else
- {
- ulDiff = 0xFFFFFFFF - m_ulTimeAtSchedulerTimeBase + ulNextFrameTime;
- }
- // Compute the difference in seconds and microseconds
- HXTimeval cDiff = {0, 0};
- cDiff.tv_sec = ulDiff / 1000;
- cDiff.tv_usec = (ulDiff - (cDiff.tv_sec * 1000)) * 1000;
- // Add this difference to the scheduler time base
- cTime.tv_sec = m_tSchedulerTimeBase.tv_sec + cDiff.tv_sec;
- cTime.tv_usec = m_tSchedulerTimeBase.tv_usec + cDiff.tv_usec;
- // Wrap the usec if necessary
- if (cTime.tv_usec >= 1000000)
- {
- cTime.tv_usec -= 1000000;
- cTime.tv_sec += 1;
- }
- // Clear the relative flag
- bRelative = FALSE;
- }
- else
- {
- bRelative = TRUE;
- ulTimeFromNow = kMinCallbackInterval;
- }
- }
- }
- else
- {
- // Frame had not completed decoding - schedule a
- // relative callback
- bRelative = TRUE;
- ulTimeFromNow = kNotFinishedInterval;
- }
- // Schedule the next callback
- if (bRelative)
- {
- m_pCallback->ScheduleRelativeCallback(ulTimeFromNow);
- }
- else
- {
- m_pCallback->ScheduleAbsoluteCallback(cTime);
- }
- }
- }
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::OnPreSeek(UINT32 ulTimeBefore, UINT32 ulTimeAfter)
- {
- MLOG_MISC(m_pErrorMessages,
- "0x%08x::OnPreSeek(%lu,%lu)n",
- this, ulTimeBefore, ulTimeAfter);
- // Set the ignore packets flag
- m_bIgnorePackets = TRUE;
- return HXR_OK;
- }
- STDMETHODIMP CGIFRenderer::OnPostSeek(UINT32 ulTimeBefore, UINT32 ulTimeAfter)
- {
- MLOG_MISC(m_pErrorMessages,
- "0x%08x::OnPostSeek(%lu,%lu)n",
- this, ulTimeBefore, ulTimeAfter);
- HX_RESULT retVal = HXR_OK;
- if (m_pStreamHeaderBuffer && !m_bImageBombed)
- {
- // Determine if the seek-to time is past our ending time.
- // We only need to blow away everything if we are going to
- // be getting packets all over again. That will happen only
- // if the seek-to time is < our end time.
- if (ulTimeAfter < m_ulEndTime)
- {
- // We are going to start receiving packets all over again, so
- // we need to blow away the CGIFCodec class and start over
- // again. We will need to reinit it with the stream header
- // buffer.
- //
- // Delete the old CGIFCodec
- HX_DELETE(m_pGIFCodec);
- // Create a new one
- m_pGIFCodec = new CGIFCodec();
- if (m_pGIFCodec)
- {
- // Get the stream header pointer
- BYTE* pData = m_pStreamHeaderBuffer->GetBuffer() + m_ulStreamHeaderOffset;
- // Initialize the CGIFCodec for decompression
- retVal = m_pGIFCodec->InitDecompress(m_pStreamHeaderBuffer->GetBuffer() + m_ulStreamHeaderOffset,
- m_pStreamHeaderBuffer->GetSize() - m_ulStreamHeaderOffset);
- if (SUCCEEDED(retVal))
- {
- // Initialize the rendering members
- m_ulCurImg = 0;
- m_ulCurImgRenderTime = 0;
- m_ulCurDelayTime = 0;
- m_lLastImg = -1;
- // Initialize the loop done count
- m_ulLoopsDone = 0;
- // Clear the ignore packets flag
- m_bIgnorePackets = FALSE;
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- }
- else
- {
- retVal = HXR_UNEXPECTED;
- }
-
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::OnPause(UINT32 ulTimeBeforePause)
- {
- MLOG_MISC(m_pErrorMessages,
- "0x%08x::OnPause(%lu)n",
- this, ulTimeBeforePause);
- // Set the paused flag
- m_bPaused = TRUE;
- return HXR_OK;
- }
- STDMETHODIMP CGIFRenderer::OnBuffering(UINT32 ulReason, UINT16 usPercentComplete)
- {
- MLOG_MISC(m_pErrorMessages,
- "0x%08x::OnBuffering(%lu,%u)n",
- this, ulReason, usPercentComplete);
- return HXR_OK;
- }
- STDMETHODIMP CGIFRenderer::OnEndofPackets()
- {
- MLOG_MISC(m_pErrorMessages,
- "0x%08x::OnEndofPackets()n",
- this);
- return HXR_OK;
- }
- STDMETHODIMP CGIFRenderer::EndStream()
- {
- MLOG_MISC(m_pErrorMessages,
- "0x%08x::EndStream()n",
- this);
- // We're finished with the stream, but we may have
- // more rendering to do
- HX_RELEASE(m_pStream);
- return HXR_OK;
- }
- STDMETHODIMP CGIFRenderer::AttachSite(IHXSite *pSite)
- {
- MLOG_MISC(m_pErrorMessages,
- "0x%08x::AttachSite(0x%08x)n",
- this, pSite);
- // Check for input error
- if (pSite == NULL)
- {
- return HXR_INVALID_PARAMETER;
- }
- // Check to see if we alredy have a site interface
- if (m_pMISUSSite)
- {
- return HXR_UNEXPECTED;
- }
- // Save a copy of the IHXSite interface
- m_pMISUSSite = pSite;
- m_pMISUSSite->AddRef();
- // Fill in the size
- m_cSize.cx = m_ulWidth;
- m_cSize.cy = m_ulHeight;
- // Tell the site of our size
- m_pMISUSSite->SetSize(m_cSize);
- // Lets see if we have a new site that supports sub rects.
- IHXSubRectSite* pSubRectSite = NULL;
- if(HXR_OK == m_pMISUSSite->QueryInterface(IID_IHXSubRectSite,
- (void**)&pSubRectSite))
- {
- //If so, since IHXSubRectSite inheirits from IHXSite, lets just
- //swap the pointers and sign up for the service.
- HX_RELEASE(m_pMISUSSite);
- m_pMISUSSite = pSubRectSite;
- pSubRectSite->SendSubRectMessages(TRUE);
- // Set the flag
- m_bCanBltSubRects = TRUE;
- }
- // Set the site attached flag
- m_bSiteAttached = TRUE;
- return HXR_OK;
- }
- STDMETHODIMP CGIFRenderer::DetachSite()
- {
- MLOG_MISC(m_pErrorMessages,
- "0x%08x::DetachSite()n",
- this);
- if (m_pCallback)
- {
- if (m_pCallback->IsCallbackPending())
- {
- m_pCallback->RemovePendingCallback();
- }
- }
- if (m_pClientAdviseSink)
- {
- m_pClientAdviseSink->Close();
- }
- // Release the callback
- // XXXMEH - MUST DO THIS HERE or we'll have circular
- // dependency and leak CGIFRenderers
- HX_RELEASE(m_pCallback);
- // Release our site interface
- HX_RELEASE(m_pMISUSSite);
- // We're done with these...
- if (m_pMISUS)
- {
- m_pMISUS->ReleaseSingleSiteUser();
- }
- HX_RELEASE(m_pMISUS);
- // Clear the site attached flag
- m_bSiteAttached = FALSE;
- return HXR_OK;
- }
- STDMETHODIMP_(BOOL) CGIFRenderer::NeedsWindowedSites()
- {
- return FALSE;
- }
- STDMETHODIMP CGIFRenderer::InitializeStatistics(UINT32 ulRegistryID)
- {
- MLOG_MISC(m_pErrorMessages,
- "0x%08x::InitializeStatistics(%lu)n",
- this, ulRegistryID);
- // Add our renderer name to the HXRegistry
- IHXRegistry *pRegistry = NULL;
- HX_RESULT retVal = m_pContext->QueryInterface(IID_IHXRegistry, (void **) &pRegistry);
- if (retVal == HXR_OK)
- {
- // Get the current registry key name
- IHXBuffer *pszRegistryName = NULL;
- retVal = pRegistry->GetPropName(ulRegistryID, pszRegistryName);
- if (retVal == HXR_OK)
- {
- // Create an IHXBuffer to hold the name
-
- IHXBuffer* pValue = NULL;
- if (m_pCommonClassFactory)
- {
- IUnknown* pUnknown = NULL;
- m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pUnknown);
- if (pUnknown)
- {
- pUnknown->QueryInterface(IID_IHXBuffer, (void**)&pValue);
- HX_RELEASE(pUnknown);
- }
- }
- if (!pValue)
- {
- HX_RELEASE(pszRegistryName);
- HX_RELEASE(pRegistry);
- return HXR_OUTOFMEMORY;
- }
- pValue->AddRef();
- // Create the key name
- char szRegistryEntry[MAX_DISPLAY_NAME] = {0}; /* Flawfinder: ignore */
- SafeSprintf(szRegistryEntry, MAX_DISPLAY_NAME, "%s.name", pszRegistryName->GetBuffer());
- // Set the key value
- retVal = pValue->Set((const BYTE*) m_pszName, strlen(m_pszName) + 1);
- if (retVal != HXR_OK)
- {
- HX_RELEASE(pValue);
- HX_RELEASE(pszRegistryName);
- HX_RELEASE(pRegistry);
- return retVal;
- }
- // Add the key/value pair to the registry
- pRegistry->AddStr(szRegistryEntry, pValue);
- HX_RELEASE(pValue);
- HX_RELEASE(pszRegistryName);
- }
- HX_RELEASE(pRegistry);
- }
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::UpdateStatistics()
- {
- MLOG_MISC(m_pErrorMessages,
- "0x%08x::UpdateStatistics()n",
- this);
- return HXR_OK;
- }
- STDMETHODIMP CGIFRenderer::SetPropertyULONG32(const char* pName, ULONG32 ulVal)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (m_pValues)
- {
- // Clear the update needed flag
- BOOL bUpdateNeeded = FALSE;
- if (!strcmp(pName, "backgroundOpacity"))
- {
- if (ulVal > 255) ulVal = 255;
- if (ulVal != m_ulBackgroundOpacity) bUpdateNeeded = TRUE;
- m_ulBackgroundOpacity = ulVal;
- }
- else if (!strcmp(pName, "mediaOpacity"))
- {
- if (ulVal > 255) ulVal = 255;
- if (ulVal != m_ulMediaOpacity) bUpdateNeeded = TRUE;
- m_ulMediaOpacity = ulVal;
- }
- else if (!strcmp(pName, "chromaKey"))
- {
- if (ulVal != m_ulMediaChromaKey) bUpdateNeeded = TRUE;
- m_ulMediaChromaKey = ulVal;
- m_bMediaChromaKeySpecified = TRUE;
- }
- else if (!strcmp(pName, "chromaKeyTolerance"))
- {
- if (ulVal != m_ulMediaChromaKeyTolerance) bUpdateNeeded = TRUE;
- m_ulMediaChromaKeyTolerance = ulVal;
- }
- else if (!strcmp(pName, "chromaKeyOpacity"))
- {
- if (ulVal != m_ulMediaChromaKeyOpacity) bUpdateNeeded = TRUE;
- m_ulMediaChromaKeyOpacity = ulVal;
- }
- // Did any values change?
- if (bUpdateNeeded)
- {
- // If we have not seen our first time sync yet, then
- // there is no need to update the buffer, since the first
- // copy has not been done yet
- if (!m_bFirstTimeSync && m_pGIFCodec)
- {
- // Compute the current frame we are on (note that
- // m_ulCurImg contains the index of the NEXT frame
- // that we are about to draw
- UINT32 ulCurFrame = (m_ulCurImg > 0 ? m_ulCurImg - 1 : 0);
- // Update the buffer
- // XXXMEH - optimization for later. In some cases if we
- // just changed the media opacity, then it may not be necessary
- // to start back at the beginning and rebuild the frame buffer
- // from the first frame.
- m_pGIFCodec->GetRGBImageEx(-1,
- ulCurFrame,
- m_pOutputBuffer->GetBuffer(),
- m_pGIFCodec->GetLogicalScreenWidth(),
- m_pGIFCodec->GetLogicalScreenHeight(),
- m_ulPadWidth,
- m_ulBytesPerPixel,
- m_bRowsInverted,
- m_bRGBOrdering,
- m_ulBackgroundColor,
- (m_ulMediaOpacity == 255 ? FALSE : TRUE),
- m_ulMediaOpacity,
- m_bMediaChromaKeySpecified,
- m_ulMediaChromaKey,
- m_ulMediaChromaKeyTolerance,
- m_ulMediaChromaKeyOpacity);
- // XXXMEH - do dumb assignment for now. We should later check
- // chroma key to find if any colors were actually encountered.
- if (m_ulBackgroundOpacity < 255 ||
- m_ulMediaOpacity < 255 ||
- m_bMediaChromaKeySpecified)
- {
- m_bUsesAlphaChannel = TRUE;
- }
- }
- }
- retVal = m_pValues->SetPropertyULONG32(pName, ulVal);
- }
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::GetPropertyULONG32(const char* pName, REF(ULONG32) rulVal)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (m_pValues)
- {
- retVal = m_pValues->GetPropertyULONG32(pName, rulVal);
- }
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::GetFirstPropertyULONG32(REF(const char*) rpName, REF(ULONG32) rulVal)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (m_pValues)
- {
- retVal = m_pValues->GetFirstPropertyULONG32(rpName, rulVal);
- }
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::GetNextPropertyULONG32(REF(const char*) rpName, REF(ULONG32) rulVal)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (m_pValues)
- {
- retVal = m_pValues->GetNextPropertyULONG32(rpName, rulVal);
- }
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::SetPropertyBuffer(const char* pName, IHXBuffer* pVal)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (m_pValues)
- {
- retVal = m_pValues->SetPropertyBuffer(pName, pVal);
- }
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::GetPropertyBuffer(const char* pName, REF(IHXBuffer*) rpVal)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (m_pValues)
- {
- retVal = m_pValues->GetPropertyBuffer(pName, rpVal);
- }
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::GetFirstPropertyBuffer(REF(const char*) rpName, REF(IHXBuffer*) rpVal)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (m_pValues)
- {
- retVal = m_pValues->GetFirstPropertyBuffer(rpName, rpVal);
- }
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::GetNextPropertyBuffer(REF(const char*) rpName, REF(IHXBuffer*) rpVal)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (m_pValues)
- {
- retVal = m_pValues->GetNextPropertyBuffer(rpName, rpVal);
- }
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::SetPropertyCString(const char* pName, IHXBuffer* pVal)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (m_pValues)
- {
- // Check for the default SMIL namespace
- BOOL bUpdateNeeded = FALSE;
- if (!strcmp(pName, "SMILDefaultNamespace"))
- {
- if (m_ulBackgroundOpacity != 0)
- {
- bUpdateNeeded = TRUE;
- }
- m_ulBackgroundOpacity = 0;
- // Update the background color
- UINT32 ulBgAlpha = 255 - m_ulBackgroundOpacity;
- m_ulBackgroundColor = (m_ulBackgroundColor & 0x00FFFFFF) |
- ((ulBgAlpha << 24) & 0xFF000000);
- }
- // Do we need to update the display buffer
- if (bUpdateNeeded && !m_bImageBombed)
- {
- // If we haven't received our first time sync yet
- // (m_bFirstTimeSync == TRUE), then all we need to do
- // is redraw the transparent background color into the
- // the display buffer. If we have already received our
- // first time sync, then we need to redraw the entire buffer,
- // including redrawing the frames
- if (m_bFirstTimeSync)
- {
- // We haven't draw any frames into our display buffer
- // yet, so all we have to do is redraw a transparent
- // background color into the buffer.
- DrawBackgroundColor();
- // We definitely will be using the alpha channel
- m_bUsesAlphaChannel = TRUE;
- }
- else
- {
- if (m_pGIFCodec && m_pOutputBuffer)
- {
- // Compute the current frame we are on (note that
- // m_ulCurImg contains the index of the NEXT frame
- // that we are about to draw
- UINT32 ulCurFrame = (m_ulCurImg > 0 ? m_ulCurImg - 1 : 0);
- // Update the buffer
- // XXXMEH - optimization for later. In some cases if we
- // just changed the media opacity, then it may not be necessary
- // to start back at the beginning and rebuild the frame buffer
- // from the first frame.
- m_pGIFCodec->GetRGBImageEx(-1,
- ulCurFrame,
- m_pOutputBuffer->GetBuffer(),
- m_pGIFCodec->GetLogicalScreenWidth(),
- m_pGIFCodec->GetLogicalScreenHeight(),
- m_ulPadWidth,
- m_ulBytesPerPixel,
- m_bRowsInverted,
- m_bRGBOrdering,
- m_ulBackgroundColor,
- (m_ulMediaOpacity == 255 ? FALSE : TRUE),
- m_ulMediaOpacity,
- m_bMediaChromaKeySpecified,
- m_ulMediaChromaKey,
- m_ulMediaChromaKeyTolerance,
- m_ulMediaChromaKeyOpacity);
- // XXXMEH - do dumb assignment for now. We should later check
- // chroma key to find if any colors were actually encountered.
- if (m_ulBackgroundOpacity < 255 ||
- m_ulMediaOpacity < 255 ||
- m_bMediaChromaKeySpecified)
- {
- m_bUsesAlphaChannel = TRUE;
- }
- }
- }
- }
- retVal = m_pValues->SetPropertyCString(pName, pVal);
- }
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::GetPropertyCString(const char* pName, REF(IHXBuffer*) rpVal)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (m_pValues)
- {
- retVal = m_pValues->GetPropertyCString(pName, rpVal);
- }
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::GetFirstPropertyCString(REF(const char*) rpName, REF(IHXBuffer*) rpVal)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (m_pValues)
- {
- retVal = m_pValues->GetFirstPropertyCString(rpName, rpVal);
- }
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::GetNextPropertyCString(REF(const char*) rpName, REF(IHXBuffer*) rpVal)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (m_pValues)
- {
- retVal = m_pValues->GetNextPropertyCString(rpName, rpVal);
- }
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::UpdatePacketTimeOffset(INT32 lTimeOffset)
- {
- HX_RESULT retVal = HXR_OK;
- // Save the time offset
- // XXXMEH - should this be negative
- m_lTimeOffset = -lTimeOffset;
- return retVal;
- }
- /************************************************************************
- * Method:
- * IHXUpdateProperties::UpdatePlayTimes
- * Purpose:
- * Call this method to update the playtime attributes
- */
- STDMETHODIMP
- CGIFRenderer::UpdatePlayTimes(IHXValues* pProps)
- {
- return HXR_OK;
- }
- STDMETHODIMP CGIFRenderer::HandleCallback(UINT32 ulSchedulerTime, UINT32 ulInstance)
- {
- HX_RESULT retVal = HXR_OK;
-
- if (!m_bPaused)
- {
- // Get the current scheduler time
- HXTimeval cTime = m_pScheduler->GetCurrentSchedulerTime();
- // Compute the difference in scheduler time
- UINT32 ulSchedDiff = GetTimevalDiff(m_tSchedulerTimeBase, cTime);
- // Compute the time in our timeline
- UINT32 ulTime = m_ulTimeAtSchedulerTimeBase + ulSchedDiff;
- // Update the display (if necessary)
- retVal = UpdateDisplay(ulTime);
- }
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::CASOnPosLength(UINT32 ulPosition, UINT32 ulLength)
- {
- HX_RESULT retVal = HXR_OK;
- // XXXMEH
- // char szDbgStr[128];
- // DEBUGPRINTF(szDbgStr, "CGIFRenderer::CASOnPosLength(%lu,%lu) tick=%lun",
- // ulPosition, ulLength, HX_GET_BETTERTICKCOUNT());
- if (m_bPaused)
- {
- // Clear the paused flag
- m_bPaused = FALSE;
- // Adjust the time according to the
- // offset passed in through OnPacket()
- INT32 lAdjustedTime = ((INT32) ulPosition) + m_lTimeOffset;
- UINT32 ulAdjustedTime = (UINT32) (lAdjustedTime >= 0 ? lAdjustedTime : 0);
- // Set the current scheduler time base
- if (m_pScheduler)
- {
- // Compute time in milliseconds
- m_tSchedulerTimeBase = m_pScheduler->GetCurrentSchedulerTime();
- m_ulTimeAtSchedulerTimeBase = ulAdjustedTime;
- }
- // Update the display
- UpdateDisplay(ulAdjustedTime);
- }
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::CASOnPresentationOpened()
- {
- HX_RESULT retVal = HXR_OK;
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::CASOnPresentationClosed()
- {
- HX_RESULT retVal = HXR_OK;
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::CASOnStatisticsChanged()
- {
- HX_RESULT retVal = HXR_OK;
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::CASOnPreSeek(ULONG32 ulOldTime, ULONG32 ulNewTime)
- {
- HX_RESULT retVal = HXR_OK;
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::CASOnPostSeek(ULONG32 ulOldTime, ULONG32 ulNewTime)
- {
- HX_RESULT retVal = HXR_OK;
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::CASOnStop()
- {
- HX_RESULT retVal = HXR_OK;
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::CASOnPause(ULONG32 ulTime)
- {
- MLOG_MISC(m_pErrorMessages,
- "0x%08x::CASOnPause(%lu)n",
- this, ulTime);
- HX_RESULT retVal = HXR_OK;
- m_bPaused = TRUE;
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::CASOnBegin(ULONG32 ulTime)
- {
- MLOG_MISC(m_pErrorMessages,
- "0x%08x::CASOnBegin(%lu)n",
- this, ulTime);
- HX_RESULT retVal = HXR_OK;
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::CASOnBuffering(ULONG32 ulFlags, UINT16 unPercentComplete)
- {
- HX_RESULT retVal = HXR_OK;
- return retVal;
- }
- STDMETHODIMP CGIFRenderer::CASOnContacting(const char* pHostName)
- {
- HX_RESULT retVal = HXR_OK;
- return retVal;
- }
- void CGIFRenderer::OnMouseMove(INT16 fwKeys, INT16 xPos, INT16 yPos)
- {
- // Make sure we're up and running
- if (!m_pGIFCodec)
- {
- return;
- }
- // don't do anything if the x/y coordinates have changed from the
- // last call to OnMouseMove - this is needed because the call to
- // IHXStatusMessage::SetStatus() results in a WM_MOUSEMOVE event
- if(xPos == m_sOldMouseX && yPos == m_sOldMouseY)
- {
- return;
- }
- m_sOldMouseX = xPos;
- m_sOldMouseY = yPos;
- #if defined(_WINDOWS)
- HCURSOR hCurrentCursor = GetCursor();
- #endif
- if (xPos >= 0 && xPos < (INT16) m_pGIFCodec->GetLogicalScreenWidth() &&
- yPos >= 0 && yPos < (INT16) m_pGIFCodec->GetLogicalScreenHeight() &&
- m_cURL.length() > 0) // we have a link
- {
- // We ARE over a hyperlink
- #if defined(_WINDOWS)
- if(!m_hHyperlinkCursor)
- {
- m_hHyperlinkCursor = LoadCursor(g_hInstance, MAKEINTRESOURCE(HANDCURSOR));
- if(!m_hHyperlinkCursor)
- {
- m_hHyperlinkCursor = LoadCursor(NULL, IDC_UPARROW);
- }
- }
- if(m_hHyperlinkCursor && hCurrentCursor != m_hHyperlinkCursor)
- {
- // We're over a link and the cursor is NOT already the hyperlink cursor,
- // so change it. This will happen when we get a WM_SETCURSOR event
- m_bSetHyperlinkCursor = TRUE;
- }
- #elif defined(_MACINTOSH)
- if (m_hHyperlinkCursor)
- {
- ::SetCursor(*m_hHyperlinkCursor);
- m_eCurrentCursor = CURSOR_HYPERLINK;
- }
- #elif defined(_UNIX) && defined(USE_XWINDOWS)
- if (m_hCurrentCursor == -1 && m_pDisplay && m_Window && m_hHyperlinkCursor != -1)
- {
- XLockDisplay(m_pDisplay);
- XDefineCursor(m_pDisplay, m_Window, m_hHyperlinkCursor);
- XUnlockDisplay(m_pDisplay);
- m_hCurrentCursor = m_hHyperlinkCursor;
- }
- #endif
- if (m_pStatusMessage)
- {
- m_bStatusMsgWillNeedErasing = TRUE;
- m_pStatusMessage->SetStatus(m_cURL.c_str());
- }
- }
- else
- {
- // We are NOT over a hyperlink
- #if defined(_WINDOWS)
- if(hCurrentCursor == m_hHyperlinkCursor)
- {
- // We are not over a hyperlink and out cursor IS the hyperlink cursor,
- // so we need to change it back. This will happen when we get a WM_SETCURSOR event
- m_bSetHyperlinkCursor = FALSE;
- }
- #elif defined(_MACINTOSH)
- if (m_eCurrentCursor == CURSOR_HYPERLINK)
- {
- ::InitCursor();
- m_eCurrentCursor = CURSOR_ARROW;
- }
- #elif defined(_UNIX) && defined(USE_XWINDOWS)
- if (m_hCurrentCursor == m_hHyperlinkCursor)
- {
- if (m_pDisplay && m_Window)
- {
- XLockDisplay(m_pDisplay);
- XUndefineCursor(m_pDisplay, m_Window);
- XUnlockDisplay(m_pDisplay);
- m_hCurrentCursor = -1;
- }
- }
- #endif
- if (m_pStatusMessage &&
- // /Fixes PR 65008 (GIF version): only set this to NULL if we
- // have recently set the status message, otherwise we may
- // cause SMIL's setting of the status message to be
- // overwritten with NULL, i.e., erased:
- m_bStatusMsgWillNeedErasing)
- {
- m_bStatusMsgWillNeedErasing = FALSE;
- m_pStatusMessage->SetStatus(NULL);
- }
- }
- }
- STDMETHODIMP CGIFRenderer::HandleEvent(HXxEvent* pEvent)
- {
- HX_RESULT retVal = HXR_OK;
- if (pEvent)
- {
- // Set defaults
- pEvent->handled = FALSE;
- pEvent->result = 0;
- // Switch based on event type
- switch (pEvent->event)
- {
- case HX_SURFACE_UPDATE:
- {
- if (m_pOutputBuffer)
- {
- IHXVideoSurface *pSurface = (IHXVideoSurface *) (pEvent->param1);
- HXxSize size;
- m_pMISUSSite->GetSize(size);
- DrawToRMASurface(pSurface, 0, 0, size);
- }
- #if defined(_UNIX) && defined(USE_XWINDOWS)
- {
- HXxWindow *pWnd = (HXxWindow*)pEvent->param2;
- if (pWnd)
- {
- m_pDisplay = (Display*)pWnd->display;
- m_Window = (Window)pWnd->window;
- if (m_pDisplay && m_hHyperlinkCursor == -1)
- {
- XLockDisplay(m_pDisplay);
- m_hHyperlinkCursor = XCreateFontCursor(m_pDisplay,
- XC_hand2);
- XUnlockDisplay(m_pDisplay);
- }
- }
- }
- #endif
- pEvent->handled = TRUE;
- }
- break;
- case HX_SURFACE_UPDATE2:
- {
- HXxExposeInfo* pExpose = (HXxExposeInfo*)pEvent->param2;
- IHXSubRectVideoSurface* pSurface =
- (IHXSubRectVideoSurface*) pEvent->param1;
- if (pSurface)
- {
- pSurface->AddRef();
- RMASurfaceUpdate2(pSurface,
- &pExpose->extents,
- pExpose->pRegion);
- pSurface->Release();
- }
- pEvent->handled = TRUE;
- }
- break;
- case HX_MOUSE_ENTER:
- case HX_MOUSE_LEAVE:
- case HX_MOUSE_MOVE:
- {
- HXxPoint* mousePt = (HXxPoint*) pEvent->param1;
- OnMouseMove (0, (INT16)mousePt->x, (INT16)mousePt->y);
- pEvent->handled = TRUE;
- }
- break;
- case HX_PRIMARY_BUTTON_UP:
- {
- #if defined(HELIX_FEATURE_HYPER_NAVIGATE)
- HandleClick();
- #endif // (HELIX_FEATURE_HYPER_NAVIGATE)
- pEvent->handled = TRUE;
- }
- break;
- #ifdef _WINDOWS
- case WM_SETCURSOR:
- {
- if(m_bSetHyperlinkCursor)
- {
- pEvent->handled = TRUE;
- m_hPreHyperlinkCursor = SetCursor(m_hHyperlinkCursor);
- }
- else
- {
- // pngui will handle the setting of the cursor (back to arrow cursor)
- pEvent->handled = FALSE;
- }
- }
- break;
- #endif
- default:
- break;
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- return retVal;
- }
- void CGIFRenderer::DrawToRMASurface(IHXVideoSurface *pVideoSurface, UINT32 ulX, UINT32 ulY, const HXxSize &size)
- {
- #if defined(HELIX_FEATURE_GIF_BROKENIMAGE)
- if (m_bImageBombed && m_bNoNativeSize &&
- (size.cx != (INT32) m_ulWidth ||
- size.cy != (INT32) m_ulHeight))
- {
- // Copy the bomb image
- PXMakeBombImage* pMakeBomb = new PXMakeBombImage();
- if (pMakeBomb)
- {
- PXImage* pImage = NULL;
- HX_RESULT rv = pMakeBomb->MakeBombImage(m_pContext,
- (UINT32) size.cx,
- (UINT32) size.cy,
- m_ulBackgroundColor,
- pImage);
- if (SUCCEEDED(rv))
- {
- IHXBuffer* pImageStore = NULL;
- rv = pImage->GetImageStore(&pImageStore);
- if (SUCCEEDED(rv))
- {
- m_ulWidth = (UINT32) size.cx;
- m_ulHeight = (UINT32) size.cy;
- HX_RELEASE(m_pOutputBuffer);
- m_pOutputBuffer = pImageStore;
- m_pOutputBuffer->AddRef();
- }
- HX_RELEASE(pImageStore);
- }
- HX_RELEASE(pImage);
- }
- HX_DELETE(pMakeBomb);
- }
- #endif /* #if defined(HELIX_FEATURE_GIF_BROKENIMAGE) */
- if (m_pOutputBuffer)
- {
- pVideoSurface->AddRef();
- HXxRect rDestRect = { 0, 0, size.cx, size.cy};
- HXxRect rSrcRect = { 0, 0, m_ulWidth,
- m_ulHeight };
- HXBitmapInfoHeader cHeader;
- cHeader.biSize = 40;
- cHeader.biWidth = (INT32) m_ulWidth;
- cHeader.biHeight = (INT32) m_ulHeight;
- cHeader.biPlanes = 1;
- cHeader.biBitCount = 32;
- cHeader.biCompression = (m_bUsesAlphaChannel ? ARGB_CID : HX_RGB);
- cHeader.biSizeImage = 0;
- cHeader.biXPelsPerMeter = 0;
- cHeader.biYPelsPerMeter = 0;
- cHeader.biClrUsed = 0;
- cHeader.biClrImportant = 0;
- pVideoSurface->Blt(m_pOutputBuffer->GetBuffer(),
- &cHeader,
- rDestRect,
- rSrcRect);
- HX_RELEASE(pVideoSurface);
- }
- }
- HX_RESULT CGIFRenderer::RMASurfaceUpdate2(IHXSubRectVideoSurface* pSurface,
- HXxRect* pExtents,
- HXxBoxRegion* pDirtyRegion)
- {
- MLOG_MISC(m_pErrorMessages,
- "%lu RMASurfaceUpdate2() this=0x%08xn",
- HX_GET_BETTERTICKCOUNT(), this);
- HX_RESULT retVal = HXR_OK;
- if (pSurface && m_pMISUSSite && m_pOutputBuffer)
- {
- // Get the size of the site
- HXxSize size;
- m_pMISUSSite->GetSize(size);
- // Scale dirty rects.
- float fx = (float) m_ulWidth / (float) size.cx;
- float fy = (float) m_ulHeight / (float) size.cy;
- // Allocate space for the scaled subrects
- HXBOX* pSrcRects = new HXBOX[pDirtyRegion->numRects];
- if (pSrcRects)
- {
- // Go through each rect in the dirty region and scale it to
- // generate the src rects.
- INT32 i = 0;
- for(i = 0; i < pDirtyRegion->numRects; i++)
- {
- pSrcRects[i].x1 = (float) pDirtyRegion->rects[i].x1 * fx + 0.5;
- pSrcRects[i].x2 = (float) pDirtyRegion->rects[i].x2 * fx + 0.5;
- pSrcRects[i].y1 = (float) pDirtyRegion->rects[i].y1 * fy + 0.5;
- pSrcRects[i].y2 = (float) pDirtyRegion->rects[i].y2 * fy + 0.5;
- }
- // Set up Src region.
- HXxBoxRegion srcRegion;
- srcRegion.numRects = pDirtyRegion->numRects;
- srcRegion.rects = pSrcRects;
- // Set the values in the bitmap info header
- HXBitmapInfoHeader cHeader;
- cHeader.biSize = 40;
- cHeader.biWidth = m_ulWidth;
- cHeader.biHeight = m_ulHeight;
- cHeader.biPlanes = 1;
- cHeader.biBitCount = 32;
- cHeader.biCompression = (m_bUsesAlphaChannel ? ARGB_CID : HX_RGB);
- cHeader.biSizeImage = 0;
- cHeader.biXPelsPerMeter = 0;
- cHeader.biYPelsPerMeter = 0;
- cHeader.biClrUsed = 0;
- cHeader.biClrImportant = 0;
- cHeader.rcolor = 0;
- cHeader.gcolor = 0;
- cHeader.bcolor = 0;
- // Blit to the video surface
- MLOG_MISC(m_pErrorMessages,
- " numRects=%ldn",
- srcRegion.numRects);
- for (i = 0; i < srcRegion.numRects; i++)
- {
- MLOG_MISC(m_pErrorMessages,
- " rect[%ld] = (%d,%d,%d,%d)n",
- i,
- srcRegion.rects[i].x1,
- srcRegion.rects[i].y1,
- srcRegion.rects[i].x2,
- srcRegion.rects[i].y2);
- }
- pSurface->BltSubRects(m_pOutputBuffer->GetBuffer(),
- &cHeader,
- pDirtyRegion,
- &srcRegion,
- 1.0/fx, 1.0/fy);
- }
- HX_VECTOR_DELETE(pSrcRects);
- }
- else
- {
- retVal = HXR_FAIL;
- }
- return retVal;
- }
- void CGIFRenderer::HandleClick()
- {
- #if defined(HELIX_FEATURE_HYPER_NAVIGATE)
- if (m_pHyperNavigate && m_cURL.length() > 0)
- {
- m_pHyperNavigate->GoToURL(m_cURL.c_str(), (m_ucTarget == kTargetPlayer) ? "_player" : (const char*) NULL);
- }
- #endif // (HELIX_FEATURE_HYPER_NAVIGATE)
- }
- HX_RESULT CGIFRenderer::CopyBombImage()
- {
- HX_RESULT retVal = HXR_OK;
- #if defined(HELIX_FEATURE_GIF_BROKENIMAGE)
- // Set the image bombed flag
- m_bImageBombed = TRUE;
- // Copy the bomb image
- PXMakeBombImage* pMakeBomb = new PXMakeBombImage();
- if (pMakeBomb)
- {
- PXImage* pImage = NULL;
- retVal = pMakeBomb->MakeBombImage(m_pContext,
- m_ulWidth,
- m_ulHeight,
- m_ulBackgroundColor,
- pImage);
- if (SUCCEEDED(retVal))
- {
- IHXBuffer* pImageStore = NULL;
- retVal = pImage->GetImageStore(&pImageStore);
- if (SUCCEEDED(retVal))
- {
- UINT32 ulSafeSizeToCopy = pImageStore->GetSize();
- UINT32 ulOutputBufSize = m_pOutputBuffer->GetSize();
- if (ulSafeSizeToCopy > ulOutputBufSize)
- {
- ulSafeSizeToCopy = ulOutputBufSize;
- }
- memcpy(m_pOutputBuffer->GetBuffer(), /* Flawfinder: ignore */
- pImageStore->GetBuffer(),
- ulSafeSizeToCopy);
- }
- HX_RELEASE(pImageStore);
- }
- HX_RELEASE(pImage);
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- HX_DELETE(pMakeBomb);
- #endif /* #if defined(HELIX_FEATURE_GIF_BROKENIMAGE) */
- return retVal;
- }
- void CGIFRenderer::DrawBackgroundColor()
- {
- if (m_pOutputBuffer)
- {
- // Combine background color and background opacity
- UINT32 ulBgAlpha = 255 - m_ulBackgroundOpacity;
- m_ulBackgroundColor = (m_ulBackgroundColor & 0x00FFFFFF) |
- ((ulBgAlpha << 24) & 0xFF000000);
- // Fill the output buffer with the background color
- UINT32 ulNumPixels = m_ulWidth * m_ulHeight;
- UINT32* pDst = (UINT32*) m_pOutputBuffer->GetBuffer();
- while (ulNumPixels--)
- {
- *pDst++ = m_ulBackgroundColor;
- }
- }
- }
- UINT32 CGIFRenderer::GetCycleTime()
- {
- UINT32 ulRet = 0;
- if (m_pGIFCodec)
- {
- UINT32 ulNumFrames = m_pGIFCodec->GetNumImages();
- for (UINT32 i = 0; i < ulNumFrames; i++)
- {
- CGIFImage* pFrame = m_pGIFCodec->GetImage(i);
- if (pFrame)
- {
- // Get delay in ms
- UINT32 ulFrameDelay = pFrame->GetDelayTime() * 10;
- // Add this delay to the total
- ulRet += ulFrameDelay;
- }
- }
- }
- return ulRet;
- }
- UINT32 CGIFRenderer::GetNextFrameTime(UINT32 ulTime)
- {
- UINT32 ulRet = ulTime;
- if (m_pGIFCodec)
- {
- UINT32 ulCycleTime = GetCycleTime();
- if (ulCycleTime)
- {
- // Get the modulo time
- UINT32 ulIter = ulTime / ulCycleTime;
- UINT32 ulIterStart = ulIter * ulCycleTime;
- UINT32 ulModTime = ulTime - ulIterStart;
- // Now see which frame is next after this time
- UINT32 ulNumFrames = m_pGIFCodec->GetNumImages();
- UINT32 ulCurFrameStart = 0;
- for (UINT32 i = 0; i < ulNumFrames; i++)
- {
- CGIFImage* pFrame = m_pGIFCodec->GetImage(i);
- if (pFrame)
- {
- // Get this frame's delay in ms
- UINT32 ulFrameDelay = pFrame->GetDelayTime() * 10;
- // Get the ending time of this frame
- UINT32 ulCurFrameEnd = ulCurFrameStart + ulFrameDelay;
- // Is this time in this frame's range?
- if (ulModTime >= ulCurFrameStart &&
- ulModTime < ulCurFrameEnd)
- {
- // We found the right frame, so make
- // sure and add back in the time that this
- // iteration started.
- ulRet = ulIterStart + ulCurFrameEnd;
- break;
- }
- // Add the delay of this frame to the running sum
- ulCurFrameStart += ulFrameDelay;
- }
- }
- }
- }
- return ulRet;
- }
- UINT32 CGIFRenderer::GetTimevalDiff(HXTimeval t1, HXTimeval t2)
- {
- UINT32 ulRet = 0;
- // Compute the sec diff with 32-bit wrap
- HXTimeval cDiff = {0, 0};
- if (t2.tv_sec >= t1.tv_sec)
- {
- cDiff.tv_sec = t2.tv_sec - t1.tv_sec;
- }
- else
- {
- cDiff.tv_sec = 0xFFFFFFFF - t2.tv_sec + t1.tv_sec;
- }
- // Compute the usec diff
- if (t2.tv_usec >= t1.tv_usec)
- {
- cDiff.tv_usec = t2.tv_usec - t1.tv_usec;
- }
- else
- {
- // We have to borrow from the sec diff
- if (cDiff.tv_sec > 0)
- {
- cDiff.tv_usec = 1000000 + t2.tv_usec - t1.tv_usec;
- cDiff.tv_sec -= 1;
- }
- }
- // Convert diff to milliseconds
- ulRet = (cDiff.tv_sec * 1000) + ((cDiff.tv_usec + 500) / 1000);
- return ulRet;
- }
- HX_RESULT STDAPICALLTYPE CGIFRenderer::HXCreateInstance(IUnknown** ppIUnknown)
- {
- HX_RESULT retVal = HXR_OK;
- if (ppIUnknown)
- {
- // Set default
- *ppIUnknown = NULL;
- // Create the object
- CGIFRenderer *pObj = new CGIFRenderer();
- if (pObj)
- {
- // QI for IUnknown
- retVal = pObj->QueryInterface(IID_IUnknown, (void**) ppIUnknown);
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- if (FAILED(retVal))
- {
- HX_DELETE(pObj);
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- return HXR_OK;
- }
- void CGIFRenderer::DamageFrameRect(UINT32 i)
- {
- if (m_pGIFCodec &&
- m_pMISUSSite &&
- i < m_pGIFCodec->GetNumImages())
- {
- CGIFImage* pImg = m_pGIFCodec->GetImage(i);
- if (pImg)
- {
- // Get the rect for the frame
- HXxRect cRect;
- cRect.left = (INT32) pImg->GetImageLeft();
- cRect.top = (INT32) pImg->GetImageTop();
- cRect.right = cRect.left + (INT32) pImg->GetImageWidth();
- cRect.bottom = cRect.top + (INT32) pImg->GetImageHeight();
- // Get the size of the logical screen
- HXxSize cLSSize = {0, 0};
- cLSSize.cx = (INT32) m_pGIFCodec->GetLogicalScreenWidth();
- cLSSize.cy = (INT32) m_pGIFCodec->GetLogicalScreenHeight();
- // Get the current size of the site
- HXxSize cSiteSize = {0, 0};
- m_pMISUSSite->GetSize(cSiteSize);
- // If the current size of the site is not the
- // same as the logical screen, then we need to scale the
- // damage rect
- if (cSiteSize.cx != cLSSize.cx ||
- cSiteSize.cy != cLSSize.cy)
- {
- // Scale the damage rect
- cRect.left = cRect.left * cSiteSize.cx / cLSSize.cx;
- cRect.top = cRect.top * cSiteSize.cy / cLSSize.cy;
- cRect.right = cRect.right * cSiteSize.cx / cLSSize.cx;
- cRect.bottom = cRect.bottom * cSiteSize.cy / cLSSize.cy;
- }
- // Damage this rect
- MLOG_MISC(m_pErrorMessages,
- "tDamaging Frame %lu: (%ld,%ld,%ld,%ld) (%ld x %ld)n",
- i, cRect.left, cRect.top, cRect.right, cRect.bottom,
- HXxRECT_WIDTH(cRect), HXxRECT_HEIGHT(cRect));
- m_pMISUSSite->DamageRect(cRect);
- }
- }
- }