smlelem.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:89k
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: RCSL 1.0/RPSL 1.0
- *
- * Portions Copyright (c) 1995-2002 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 ***** */
- // system
- #include <time.h>
- // include
- #include "hxtypes.h"
- #include "hxwintyp.h"
- #include "hxcom.h"
- #include "ihxpckts.h"
- #include "hxxml.h"
- #include "smiltype.h"
- // pncont
- #include "hxstring.h"
- #include "hxslist.h"
- #include "hxstack.h"
- #include "chxpckts.h"
- // pnmisc
- #include "nptime.h"
- #include "smpte.h"
- #include "hxwinver.h"
- #include "hxstrutl.h" /* for new_string(). */
- // rnxmllib
- #include "hxxmlprs.h"
- // rmasmil
- #include "smlparse.h"
- #include "smltime.h"
- #include "smlprstime.h"
- #include "animattr.h"
- #include "smlelem.h"
- // pndebug
- #include "hxheap.h"
- #ifdef _DEBUG
- #undef HX_THIS_FILE
- static const char HX_THIS_FILE[] = __FILE__;
- #endif
-
- /*
- * CSmilElement methods
- */
- CSmilElement::CSmilElement(SMILNode* pNode):
- m_pNode(pNode),
- m_lBeginOffset(0),
- m_bBeginOffsetSet(FALSE),
- m_bNegBeginOffsetAlreadyUsed(FALSE),
- m_bCurBeginIsOffsetFromSyncBase(FALSE),
- m_ulBeginOffsetFromSyncBase((UINT32)-1),
- m_ulClipBegin((UINT32)-1),
- m_ulAuthoredClipBegin((UINT32)-1),
- m_ulClipEnd((UINT32)-1),
- m_ulDelay((UINT32)-1),
- m_ulDuration((UINT32)-1),
- m_ulOriginalDuration((UINT32)-1),
- m_ulDurationInAddTrack((UINT32)-1),
- m_bCurEndClippedByParent(FALSE),
- m_ulMaxDuration((UINT32)-1),
- m_ulMaxActiveDur((UINT32)-1),
- m_ulMinActiveDur(0),
- m_ulAuthoredDur((UINT32)-1),
- m_bHasExplicitDur(FALSE),
- m_bHasExplicitEnd(FALSE),
- m_bDurationIncludesDelayBeyondSyncbase(FALSE),
- m_bAddDurationAlreadyDone(FALSE),
- m_bUseMediaDurForMinDur(FALSE),
- m_bUseMediaDurForMaxDur(FALSE),
- m_lEndOffset(0),
- m_bEndOffsetSet(FALSE),
- m_ulAnticipatedPauseDur(0),
- m_ulEndSync((UINT32)-1),
- m_fRepeatValue(1.0),
- m_ulTimestamp(0),
- m_bInsertedIntoTimeline(FALSE),
- m_bHasBeenScheduled(FALSE),
- m_bIsPausedInExcl(FALSE),
- m_bIsDeferredInExcl(FALSE),
- m_ulTimeDeferralOccurred((UINT32)-1),
- m_bIsStoppedInExcl(FALSE),
- m_ulStopTimeInExcl((UINT32)-1),
- m_bCurrentSourceIsLive(FALSE),
- m_bRendererInitialized(FALSE),
- m_bIsRestarting(FALSE),
- m_bAwaitingSyncAncestorBeginNotification(FALSE),
- m_ulLongSyncArcBeginInGroupTime((UINT32)-1),
- m_bIndefiniteDuration(FALSE),
- m_bIndefiniteEnd(FALSE),
- m_bIndefiniteBegin(FALSE),
- m_restartBehavior(SmilRestartAlways),
- m_restartDefaultBehavior(SmilRestartInherit),
- // /Defaults to "default" which means use val of syncToleranceDefault:
- m_ulSyncTolerance((UINT32)-1),
- // /Defaults to "inherit"; if there is no parent timed element, then
- // it is implementation-dependent (but should be less than or = 2s):
- m_ulSyncToleranceDefault((UINT32)-1),
- m_syncBehavior(SmilSyncBehaviorDefault),
- m_syncBehaviorDefault(SmilSyncBehaviorInherit),
- m_ulReadIndex(0),
- m_nBeginEventSourceTag(SMILEventSourceNone),
- m_nEndEventSourceTag(SMILEventSourceNone),
- m_nEndsyncEventSourceTag(SMILEventSourceNone),
- m_lBeginEventClockValue(0),
- m_lEndEventClockValue(0),
- m_pHandler(0),
- m_pTimelineElement(NULL),
- m_pBeginTimeList(NULL),
- m_pEndTimeList(NULL),
- m_bWallClockBegin(FALSE),
- m_bWallClockEnd(FALSE),
- m_bHasAtLeastOneEventBasedBegin(FALSE),
- m_bHasAtLeastOneNonEventBasedBegin(FALSE),
- m_eFill(FillDefault),
- m_eFillDefault(FillDefaultInherit),
- m_eActualFill(FillDefault),
- m_eErase(EraseWhenDone),
- m_ulRemoveTime(((UINT32) -1)),
- m_bUsesExternalMediaMarkerFile(FALSE),
- m_bClipBeginUsesMarker(FALSE),
- m_bClipBeginMarkerResolved(FALSE),
- m_bWaitingOnClipBeginToResolve(FALSE),
- m_pszClipBeginMarkerName(NULL),
- m_pszClipBeginExternalMarkerFileName(NULL),
- m_bClipEndUsesMarker(FALSE),
- m_bClipEndMarkerResolved(FALSE),
- m_bWaitingOnClipEndToResolve(FALSE),
- m_pszClipEndMarkerName(NULL),
- m_pszClipEndExternalMarkerFileName(NULL),
- m_eAccessErrorBehavior(AccessErrorBehaviorInherit)
- {
- // /XXXEH- we may need to set m_bIndefiniteBegin to TRUE if
- // hasAncestor(SMILExcl, this), but setInitialDelay() fix seems to be
- // all we need (...<==famous last words).
- m_pHyperlinks = new CHXSimpleList;
- getParentRestartDefault();
- }
- CSmilElement::~CSmilElement()
- {
- if (m_pBeginTimeList)
- {
- CHXSimpleList::Iterator ndx = m_pBeginTimeList->Begin();
- for (; ndx != m_pBeginTimeList->End(); ++ndx)
- {
- SmilTimeValue* pTV = (SmilTimeValue*)(*ndx);
- HX_DELETE(pTV);
- }
- HX_DELETE(m_pBeginTimeList);
- }
- if (m_pEndTimeList)
- {
- CHXSimpleList::Iterator ndx = m_pEndTimeList->Begin();
- for (; ndx != m_pEndTimeList->End(); ++ndx)
- {
- SmilTimeValue* pTV = (SmilTimeValue*)(*ndx);
- HX_DELETE(pTV);
- }
- HX_DELETE(m_pEndTimeList);
- }
- HX_DELETE(m_pHyperlinks);
- HX_DELETE(m_pTimelineElement);
- HX_VECTOR_DELETE(m_pszClipBeginMarkerName);
- HX_VECTOR_DELETE(m_pszClipBeginExternalMarkerFileName);
- HX_VECTOR_DELETE(m_pszClipEndMarkerName);
- HX_VECTOR_DELETE(m_pszClipEndExternalMarkerFileName);
- }
- void
- CSmilElement::addDuration(UINT32 ulDuration)
- {
- // default add duration just attempts to add it to it's parent
- m_ulDuration = ulDuration;
- if(m_pNode->m_pParent && m_pNode->m_pParent->m_pElement)
- {
- m_pNode->m_pParent->m_pElement->addDuration(m_ulDuration);
- m_bAddDurationAlreadyDone = TRUE;
- }
- }
- void
- CSmilElement::addElement(CSmilElement* pElement,
- UINT32& ulBeginOffset, UINT32& ulDuration)
- {
- }
- void
- CSmilElement::prepForRestart(BOOL bParentIsRestarting, LONG32 lWhen)
- {
- m_bInsertedIntoTimeline = FALSE;
- m_bRendererInitialized = FALSE;
- m_bBeginOffsetSet = FALSE;
- // /Reset these, too, or hiding of site will happen too early next time:
- m_bCurBeginIsOffsetFromSyncBase = TRUE;
- // /This seems to work fine in case where begin="x; y" where x is a
- // clock value and y is an event-arc that resolves at/to a time prior
- // to x. (The other option is to set m_bCurBeginIsOffsetFromSyncBase
- // to FALSE when !m_bBeginOffsetSet):
- m_ulBeginOffsetFromSyncBase = 0;
- m_bNegBeginOffsetAlreadyUsed = FALSE;
- m_ulClipBegin = m_ulAuthoredClipBegin;
- m_bAddDurationAlreadyDone = FALSE;
- // /XXXEH- TODO: test this!:
- m_bDurationIncludesDelayBeyondSyncbase = FALSE;
- m_bIsPausedInExcl = FALSE;
- m_bIsDeferredInExcl = FALSE;
- m_ulTimeDeferralOccurred = (UINT32)-1;
- m_bIsStoppedInExcl = FALSE;
- m_ulAnticipatedPauseDur = 0;
- // /If we restart a source, the next play may be a different file, even
- // live one time and on-demand the next, so reset this and let next call
- // to TrackDurationSet() tell us if it's live this time:
- m_bCurrentSourceIsLive = FALSE;
- // /Adding this helps fix a lot of restart problems, including part of
- // PR 62408 and par version of PR 50660. The playToAssoc was never
- // removed when the track ended the first time, so the doc renderer
- // (m_pHandler) used to see this track as already added and would
- // erroneously add this restart as a repeat track:
- m_bIsRestarting = TRUE;
- // /Helps fix restart problems related to PR 55253:
- if (bParentIsRestarting)
- {
- LONG32 lNextResolvedEndTime = 0;
- BOOL bHasFutureResolvedEnd = FALSE;
- if (m_bHasExplicitEnd)
- {
- SmilTimeValue* pNextResolvedEndTimeValue = NULL;
- HX_RESULT rettimeval = HXR_OK;
- // /lWhen must be in syncBase time space, not group time space:
- rettimeval = getNextResolvedTimeValue(pNextResolvedEndTimeValue,
- SMILTIME_NEGATIVE_INFINITY, lWhen, SmilEndTimeList, NULL);
- if (SUCCEEDED(rettimeval) && NULL != pNextResolvedEndTimeValue)
- {
- HX_RESULT rtval = pNextResolvedEndTimeValue->
- getEffectiveResolvedTime(lNextResolvedEndTime);
- if (SUCCEEDED(rtval))
- {
- bHasFutureResolvedEnd = TRUE;
- if (lWhen < lNextResolvedEndTime)
- {
- m_ulDuration = (UINT32)(lNextResolvedEndTime - lWhen);
- }
- }
- }
- }
- if (m_bHasExplicitDur)
- {
- if (!bHasFutureResolvedEnd)
- {
- m_ulDuration = m_ulAuthoredDur;
- }
- else if (lNextResolvedEndTime - lWhen > (LONG32)m_ulAuthoredDur)
- {
- m_ulDuration = m_ulAuthoredDur;
- }
- }
- else
- {
- // /Let SetDelay() and insertTimeline... deal with new duration:
- m_ulDuration = (UINT32)-1;
- }
- }
- // /Reset the delay since it will be new, obviously, for this restart;
- // helps fix restart problems related to PR 56233:
- m_ulDelay = (UINT32)-1;
- // /Note: we don't want to or need to reset the delay here. A restart
- // based on either a syncArc or eventArc will take care of that.
- if (m_pTimelineElement)
- {
- m_pTimelineElement->prepForRestart();
- }
- // /Now, call this function for all descendants as well in case this is
- // a time container (or a media object with timeline-element children);
- // (Helps fix restart problems related to PR 55253)
- SMILNode* pChild = m_pNode->getFirstChild();
- while (pChild)
- {
- CSmilElement* pElement = pChild->m_pElement;
- if (pElement && pElement->m_pHandler &&
- pElement->m_bInsertedIntoTimeline)
- {
- pElement->prepForRestart(TRUE, lWhen);
- }
- pChild = m_pNode->getNextChild();
- }
- }
- void
- CSmilElement::prepForPauseInExcl(LONG32 lCurTime)
- {
- m_bIsPausedInExcl = TRUE;
- // /If we're being set to paused state, then we need to adjust our hide
- // event (removeTime) in concert with adjusting when we will end:
- BOOL bHasFutureResolvedExplicitEnd = FALSE;
- if (m_bHasExplicitEnd)
- {
- SmilTimeValue* pNextResolvedEndTimeValue = NULL;
- HX_RESULT rettimeval = HXR_OK;
- // /lCurTime must be in syncBase time space, not group time space:
- rettimeval = getNextResolvedTimeValue(pNextResolvedEndTimeValue,
- SMILTIME_NEGATIVE_INFINITY, lCurTime, SmilEndTimeList, NULL);
- if (SUCCEEDED(rettimeval) && NULL != pNextResolvedEndTimeValue)
- {
- LONG32 lNextResolvedEndTime = SMILTIME_NEGATIVE_INFINITY;
- HX_RESULT rtval = pNextResolvedEndTimeValue->
- getEffectiveResolvedTime(lNextResolvedEndTime);
- if (SUCCEEDED(rtval))
- {
- HX_ASSERT(lCurTime <= lNextResolvedEndTime);
- bHasFutureResolvedExplicitEnd = TRUE;
- updateRemoveTime(lNextResolvedEndTime);
- }
- }
- }
- // /If we don't have explicit end, then we'll end when we get resumed
- // plus the remainder of our duration:
- if (!bHasFutureResolvedExplicitEnd)
- {
- updateRemoveTime(SMILTIME_PAUSED_INDEFINITELY);
- }
- }
- void
- CSmilElement::prepForResumeInExcl()
- {
- HX_ASSERT(m_bIsPausedInExcl);
- LISTPOSITION lPos = NULL;
- HX_ASSERT(m_pBeginTimeList);
- if (m_pBeginTimeList)
- {
- lPos = m_pBeginTimeList->GetHeadPosition();
- }
- while (lPos)
- {
- SmilTimeValue* pTimeVal =
- (SmilTimeValue*)m_pBeginTimeList->GetAt(lPos);
- // /There should be only one resumeEvent:
- if (pTimeVal && pTimeVal->isResumeEvent())
- {
- // /Fixes PR 62408: remove resumeEvent from element's begin
- // list since it was an internally-generated single-use begin
- // value and we don't want it to re-resolve when (if) the
- // original pausing element restarts and then raises another
- // resumeEvent when it ends again:
- m_pBeginTimeList->RemoveAt(lPos);
- break;
- }
- m_pBeginTimeList->GetNext(lPos);
- }
- m_bIsPausedInExcl = FALSE;
- }
- void
- CSmilElement::prepForStopInExcl(LONG32 lCurTime)
- {
- m_bIsStoppedInExcl = TRUE;
- m_ulStopTimeInExcl = (ULONG32)lCurTime;
- }
- void
- CSmilElement::prepForDeferralInExcl(UINT32 lCurTime)
- {
- m_ulTimeDeferralOccurred = lCurTime;
- m_bIsDeferredInExcl = TRUE;
- }
- HX_RESULT
- CSmilElement::setBeginTime(CSmilParser* pParser)
- {
- HX_RESULT ret = HXR_OK;
-
- BOOL bBeginTimeHasBeenSet = FALSE;
- UINT32 ulOffset = 0;
- SmilTimeValue* pNextResolvedTimeValue = NULL;
- LISTPOSITION lPos = NULL;
- // /We need this so we can go through
- CHXSimpleList* pListOfAllResolvedBeginTimes = new CHXSimpleList;
- // /Looks at all resolved begin times in the list and
- // returns the SmilTimeValue with the closest time at or
- // later than the time passed in:
- HX_RESULT rettimeval = HXR_OK;
- rettimeval = getNextResolvedTimeValue(pNextResolvedTimeValue,
- SMILTIME_NEGATIVE_INFINITY, SMILTIME_NEGATIVE_INFINITY,
- SmilBeginTimeList, pListOfAllResolvedBeginTimes);
- // /NOTE: ret!=HXR_OK is NOT an error condition; it means
- // that no value in the begin time list was found that was
- // resolved.
- BOOL bIsDescendantOfExcl = pParser->hasAncestor(SMILExcl, m_pNode);
- SMILNode* pSyncAncestor = pParser->getSyncAncestor(m_pNode);
- HX_ASSERT(pSyncAncestor);
- // make sure that we do not have an illegal begin value
- // if we have a seq for a parent.
- // /Note: we want to use our sync ancestor, not our parent, because
- // our parent could be a non-time-container like <a>, <switch>,
- // or <priorityClass>:
- if ((pSyncAncestor && SMILSeq == pSyncAncestor->m_tag &&
- // /OK if parent seq was created to expand for repeat purposes:
- !m_pNode->m_bRepeatHandled) &&
- ( (!SUCCEEDED(rettimeval) || NULL==pNextResolvedTimeValue) ||
- (pNextResolvedTimeValue->m_type != SmilTimeOffset &&
- pNextResolvedTimeValue->m_type != SmilTimeClockValue) ) )
- {
- // only offsets are legal values...
- ret = HXR_INVALID_PARAMETER;
- goto cleanup;
- }
- // /For excl descendants, we don't want to declare that a begin time
- // has been set, because we need to figure out whether or not to
- // schedule it based on when other excl children begin (which we may
- // not know yet):
- if (SUCCEEDED(rettimeval) && NULL != pNextResolvedTimeValue)
- {
- if (pListOfAllResolvedBeginTimes)
- {
- // /Go through this list and insert each into the pending list:
- LISTPOSITION lPosTmp =
- pListOfAllResolvedBeginTimes->GetHeadPosition();
- while (lPosTmp)
- {
- SmilTimeValue* pTmpVal = (SmilTimeValue*)
- pListOfAllResolvedBeginTimes->GetAt(lPosTmp);
- if (pTmpVal && pTmpVal->isTimeResolved() &&
- pTmpVal->m_pElement)
- {
- if (pTmpVal != pNextResolvedTimeValue ||
- bIsDescendantOfExcl)
- {
- // /(?XXXEH- TODO: insert into list based on resolved
- // time? note that begin="20s;0s" works OK, so...?)
- if (pParser->EstablishBeginTimeList())
- {
- CHXSimpleList* pList =
- pParser->GetPendingBeginTimeList();
- // /Don't add if it's a duplicate:
- if (!pParser->isDuplicateEntry(pList, pTmpVal))
- {
- pList->AddTail(pTmpVal);
- }
- }
- }
- }
- else
- {
- HX_ASSERT(0 && "timeval invalid");
- }
- pListOfAllResolvedBeginTimes->GetNext(lPosTmp);
- } // /end while(lPos...).
- }
- HX_DELETE(pListOfAllResolvedBeginTimes);
-
- if (!bIsDescendantOfExcl)
- {
- bBeginTimeHasBeenSet = TRUE;
- HX_ASSERT(pNextResolvedTimeValue->isTimeResolved());
- switch (pNextResolvedTimeValue->m_type)
- {
- case SmilTimeOffset:
- case SmilTimeClockValue:
- {
- // /XXXEH- is this what we really want to do?
- // Alternatively, we could have resolved-to "base" time
- // as 0 and then m_lOffset is added to get resolved-to
- // "offset" time:
- m_lBeginOffset = pNextResolvedTimeValue->getTimeOffset();
- m_bBeginOffsetSet = TRUE;
- // /Handle this now for time containers who never get
- // called with a TrackDurationSet():
- m_bCurBeginIsOffsetFromSyncBase = TRUE;
- m_ulBeginOffsetFromSyncBase = m_lBeginOffset;
- #if defined(_DEBUG) // /XXXEH- testing!:
- LONG32 lResolvedToTime = 0;
- HX_RESULT tmprslt =
- pNextResolvedTimeValue->getEffectiveResolvedTime(
- lResolvedToTime);
- HX_ASSERT(tmprslt==HXR_OK &&
- m_lBeginOffset == lResolvedToTime);
- #endif
- }
- break;
- case SmilTimeEvent:
- #if defined(ENABLE_SYNC_TO_PREV)
- case SmilTimeSyncToPrev:
- #endif
- case SmilTimeSyncBase:
- {
- // /NOTE: this's time must be *resolved* already which
- // shouldn't happen yet:
- HX_ASSERT(!pNextResolvedTimeValue->isTimeResolved());
- }
- break;
- case SmilTimeMediaMarker:
- {
- HX_ASSERT(!pNextResolvedTimeValue->isTimeResolved());
- }
- break;
- case SmilTimeWallclock:
- {
- // /XXXEH- wouldn't it be better to use
- // getEffectiveResolvedTime() here(?) so as to treat all time
- // types consistently?
- m_lBeginOffset = pNextResolvedTimeValue->getTimeOffset();
- m_bBeginOffsetSet = TRUE;
- // /Handle this now for time containers who never get
- // called with a TrackDurationSet():
- m_bCurBeginIsOffsetFromSyncBase = TRUE;
- m_ulBeginOffsetFromSyncBase = m_lBeginOffset;
- m_bWallClockBegin = TRUE;
- }
- break;
- default:
- HX_ASSERT(0);
- break;
- } // /end of "switch(pNextResolvedTimeValue->m_type)".
- } // /end of "if (!bIsDescendantOfExcl)".
- }
- // /Now, go through all unresolved begin times and add this element to
- // the appropriate list(s) for each unresolved time value found:
- if (m_pBeginTimeList)
- {
- lPos = m_pBeginTimeList->GetHeadPosition();
- }
- if (NULL == lPos) // /list is empty.
- {
- goto cleanup;
- }
- while (lPos && HXR_OK == ret)
- {
- SmilTimeValue* pTmpVal = (SmilTimeValue*)m_pBeginTimeList->GetAt(lPos);
- if (pTmpVal && !pTmpVal->isTimeResolved())
- {
- switch (pTmpVal->m_type)
- {
- case SmilTimeOffset:
- case SmilTimeClockValue:
- {
- // /We shouldn't ever get here because clock times are
- // always resolved:
- HX_ASSERT(pTmpVal->isTimeResolved());
- }
- break;
- case SmilTimeSyncBase:
- {
- pParser->addBeginTimeSyncElement(this);
- if (!bBeginTimeHasBeenSet)
- {
- m_BeginEventSourceID = pTmpVal->m_idRef;
- m_nBeginEventSourceTag = pTmpVal->m_position;
- // /NOTE: this is unresolved:
- m_lBeginEventClockValue =
- pTmpVal->getTimeOffset();
- }
- // /Fixes BUG-20010521_syncArcToElementWith...smil
- // where begin="0s;x.end" and x.end was being ignored:
- else
- {
- if (!m_BeginEventSourceID.GetLength())
- {
- m_BeginEventSourceID = pTmpVal->m_idRef;
- m_nBeginEventSourceTag = pTmpVal->m_position;
- // /NOTE: this is unresolved:
- m_lBeginEventClockValue = pTmpVal->getTimeOffset();
- }
- else
- {
- HX_ASSERT(0 &&
- "XXXEHodge: need to handle multiple sync-arc begins");
- // /XXXEH- TODO: if m_BeginEventSourceID is already
- // set due to another sync-arc begin time, we need
- // to have a list of m_BeginEventSourceID's & ...etc.
- // Currently, just the first one wins. We could
- // treat this sync-arc as a beginEvent event-arc...
- // (We also need to handle this in SetEndTime().)
- }
- }
- }
- break;
- #if defined(ENABLE_SYNC_TO_PREV)
- case SmilTimeSyncToPrev:
- {
- // /XXXEH- shouldn't we treat this just like we treat the
- // sync base case above by doing the following?:
- // pParser->addBeginTimeSyncElement(this);
- // /XXXEH- make sure we handle begin="3s; prev.end" where
- // both are valid times; the following doesn't handle this
- // case:
- if (!bBeginTimeHasBeenSet)
- {
- SMILNode* pSibling =
- m_pNode->m_pParent->getFirstChild();
- // /Spec says to use parent time container's begin if
- // m_pNode is the first child (and has no prev
- // sibling):
- SMILNode* pLastNode = m_pNode->m_pParent;
- while (pSibling)
- {
- if (pSibling->m_id == m_pNode->m_id)
- {
- // we found our boy...
- break;
- }
- pLastNode = pSibling;
- // /XXXEH- TODO: skip over children that aren't
- // *timed* elements, e.g., <a> tags; maybe we
- // are supposed to use a non-timed-prev-element's
- // last timed child, if any, and, if none exists,
- // use it's prev timed sibling???:
- pSibling = m_pNode->m_pParent->getNextChild();
- }
- HX_ASSERT(pSibling && pLastNode);
- if (pSibling && pLastNode)
- {
- // /First, if we had no prev sibling, then
- // we need to use our parent time container's
- // begin time as our sync base:
- if (pLastNode == m_pNode->m_pParent)
- {
- SMILNode* pFirstTimeContainerAncestor =
- pParser->getSyncAncestor(m_pNode);
- // /There should ALWAYS be a time container
- // ancestor, even if it's the implied seq
- // that we create when no time container
- // exists as the 1st timed child of the body:
- HX_ASSERT(pFirstTimeContainerAncestor);
- if (pFirstTimeContainerAncestor)
- {
- #if XXXEH_
- /* /Need to figure out if this is earlier than any current times and, if
- so, call insertElementWithPendingBeginOrEnd() with the earlier time, else
- call insertElementWithPendingBeginOrEnd() with this (pTmpVal) time:
- */
- #endif
- // /For parent as prev, we can just treat
- // this as a SmilTimeOffset value since
- // they're essentially the same thing:
- pLastNode = pFirstTimeContainerAncestor;
- m_lBeginOffset= pTmpVal->getTimeOffset();
- pTmpVal->m_type = SmilTimeOffset;
- pTmpVal->setIsTimeResolved(TRUE);
- m_bBeginOffsetSet = TRUE;
- }
- // /else give up; can't do anything here.
- }
- else // /Use prev sibling time:
- {
- m_BeginEventSourceID = pLastNode->m_id;
- // /XXXEH- wouldn't it be better to use
- // getEffectiveResolvedTime() here(?) so as
- // to treat all time types consistently?
- m_lBeginEventClockValue =
- pTmpVal->getTimeOffset();
- m_nBeginEventSourceTag =
- pTmpVal->m_position;
- }
- }
- else
- {
- ret = HXR_FAIL;
- }
- }
- }
- break;
- #endif
- case SmilTimeEvent:
- {
- pParser->addBeginEventElement(pTmpVal);
- }
- break;
- case SmilTimeMediaMarker:
- {
- pParser->addBeginMediaMarkerSyncElement(pTmpVal);
- }
- break;
- case SmilTimeWallclock:
- {
- // /We shouldn't ever get here because wallclock times
- // are always resolved:
- HX_ASSERT(pTmpVal->isTimeResolved());
- }
- break;
- default:
- HX_ASSERT(0);
- break;
- } // /end switch(pTmpVal->m_type).
- }
- m_pBeginTimeList->GetNext(lPos);
- } // /end while (lPos ...).
- // else time must already be set.
- cleanup:
- return ret;
- }
- HX_RESULT
- CSmilElement::setEndTime(CSmilParser* pParser)
- {
- HX_RESULT ret = HXR_OK;
- BOOL bEndTimeHasBeenSet = FALSE;
- UINT32 ulOffset = 0;
- SmilTimeValue* pNextResolvedTimeValue = NULL;
- LISTPOSITION lPos = NULL;
- CHXSimpleList* pListOfAllResolvedEndTimes = new CHXSimpleList;
- // /Looks at all resolved end times in the list and
- // returns the SmilTimeValue with the closest time at or
- // later than the time passed in:
- HX_RESULT rettimeval = HXR_OK;
- rettimeval = getNextResolvedTimeValue(pNextResolvedTimeValue,
- SMILTIME_NEGATIVE_INFINITY, SMILTIME_NEGATIVE_INFINITY,
- SmilEndTimeList, pListOfAllResolvedEndTimes);
- // /NOTE: ret!=HXR_OK is NOT an error condition; it means
- // that no value in the end time list was found that was
- // resolved.
-
- if (SUCCEEDED(rettimeval) && NULL != pNextResolvedTimeValue)
- {
- if (pListOfAllResolvedEndTimes)
- {
- // /Go through this list and insert each into the pending list:
- LISTPOSITION lPosTmp =
- pListOfAllResolvedEndTimes->GetHeadPosition();
- while (lPosTmp)
- {
- SmilTimeValue* pTmpVal = (SmilTimeValue*)
- pListOfAllResolvedEndTimes->GetAt(lPosTmp);
- if (pTmpVal && pTmpVal->isTimeResolved() &&
- pTmpVal->m_pElement)
- {
- if (pTmpVal != pNextResolvedTimeValue)
- {
- // /(?XXXEH- TODO: insert into list based on resolved
- // time? end="20s;0s" works OK, so...?)
- if (pParser->EstablishEndTimeList())
- {
- CHXSimpleList* pList =
- pParser->GetPendingEndTimeList();
- // /Don't add if it's a duplicate:
- if (!pParser->isDuplicateEntry(pList, pTmpVal))
- {
- pList->AddTail(pTmpVal);
- }
- }
- }
- }
- else
- {
- HX_ASSERT(0 && "timeval invalid");
- }
- pListOfAllResolvedEndTimes->GetNext(lPosTmp);
- } // /end while(lPos...).
- }
- HX_DELETE(pListOfAllResolvedEndTimes);
- bEndTimeHasBeenSet = TRUE;
- HX_ASSERT(pNextResolvedTimeValue->isTimeResolved());
- switch (pNextResolvedTimeValue->m_type)
- {
- case SmilTimeOffset:
- case SmilTimeClockValue:
- {
- // /XXXEH- is this what we really want to do?
- // Alternatively, we could have resolved-to "base" time
- // as 0 and then m_lOffset is added to get resolved-to
- // "offset" time:
- m_lEndOffset = pNextResolvedTimeValue->getTimeOffset();
- m_bEndOffsetSet = TRUE;
- #if defined(_DEBUG) // /XXXEH- testing!:
- LONG32 lResolvedToTime = 0;
- HX_RESULT tmprslt =
- pNextResolvedTimeValue->getEffectiveResolvedTime(
- lResolvedToTime);
- HX_ASSERT(tmprslt==HXR_OK &&
- m_lEndOffset == lResolvedToTime);
- #endif
- }
- break;
- case SmilTimeSyncBase:
- #if defined(ENABLE_SYNC_TO_PREV)
- case SmilTimeSyncToPrev:
- #endif
- case SmilTimeEvent:
- {
- // /NOTE: this's time must be *resolved* already which
- // shouldn't happen yet:
- HX_ASSERT(!pNextResolvedTimeValue->isTimeResolved());
- }
- break;
- case SmilTimeMediaMarker:
- {
- //XXXEH- TODO: handle media markers:
- HX_ASSERT(0);
- //pParser->addEndMediaMarkerSyncElement(this);
- }
- break;
- case SmilTimeWallclock:
- {
- // /XXXEH- wouldn't it be better to use
- // getEffectiveResolvedTime() here(?) so as to treat all time
- // types consistently?
- m_lEndOffset = pNextResolvedTimeValue->getTimeOffset();
- m_bEndOffsetSet = TRUE;
- m_bWallClockEnd = TRUE;
- }
- break;
- case SmilTimeNone:
- break;
- } // /end switch(pNextResolvedTimeValue->m_type).
- }
- // /Now, go through all unresolved end times and add this element to
- // the appropriate list(s) for each unresolved time value found:
- if (m_pEndTimeList)
- {
- lPos = m_pEndTimeList->GetHeadPosition();
- }
- if (NULL == lPos) // /list is empty.
- {
- goto cleanup;
- }
- while (lPos && HXR_OK == ret)
- {
- SmilTimeValue* pTmpVal = (SmilTimeValue*)m_pEndTimeList->GetAt(lPos);
- if (pTmpVal && !pTmpVal->isTimeResolved())
- {
- switch (pTmpVal->m_type)
- {
- case SmilTimeOffset:
- case SmilTimeClockValue:
- {
- // /We shouldn't ever get here because clock times are
- // always resolved:
- HX_ASSERT(pTmpVal->isTimeResolved());
- }
- break;
- case SmilTimeSyncBase:
- {
- pParser->addEndTimeSyncElement(this);
- // /XXXEH- make sure we handle end="3s; prev.end" where
- // both are valid times; the following doesn't handle this
- // case:
- if (!bEndTimeHasBeenSet)
- {
- m_EndEventSourceID = pTmpVal->m_idRef;
- m_nEndEventSourceTag = pTmpVal->m_position;
- // /XXXEH- wouldn't it be better to use
- // getEffectiveResolvedTime() here(?) so as to treat
- // all time types consistently?
- m_lEndEventClockValue =
- pTmpVal->getTimeOffset();
- }
- }
- break;
- #if defined(ENABLE_SYNC_TO_PREV)
- case SmilTimeSyncToPrev:
- {
- // /XXXEH- shouldn't we treat this just like we treat the
- // sync base case above by doing the following?:
- // pParser->addEndTimeSyncElement(this);
- // /XXXEH- make sure we handle end="3s; prev.end" where
- // both are valid times; the following doesn't handle this
- // case:
- if (!bEndTimeHasBeenSet)
- {
- SMILNode* pSibling =
- m_pNode->m_pParent->getFirstChild();
- SMILNode* pLastNode = pSibling;
- while (pSibling)
- {
- if (pSibling->m_id == m_pNode->m_id)
- {
- // we found our boy...
- break;
- }
- pLastNode = pSibling;
- pSibling = m_pNode->m_pParent->getNextChild();
- }
- HX_ASSERT(pSibling && pLastNode);
- if (pSibling && pLastNode)
- {
- m_EndEventSourceID = pLastNode->m_id;
- // /XXXEH- wouldn't it be better to use
- // getEffectiveResolvedTime() here(?) so as to
- // treat all time types consistently?
- m_lEndEventClockValue =
- pTmpVal->getTimeOffset();
- m_nEndEventSourceTag =
- pTmpVal->m_position;
- }
- else
- {
- ret = HXR_FAIL;
- }
- }
- }
- break;
- #endif
- case SmilTimeEvent:
- {
- pParser->addEndEventElement(pTmpVal);
- }
- break;
- case SmilTimeMediaMarker:
- {
- pParser->addEndMediaMarkerSyncElement(pTmpVal);
- }
- break;
- case SmilTimeWallclock:
- {
- // /We shouldn't ever get here because wallclock times
- // are always resolved:
- HX_ASSERT(pTmpVal->isTimeResolved());
- }
- break;
- case SmilTimeNone:
- break;
- } // /end switch(pTmpVal->m_type).
- }
- m_pEndTimeList->GetNext(lPos);
- } // /end while (lPos ...).
- // else time must allready be set.
- cleanup:
- return ret;
- }
- HX_RESULT
- CSmilElement::getEndTimeValue(REF(SmilTimeValue*) pValue)
- {
- HX_RESULT ret = HXR_OK;
- // This function just returns the first value in the end-time list,
- // even if that value is not yet resolved to a clock time:
- // If you want to use the "right" value for a given time t, then
- // call "getNextResolvedTimeValue()"
- if (m_pEndTimeList)
- {
- LISTPOSITION pos = m_pEndTimeList->GetHeadPosition();
- if (pos)
- {
- pValue = (SmilTimeValue*)m_pEndTimeList->GetAt(pos);
- }
- }
- return ret;
- }
- HX_RESULT
- CSmilElement::getBeginTimeValue(REF(SmilTimeValue*) pValue)
- {
- HX_RESULT ret = HXR_OK;
- // This function just returns the first value in the begin-time list,
- // even if that value is not yet resolved to a clock time:
- // If you want to use the "right" value for a given time t, then
- // call "getNextResolvedTimeValue()"
- if (m_pBeginTimeList)
- {
- LISTPOSITION pos = m_pBeginTimeList->GetHeadPosition();
- if (pos)
- {
- pValue = (SmilTimeValue*)m_pBeginTimeList->GetAt(pos);
- }
- }
- return ret;
- }
- // /Returns HXR_OK except if the element has not ever been inserted in the
- // timeline, in which case the return value is HXR_NOT_INITIALIZED.
- // In this case, the value placed into ulActualStartTime will remain whatever
- // is set in the delay value of the element. If the element has an
- // indefinite begin time, SMIL_TIME_INFINITY is returned in ulActualStartTime
- // with HXR_OK as the return value. Note that SMIL_TIME_INFINITY is not
- // the same value as ((UINT32)-1) which is a possible return value and means
- // that the value is not initialized:
- HX_RESULT
- CSmilElement::getCurrentScheduledStartTime(REF(ULONG32) ulActualStartTime)
- {
- HX_RESULT ret = HXR_OK;
-
- ulActualStartTime = m_ulDelay;
- BOOL bIsMediaObject = CSmilParser::isMediaObject(m_pNode);
- if (!m_bHasBeenScheduled && bIsMediaObject)
- {
- ret = HXR_NOT_INITIALIZED;
- }
- else if (m_bIndefiniteBegin)
- {
- ulActualStartTime = SMILTIME_INFINITY;
- }
- else if (!bIsMediaObject && ulActualStartTime == ((UINT32) -1))
- {
- ret = HXR_NOT_INITIALIZED;
- }
- // /#define XXXEHODGE_DEBUG_PRINTF_CURRENTSCHEDULEDSTARTTIME
- #if defined(_DEBUG) && defined(XXXEHODGE_DEBUG_PRINTF_CURRENTSCHEDULEDSTARTTIME)
- {
- static BOOL bFirstTime = TRUE;
- FILE* f1 = ::fopen("c:\smil2.txt", bFirstTime?"w":"a+");
- ::fprintf(f1, "n[%s]->getCurrentScheduledStartTime() "
- "ulActualStopTime := %lu (delay=%lu, dur=%lu, "
- "beginOffsetFromSyncBase=%lu) n", (const char*)m_pNode->m_id,
- ulActualStartTime, m_ulDelay, m_ulDuration, m_ulBeginOffsetFromSyncBase);
- ::fclose(f1);
- bFirstTime=FALSE;
- }
- #endif
- return ret;
- }
- // /Returns HXR_OK except if the element has not ever been inserted in the
- // timeline, in which case the return value is HXR_NOT_INITIALIZED.
- // In this case, the value placed into ulActualStopTime will remain whatever
- // is set in the delay value of the element. If the element has an
- // indefinite end time, SMIL_TIME_INFINITY is returned in ulActualStopTime
- // with HXR_OK as the return value. Note that SMIL_TIME_INFINITY is not
- // the same value as ((UINT32)-1) which is a possible return value and means
- // that the value is not initialized:
- HX_RESULT
- CSmilElement::getCurrentScheduledStopTime(REF(ULONG32) ulActualStopTime)
- {
- HX_RESULT ret = HXR_OK;
- // /Fixes PR 63733: initialize to invalid time in case caller did not:
- ulActualStopTime = (UINT32)-1;
- if (m_bIndefiniteDuration || m_bIndefiniteEnd)
- {
- ulActualStopTime = SMILTIME_INFINITY;
- }
- // /Helps fix PR 53531 (unwinding after string of pauses) when
- // m_ulDuration has not been updated to reflect the paused time so far:
- else if (isPausedInExcl())
- {
- #if XXXEH_HANDLE_CASE_WHERE_RESOLVED_END_IS_NOW_IN_EFFECT
- #else
- ulActualStopTime = SMILTIME_PAUSED_INDEFINITELY;
- #endif
- }
- else if (isStoppedInExcl())
- {
- ulActualStopTime = m_ulStopTimeInExcl;
- }
- else if (isDeferredInExcl())
- {
- ulActualStopTime = SMILTIME_DEFERRED_INDEFINITELY;
- }
- else if (m_ulDelay != ((UINT32) -1) &&
- m_ulDuration != ((UINT32) -1))
- {
- if (m_bBeginOffsetSet)
- {
- LONG32 lBeginOffsetPast0 = m_lBeginOffset;
- if (m_lBeginOffset < 0)
- {
- lBeginOffsetPast0 = 0;
- }
- ulActualStopTime = m_ulDelay + m_ulDuration - lBeginOffsetPast0;
- }
- else
- {
- if (m_bCurBeginIsOffsetFromSyncBase)
- {
- ulActualStopTime = m_ulDelay + m_ulDuration;
- // /Adding this if() check fixes hide-site problems exposed
- // in the repro case for PR 53531 once 53531 had been fixed;
- // this makes sure that the beginOffsetFromSyncBase is
- // accounted for only when it should be. Fixes
- // BUG-20010619_lastExclChildGetsItsOffsetFromSyncbaseIgnored.smil
- if (m_bDurationIncludesDelayBeyondSyncbase)
- {
- ulActualStopTime -= m_ulBeginOffsetFromSyncBase;
- }
- }
- else
- {
- ulActualStopTime = m_ulDelay + m_ulDuration;
- }
- }
- }
- else if (m_ulDelay != (UINT32)-1 && m_bCurrentSourceIsLive)
- {
- // /Fix for PR 57230:
- // live sources that have 0 dur, which means they play
- // forever, should have infinity, not 0, used as
- // their dur when calculating whether or not they're
- // visible at the current time:
- ulActualStopTime = (UINT32)SMILTIME_INFINITY;
- }
- else
- {
- ret = HXR_NOT_INITIALIZED;
- }
- // /#define XXXEHODGE_DEBUG_PRINTF_CURRENTSCHEDULEDSTOPTIME
- #if defined(_DEBUG) && defined(XXXEHODGE_DEBUG_PRINTF_CURRENTSCHEDULEDSTOPTIME)
- {
- static BOOL bFirstTime = TRUE;
- FILE* f1 = ::fopen("c:\smil2.txt", bFirstTime?"w":"a+");
- ::fprintf(f1, "n[%s]->getCurrentScheduledStopTime() "
- "ulActualStopTime := %lu (delay=%lu, dur=%lu, "
- "beginOffsetFromSyncBase=%lu) n", (const char*)m_pNode->m_id,
- ulActualStopTime, m_ulDelay, m_ulDuration, m_ulBeginOffsetFromSyncBase);
- ::fclose(f1);
- bFirstTime=FALSE;
- }
- #endif
- return ret;
- }
- // /This function takes a time as input and returns in pValue the begin
- // or end time (depending on listType) that makes the most
- // sense given the time passed in; it assumes times that are
- // resolvable have already been resolved (and thus their m_bIsResolved
- // is TRUE), and it thus ignores unresolved times. It returns
- // HXR_FAILED and sets pValue to NULL if no now-or-future resolved begin
- // time is found.
- // NOTE!!!: this will NOT return the currently-active time if the element
- // is already playing at lCurTime since it would be in the past. The
- // currently-active begin and end times can be found in this->m_lBeginOffset
- // or this->m_lEndOffset, respectively, and that those values are only
- // valid if m_bBeginOffsetSet and m_bEndOffsetSet, respectively, are TRUE:
- // Also Note: pValue, as well as the two lists, is|are filled with either
- // begin or end time|times, depending on the listType value:
- HX_RESULT
- CSmilElement::getNextResolvedTimeValue(REF(SmilTimeValue*) pValue,
- INT32 lCurTimeInGroupTime,
- INT32 lCurTimeInSyncBaseTime,
- SmilTimingListType listType,
- CHXSimpleList* pListOfAllResolvedTimes)
- {
- HX_RESULT retval = HXR_OK;
- SmilTimeValue* pTmpVal = NULL;
- SmilTimeValue* pTimeValFoundSoFar = NULL;
- CHXSimpleList* pWhichList = NULL;
- LONG32 lCurTimeInSameTimeSpace = lCurTimeInSyncBaseTime;
- LONG32 lCurUsableTimeInGroupTime = lCurTimeInGroupTime;
- // /If group time is not known, use sync-base time:
- if (SMILTIME_NEGATIVE_INFINITY == lCurTimeInGroupTime)
- {
- lCurUsableTimeInGroupTime = lCurTimeInSyncBaseTime;
- }
- LISTPOSITION lPos = NULL;
- if (SmilBeginTimeList == listType) // /get begin time:
- {
- pWhichList = m_pBeginTimeList;
- }
- else if (SmilEndTimeList == listType)// /get end time:
- {
- pWhichList = m_pEndTimeList;
- }
- else
- {
- HX_ASSERT(SmilBeginTimeList == listType ||
- SmilEndTimeList == listType);
- }
- if (NULL == pWhichList)
- {
- retval = HXR_FAILED;
- goto cleanup;
- }
- lPos = pWhichList->GetHeadPosition();
- if (NULL == lPos) // /list is empty.
- {
- retval = HXR_FAILED;
- goto cleanup;
- }
- // /The following loop simply finds the time that is nearest
- // to, but not earlier than, lCurTime:
- // *Which* curTime depends on the type; events resolve to group times,
- // while clockValues resolve to syncBase times:
- while (lPos && HXR_OK == retval)
- {
- pTmpVal = (SmilTimeValue*)pWhichList->GetAt(lPos);
- if (pTmpVal)
- {
- if (!pTmpVal->isTimeResolved())
- {
- pWhichList->GetNext(lPos);
- continue;
- }
- // /It's resolved, so insert it:
- if (pListOfAllResolvedTimes)
- {
- pListOfAllResolvedTimes->AddTail(pTmpVal);
- }
- LONG32 lResolvedToTimeOfTimeValFoundSoFar =SMILTIME_INFINITY;
- HX_RESULT tmprslt = HXR_OK;
- if (NULL != pTimeValFoundSoFar)
- {
- // /We want to use pTimeValFoundSoFar, not pTmpVal here!
- // Fixes case where there are two or more resolved times and
- // the first, lexically, is higher than any of the others:
- tmprslt = pTimeValFoundSoFar->getEffectiveResolvedTime(
- lResolvedToTimeOfTimeValFoundSoFar);
- HX_ASSERT(HXR_OK == tmprslt);
- if (!SUCCEEDED(tmprslt))
- {
- HX_ASSERT(SUCCEEDED(tmprslt));
- continue;
- }
- }
- switch (pTmpVal->getTimeType())
- {
- case SmilTimeMediaMarker:
- case SmilTimeWallclock:
- case SmilTimeEvent:
- lCurTimeInSameTimeSpace = lCurUsableTimeInGroupTime;
- break;
- case SmilTimeOffset:
- case SmilTimeClockValue:
- case SmilTimeSyncBase:
- default:
- lCurTimeInSameTimeSpace = lCurTimeInSyncBaseTime;
- break;
- }
- switch (pTmpVal->getTimeType())
- {
- case SmilTimeNone:
- break; // /Skip this time.
- case SmilTimeWallclock:
- case SmilTimeOffset:
- case SmilTimeClockValue:
- {
- LONG32 lEffectiveResolvedToTime = 0;
- tmprslt = pTmpVal->getEffectiveResolvedTime(
- lEffectiveResolvedToTime);
- #if defined(_DEBUG) // /XXXEH- testing!:
- LONG32 lTimeOffset = pTmpVal->getTimeOffset();
- HX_ASSERT(tmprslt==HXR_OK &&
- lTimeOffset == lEffectiveResolvedToTime);
- #endif
- // /XXXEH- TODO: add bool (& time val?) that says if (& when) this begin time
- // was already used; if already used, don't use it again, and seeks and
- // repeats must erase this bool (& time val); this is especially needed
- // if we start treating all times as events, i.e., consistently:
- // /Only use times that are now or later:
- if (lEffectiveResolvedToTime >= lCurTimeInSameTimeSpace)
- {
- if (NULL == pTimeValFoundSoFar ||
- lEffectiveResolvedToTime <
- lResolvedToTimeOfTimeValFoundSoFar)
- {
- pTimeValFoundSoFar = pTmpVal;
- }
- }
- }
- break;
- case SmilTimeMediaMarker:
- case SmilTimeSyncBase:
- #if defined(ENABLE_SYNC_TO_PREV)
- case SmilTimeSyncToPrev:
- #endif
- case SmilTimeEvent:
- {
- // /XXXEH- TODO: finish this, and make sure m_lResolvedToTime and m_lWhenTimeWasResolved are being set:
- LONG32 lEffectiveResolvedToTime = 0;
- HX_RESULT tmprslt2 = pTmpVal->
- getEffectiveResolvedTime(
- lEffectiveResolvedToTime);
- HX_ASSERT(SUCCEEDED(tmprslt2));// /Should be resovled.
- if (SUCCEEDED(tmprslt2) &&
- lEffectiveResolvedToTime >= lCurTimeInSameTimeSpace)
- {
- LONG32 lTimeOffset = pTmpVal->getTimeOffset();
- if (lEffectiveResolvedToTime <
- // /XXXEH- TODO: add +offset since this is an event-based time; need
- // "timecmp(x,y)" function that compares two SmilTimeValues (taking into
- // account that negative offsets shouldn't be compared if this is an event
- // time) and returns -1 if x is greater, 0 if same, +1 if y is later:
- // /XXXEH- TODO: argue the following with W3C SYMM Smil Boston Working
- // Group: if we treat event-based times with negative offset as "now"
- // w/clip-begin, then why not same for sync-base (and other) values whose
- // times are in the past when they first become resolved (e.g., clipped by
- // parent, or sync-arc to event-arc'd time)? For example:
- // <par>
- // <ref id="x" begin="foo.activate" />
- // <par begin="10s">
- // <!-- resolves 3s after it's intended value: -->
- // <ref begin="x.begin-3s"/>
- lResolvedToTimeOfTimeValFoundSoFar)
- {
- pTimeValFoundSoFar = pTmpVal;
- }
- // /XXXEH- TODO: verify that this is how the
- // SMIL Boston draft ends up dealing with the
- // begin="x.focusInEvent-5s; x.focusInEvent-3s"
- // issue:
- // /Take the one with the earliest offset if
- // the resolved time is the same, so
- // "x.focusInEvent-5s" beats out "x.focusInEvent",
- // and "x.focusInEvent" beats out "x.focusInEvent+2s"
- // /XXXEH- I think restart might play into this
- // so that x.focusInEvent-5s would be used over
- // x.focusInEvent-3s if and only if (restart=="never"
- // OR (restart!="never" AND this's dur <=2s)):
- else if (lEffectiveResolvedToTime ==
- lResolvedToTimeOfTimeValFoundSoFar &&
- lTimeOffset <
- pTimeValFoundSoFar->getTimeOffset())
- {
- pTimeValFoundSoFar = pTmpVal;
- }
- }
- }
- break;
- }
- }
- pWhichList->GetNext(lPos);
- } // /end while(lPos...).
- pValue = pTimeValFoundSoFar;
- if (NULL == pValue)
- {
- retval = HXR_FAILED;
- }
- cleanup:
- return retval;
- }
- HX_RESULT
- CSmilElement::resolveEventTimeValues(INT32 lCurTime,
- const char* pEventName,
- const char* pEventElementId,
- SmilTimingListType listType,
- REF(BOOL) bATimeWasResolved)
- {
- HX_RESULT retval = HXR_OK;
- SmilTimeValue* pValue = NULL;
- CHXSimpleList* pWhichList = NULL;
- bATimeWasResolved = FALSE;
- LISTPOSITION lPos = NULL;
- if (NULL == pEventName ||
- // /pEventElementId can be NULL but not non-NULL and empty:
- (pEventElementId && ' ' == *pEventElementId) )
- {
- retval = HXR_FAILED;
- goto cleanup;
- }
- if (SmilBeginTimeList == listType) // /get begin time:
- {
- pWhichList = m_pBeginTimeList;
- }
- else if (SmilEndTimeList == listType)// /get end time:
- {
- pWhichList = m_pEndTimeList;
- }
- else
- {
- HX_ASSERT(SmilBeginTimeList == listType ||
- SmilEndTimeList == listType);
- }
- if (NULL == pWhichList)
- {
- retval = HXR_FAILED;
- goto cleanup;
- }
- // /XXXEH- is there any reason we should start from tail instead?
- lPos = pWhichList->GetHeadPosition();
- if (NULL == lPos) // /list is empty.
- {
- retval = HXR_FAILED;
- goto cleanup;
- }
- while (lPos && HXR_OK == retval)
- {
- pValue = (SmilTimeValue*)pWhichList->GetAt(lPos);
- // /If this begin or end time is a time event based on this event
- // from the element with pEventElementId, then we can (and do)
- // resolve it here:
- if(NULL!= pValue && (SmilTimeEvent == pValue->m_type ||
- (pValue->m_bTreatSyncArcAsEvent &&
- pValue->isSyncBaseTimeVal()) ) )
- {
- // /Now, see if we've got an element that is waiting for this
- // event from the pEventElement:
- if (!pValue->getIdRef() || !pValue->getEventName())
- {
- HX_ASSERT(pValue->getIdRef() && pValue->getEventName());
- pWhichList->GetNext(lPos);
- continue;
- }
- if ((!pEventElementId || strcmp(pValue->getIdRef(),
- pEventElementId) == 0) &&
- strcmp(pValue->getEventName(), pEventName) == 0 )
- {
- BOOL bIsResolvedAlready = pValue->isTimeResolved();
- INT32 lProirResolvedToTime = (bIsResolvedAlready?
- pValue->getResolvedToTimeWithoutOffset():-1);
- pValue->setIsTimeResolved(TRUE);
- pValue->setResolvedToTime(lCurTime);
- pValue->setWhenTimeWasResolved(lCurTime);
- // /[Optimization]: In case we get called twice with the
- // same event at the same resolved time, let's not force
- // a stop/start of the element:
- if (!bIsResolvedAlready || lCurTime !=lProirResolvedToTime)
- {
- bATimeWasResolved = TRUE;
- }
- }
- }
- pWhichList->GetNext(lPos);
- } // /end while(lPos...).
- cleanup:
- return retval;
- }
- // /This method goes through the m_pEndTimeList to see if there's an
- // event-arc end time or other unresolved end time; this is important
- // for use in the algorithm for determining whether or not something
- // should restart (see SMIL 2.0 Spec Timing Module's getNextInterval()
- // pseudocode):
- BOOL
- CSmilElement::hasUnresolvedEndTime()
- {
- BOOL bHasUnresolvedEndTime = FALSE;
- SmilTimeValue* pValue = NULL;
- LISTPOSITION lPos = NULL;
- if (NULL == m_pEndTimeList)
- {
- goto cleanup;
- }
- // /XXXEH- is there any reason we should start from tail instead?
- lPos = m_pEndTimeList->GetHeadPosition();
- if (NULL == lPos) // /list is empty.
- {
- goto cleanup;
- }
- while (lPos && !bHasUnresolvedEndTime)
- {
- pValue = (SmilTimeValue*)m_pEndTimeList->GetAt(lPos);
- if(NULL == pValue)
- {
- m_pEndTimeList->GetNext(lPos);
- continue;
- }
- if (SmilTimeEvent == pValue->m_type)
- {
- bHasUnresolvedEndTime = TRUE;
- }
- // /XXXEH- TODO: need to go through sync-arc element and see
- // if *it* has any unresolved time(s) (begin or end, depending
- // on this sync-arc time's position value) and, if not, then
- // DON'T claim bHasUnresolvedEndTime is TRUE:
- else if (pValue->m_bTreatSyncArcAsEvent &&
- pValue->isSyncBaseTimeVal())
- {
- if (!pValue->isTimeResolved())
- {
- bHasUnresolvedEndTime = TRUE;
- }
- }
- m_pEndTimeList->GetNext(lPos);
- } // /end while(lPos...).
- cleanup:
- return bHasUnresolvedEndTime;
- }
- // /This method returns the pure duration from the media's begin to its
- // end, w/o any delay included:
- ULONG32
- CSmilElement::getPureDuration()
- {
- HX_ASSERT(!m_bDurationIncludesDelayBeyondSyncbase ||
- m_bCurBeginIsOffsetFromSyncBase);
- if (m_bDurationIncludesDelayBeyondSyncbase)
- {
- return (m_ulDuration - m_ulBeginOffsetFromSyncBase);
- }
- else
- {
- return m_ulDuration;
- }
- /*
- return (m_bDurationIncludesDelayBeyondSyncbase?
- m_ulDuration-m_ulBeginOffsetFromSyncBase : m_ulDuration);
- */
- }
- HX_RESULT
- CSmilElement::resolveSyncArcTimeValues(INT32 lResolvedToTime,
- const char* pSyncBaseElementId,
- SmilTimingListType listType,
- REF(BOOL) bATimeWasResolved,
- BOOL bMoveNewlyResolvedsToPendingTimesList,
- CSmilParser* pParser)
- {
- HX_RESULT retval = HXR_OK;
- SmilTimeValue* pValue = NULL;
- CHXSimpleList* pWhichList = NULL;
- bATimeWasResolved = FALSE;
- LISTPOSITION lPos = NULL;
- if (NULL == pSyncBaseElementId)
- {
- retval = HXR_FAILED;
- goto cleanup;
- }
- if (SmilBeginTimeList == listType) // /get begin time:
- {
- pWhichList = m_pBeginTimeList;
- }
- else if (SmilEndTimeList == listType)// /get end time:
- {
- pWhichList = m_pEndTimeList;
- }
- else
- {
- HX_ASSERT(SmilBeginTimeList == listType ||
- SmilEndTimeList == listType);
- }
- if (NULL == pWhichList)
- {
- retval = HXR_FAILED;
- goto cleanup;
- }
- // /XXXEH- is there any reason we should start from tail instead?
- lPos = pWhichList->GetHeadPosition();
- if (NULL == lPos) // /list is empty.
- {
- retval = HXR_FAILED;
- goto cleanup;
- }
- while (lPos && HXR_OK == retval)
- {
- pValue = (SmilTimeValue*)pWhichList->GetAt(lPos);
- // /If this begin or end time is a time event based on this event
- // from the element with pSyncBaseElementId, then we can (and do)
- // resolve it here:
- if(NULL!= pValue && pValue->isSyncBaseTimeVal())
- {
- // /Now, see if we've got an element that is waiting for this
- // event from the pEventElement:
- if (!pValue->getIdRef())
- {
- HX_ASSERT(pValue->getIdRef());
- pWhichList->GetNext(lPos);
- continue;
- }
- if (strcmp(pValue->getIdRef(), pSyncBaseElementId) == 0)
- {
- // /Helps fix SMIL 2.0 Interop Timing #15.13:
- // if we're resuming a paused element and its duration thus
- // got extended, don't re-resolve (and re-insert) other
- // elements who are sync-arc'd to the *begin* time of this
- // resumed element:
- if (pValue->isTimeResolved() && lResolvedToTime ==
- pValue->getResolvedToTimeWithoutOffset() &&
- SmilBeginTimeList == listType)
- {
- bMoveNewlyResolvedsToPendingTimesList = FALSE;
- }
- pValue->setIsTimeResolved(TRUE);
- pValue->setResolvedToTime(lResolvedToTime);
- // /XXXEH- this shouldn't matter what we put here, but
- // we *should* fill this with the current time:
- pValue->setWhenTimeWasResolved(0);
- bATimeWasResolved = TRUE;
- if (pParser && bMoveNewlyResolvedsToPendingTimesList)
- {
- if (SmilBeginTimeList == listType)
- {
- if (pParser->EstablishBeginTimeList())
- {
- CHXSimpleList* pList =
- pParser->GetPendingBeginTimeList();
- // /Don't add if it's a duplicate:
- if (!pParser->isDuplicateEntry(pList, pValue))
- {
- pList->AddTail(pValue);
- }
- }
- }
- else
- {
- if (pParser->EstablishEndTimeList())
- {
- CHXSimpleList* pList =
- pParser->GetPendingEndTimeList();
- // /Don't add if it's a duplicate:
- if (!pParser->isDuplicateEntry(pList, pValue))
- {
- pList->AddTail(pValue);
- }
- }
- }
- }
- }
- }
- pWhichList->GetNext(lPos);
- } // /end while(lPos...).
- cleanup:
- return retval;
- }
- // /Returns HXR_FAILED if element or its parent don't exist. The spec says
- // that "always" is what is to be used for restart and restartDefault for the
- // element if it has no parent or the parent has no restartDefault value:
- HX_RESULT
- CSmilElement::getParentRestartDefault()
- {
- HX_RESULT ret = HXR_OK;
- if (NULL == m_pNode)
- {
- ret = HXR_FAILED;
- }
- else
- {
- SMILNode* pParent = m_pNode->m_pParent;
- if (!pParent || !pParent->m_pElement)
- {
- ret = HXR_FAILED;
- }
- else
- {
- switch (pParent->m_pElement->m_restartDefaultBehavior)
- {
- case SmilRestartNever:
- case SmilRestartWhenNotActive:
- case SmilRestartAlways:
- // /Both restartDefault and restart behavior are assigned
- // to parent's restartDefault behavior:
- m_restartDefaultBehavior =
- m_restartBehavior =
- pParent->m_pElement->m_restartDefaultBehavior;
- break;
- case SmilRestartInherit:
- m_restartDefaultBehavior =
- m_restartBehavior = SmilRestartAlways;
- break;
- default:
- HX_ASSERT(0);
- break;
- }
- }
- }
- return ret;
- }
- void CSmilElement::updateRemoveTime(UINT32 ulRemoveTime)
- {
- m_ulRemoveTime = ulRemoveTime;
- if (m_pHandler)
- {
- m_pHandler->handleRemoveTimeUpdate(this, ulRemoveTime);
- }
- }
- void CSmilElement::handleXMMF(const char* pszID, const char* pszXMMFile, const char* pszSrc)
- {
- if (m_pHandler)
- {
- m_pHandler->handleExternalMediaMarkerFile(this,
- pszID,
- pszXMMFile,
- pszSrc);
- }
- }
- BOOL CSmilElement::hasEventBasedBeginTime()
- {
- BOOL bRet = FALSE;
- if (m_pBeginTimeList)
- {
- LISTPOSITION pos = m_pBeginTimeList->GetHeadPosition();
- while (pos)
- {
- SmilTimeValue* pValue =
- (SmilTimeValue*) m_pBeginTimeList->GetNext(pos);
- if (pValue &&
- pValue->m_type == SmilTimeEvent)
- {
- bRet = TRUE;
- break;
- }
- }
- }
- // We also have to check our sync ancestor because
- // if our sync ancestor has an event based begin
- // time, then so do we. However, if we already
- // know we have an event based time, then we don't
- // need to check
- if (!bRet)
- {
- CSmilElement* pSyncAnc = getSyncAncestorElement();
- if (pSyncAnc)
- {
- bRet = pSyncAnc->hasEventBasedBeginTime();
- }
- }
- return bRet;
- }
- CSmilElement* CSmilElement::getSyncAncestorElement()
- {
- CSmilElement* pRet = NULL;
- if (m_pNode)
- {
- BOOL bLegalMediaObjectChild = FALSE;
- if (m_pNode->m_tag == SMILArea ||
- m_pNode->m_tag == SMILAnchor ||
- m_pNode->m_tag == SMILAnimate ||
- m_pNode->m_tag == SMILSet ||
- m_pNode->m_tag == SMILAnimateColor ||
- m_pNode->m_tag == SMILAnimateMotion)
- {
- bLegalMediaObjectChild = TRUE;
- }
- SMILNode* pAnc = m_pNode->m_pParent;
- while (pAnc)
- {
- if (pAnc->m_tag == SMILPar ||
- pAnc->m_tag == SMILExcl ||
- pAnc->m_tag == SMILSeq)
- {
- pRet = pAnc->m_pElement;
- break;
- }
- else if ((pAnc->m_tag == SMILRef ||
- pAnc->m_tag == SMILText ||
- pAnc->m_tag == SMILImg ||
- pAnc->m_tag == SMILAudio ||
- pAnc->m_tag == SMILVideo ||
- pAnc->m_tag == SMILAnimation ||
- pAnc->m_tag == SMILTextstream ||
- pAnc->m_tag == SMILBrush ||
- pAnc->m_tag == SMILPrefetch) &&
- bLegalMediaObjectChild)
- {
- pRet = pAnc->m_pElement;
- break;
- }
- pAnc = pAnc->m_pParent;
- }
- }
- return pRet;
- }
- BOOL CSmilElement::hasEventBasedEndTime()
- {
- BOOL bRet = FALSE;
- if (m_pEndTimeList)
- {
- LISTPOSITION pos = m_pEndTimeList->GetHeadPosition();
- while (pos)
- {
- SmilTimeValue* pValue =
- (SmilTimeValue*) m_pEndTimeList->GetNext(pos);
- if (pValue &&
- pValue->m_type == SmilTimeEvent)
- {
- bRet = TRUE;
- break;
- }
- }
- }
- return bRet;
- }
- HX_RESULT
- CSmilElement::GetElementProperties(REF(IHXValues*) pProperties)
- {
- HX_RESULT rc = HXR_OK;
- BOOL bDone = FALSE;
- ElementWithinTag elementWithinTag = WithinUnknown;
- SMILNode* pNode = m_pNode;
- HX_ASSERT(pNode);
- while (pNode->m_pParent && !bDone)
- {
- switch (pNode->m_pParent->m_tag)
- {
- case SMILPar:
- if (elementWithinTag == WithinSeq)
- {
- elementWithinTag = WithinSeqInPar;
- }
- else
- {
- elementWithinTag = WithinPar;
- }
- bDone = TRUE;
- break;
- case SMILSeq:
- elementWithinTag = WithinSeq;
- break;
- default:
- break;
- }
- pNode = pNode->m_pParent;
- }
- pProperties = new CHXHeader();
- pProperties->AddRef();
- pProperties->SetPropertyULONG32("ElementWithinTag", elementWithinTag);
- pProperties->SetPropertyULONG32("Delay", m_ulDelay);
- if (m_bHasExplicitDur)
- {
- pProperties->SetPropertyULONG32("Duration", m_ulDuration);
- }
- return rc;
- }
- void
- CSmilElement::checkElementFillBehavior()
- {
- if (m_pTimelineElement)
- {
- m_pTimelineElement->checkElementFillBehavior();
- }
- }
- /*
- * CSmilRootLayout methods
- */
- CSmilRootLayout::CSmilRootLayout(SMILNode* pNode) :
- CSmilElement(pNode)
- {
- m_dWidth = 0.0;
- m_eWidthType = CSS2TypeAuto;
- m_dHeight = 0.0;
- m_eWidthType = CSS2TypeAuto;
- m_ulBackgroundColor = 0;
- m_eBackgroundColorType = CSS2TypeTransparent;
- m_eResizeBehavior = ResizeZoom;
- m_eContextWindow = ContextWindowAuto;
- }
- CSmilRootLayout::~CSmilRootLayout()
- {
- }
- HX_RESULT
- CSmilRootLayout::handleElement()
- {
- HX_RESULT rc = HXR_OK;
- if(m_pHandler)
- {
- rc = m_pHandler->handleRootLayout(this);
- }
- return rc;
- }
- /*
- * CSmilRegion methods
- */
- CSmilRegion::CSmilRegion(SMILNode* pNode) :
- CSmilElement(pNode)
- {
- m_Rect.m_dLeft = 0.0;
- m_Rect.m_eLeftType = CSS2TypeAuto;
- m_Rect.m_dTop = 0.0;
- m_Rect.m_eTopType = CSS2TypeAuto;
- m_Rect.m_dRight = 0.0;
- m_Rect.m_eRightType = CSS2TypeAuto;
- m_Rect.m_dBottom = 0.0;
- m_Rect.m_eBottomType = CSS2TypeAuto;
- m_Rect.m_dWidth = 0.0;
- m_Rect.m_eWidthType = CSS2TypeAuto;
- m_Rect.m_dHeight = 0.0;
- m_Rect.m_eHeightType = CSS2TypeAuto;
- m_lZIndex = 0;
- m_eZIndexType = CSS2TypeAuto;
- m_eFit = FitHidden;
- m_eShowBackground = ShowBackgroundAlways;
- m_ulBackgroundColor = 0xFF000000;
- m_eBackgroundColorType = CSS2TypeTransparent;
- m_dSoundLevel = 100.0;
- m_bRegionNameSpecified = FALSE;
- }
- CSmilRegion::~CSmilRegion()
- {
- }
- HX_RESULT
- CSmilRegion::handleElement()
- {
- HX_RESULT rc = HXR_OK;
- if(m_pHandler)
- {
- rc = m_pHandler->handleRegion(this);
- }
- return rc;
- }
- CSmilRegPoint::CSmilRegPoint(SMILNode* pNode) :
- CSmilElement(pNode)
- {
- m_RegPoint.m_dLeft = 0.0;
- m_RegPoint.m_eLeftType = CSS2TypeAuto;
- m_RegPoint.m_dTop = 0.0;
- m_RegPoint.m_eTopType = CSS2TypeAuto;
- m_RegPoint.m_dRight = 0.0;
- m_RegPoint.m_eRightType = CSS2TypeAuto;
- m_RegPoint.m_dBottom = 0.0;
- m_RegPoint.m_eBottomType = CSS2TypeAuto;
- m_RegPoint.m_eRegAlign = RegAlignTopLeft;
- }
- CSmilRegPoint::~CSmilRegPoint()
- {
- }
- HX_RESULT
- CSmilRegPoint::handleElement()
- {
- HX_RESULT rc = HXR_OK;
- if(m_pHandler)
- {
- rc = m_pHandler->handleRegPoint(this);
- }
- return rc;
- }
- #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT)
- CSmilViewport::CSmilViewport(SMILNode* pNode) :
- CSmilElement(pNode)
- {
- m_ulBackgroundColor = 0;
- m_eBackgroundColorType = CSS2TypeTransparent;
- m_dWidth = 0.0;
- m_eWidthType = CSS2TypeAuto;
- m_dHeight = 0.0;
- m_eHeightType = CSS2TypeAuto;
- m_eOpen = ViewportOpenOnStart;
- m_eClose = ViewportCloseOnRequest;
- m_eResizeBehavior = ResizeZoom;
- m_eContextWindow = ContextWindowAuto;
- }
- CSmilViewport::~CSmilViewport()
- {
- }
- HX_RESULT
- CSmilViewport::handleElement()
- {
- HX_RESULT rc = HXR_OK;
- if(m_pHandler)
- {
- rc = m_pHandler->handleViewport(this);
- }
- return rc;
- }
- #endif /* #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT) */
- /*
- * CSmilMeta methods
- */
- CSmilMeta::CSmilMeta(SMILNode* pNode):
- CSmilElement(pNode)
- {
- }
- CSmilMeta::~CSmilMeta()
- {
- }
- HX_RESULT
- CSmilMeta::handleElement()
- {
- HX_RESULT rc = HXR_OK;
- if(m_pHandler)
- {
- rc = m_pHandler->handleMeta(this);
- }
- return rc;
- }
- /*
- * CSmilMetadata methods
- */
- CSmilMetadata::CSmilMetadata(SMILNode* pNode):
- CSmilElement(pNode)
- {
- }
- CSmilMetadata::~CSmilMetadata()
- {
- }
- HX_RESULT
- CSmilMetadata::handleElement()
- {
- HX_RESULT rc = HXR_OK;
- if(m_pHandler)
- {
- rc = m_pHandler->handleMetadata(this);
- }
- return rc;
- }
- /*
- * CSmilRendererPreFetch methods
- */
- CSmilRendererPreFetch::CSmilRendererPreFetch(SMILNode* pNode):
- CSmilElement(pNode)
- {
- }
- CSmilRendererPreFetch::~CSmilRendererPreFetch()
- {
- }
- HX_RESULT
- CSmilRendererPreFetch::handleElement()
- {
- HX_RESULT rc = HXR_OK;
- if(m_pHandler)
- {
- rc = m_pHandler->handleRendererPreFetch(this);
- }
- return rc;
- }
- /*
- * CSmilEndLayout methods
- */
- CSmilEndLayout::CSmilEndLayout():
- CSmilElement(NULL)
- {
- }
- CSmilEndLayout::~CSmilEndLayout()
- {
- }
- HX_RESULT
- CSmilEndLayout::handleElement()
- {
- HX_RESULT rc = HXR_OK;
- if(m_pHandler)
- {
- rc = m_pHandler->handleEndLayout(this);
- }
- return rc;
- }
- /*
- * CSmilMetaValues methods
- */
- CSmilMetaValues::CSmilMetaValues():
- CSmilElement(NULL),
- m_pValues(0)
- {
- }
- CSmilMetaValues::~CSmilMetaValues()
- {
- HX_RELEASE(m_pValues);
- }
- /*
- * CSmilCustomTest methods:
- */
- CSmilCustomTest::CSmilCustomTest(SMILNode* pNode) :
- CSmilElement(pNode)
- , m_bDefaultState(FALSE)
- , m_bOverrideVisible(FALSE)
- {
- }
- CSmilCustomTest::~CSmilCustomTest()
- {
- }
- /*
- * CSmilSource methods
- */
- CSmilSource::CSmilSource(SMILNode* pNode):
- CSmilElement(pNode)
- {
- m_ulColor = 0;
- m_eColorType = CSS2TypeTransparent;
- m_Rect.m_dLeft = 0.0;
- m_Rect.m_eLeftType = CSS2TypeAuto;
- m_Rect.m_dTop = 0.0;
- m_Rect.m_eTopType = CSS2TypeAuto;
- m_Rect.m_dRight = 0.0;
- m_Rect.m_eRightType = CSS2TypeAuto;
- m_Rect.m_dBottom = 0.0;
- m_Rect.m_eBottomType = CSS2TypeAuto;
- m_Rect.m_dWidth = 0.0;
- m_Rect.m_eWidthType = CSS2TypeAuto;
- m_Rect.m_dHeight = 0.0;
- m_Rect.m_eHeightType = CSS2TypeAuto;
- m_lZIndex = 0;
- m_eZIndexType = CSS2TypeAuto;
- m_eFit = FitHidden;
- m_bFitSpecified = FALSE;
- m_ulBackgroundColor = 0;
- m_eBackgroundColorType = CSS2TypeTransparent;
- m_bRegPointIsPredef = TRUE;
- m_ePredefRegPoint = RegAlignTopLeft;
- m_eRegAlign = RegAlignTopLeft;
- m_bRegAlignSpecified = FALSE;
- m_bBackgroundOpacitySpecified = FALSE;
- m_ulBackgroundOpacity = 255;
- m_bMediaOpacitySpecified = FALSE;
- m_ulMediaOpacity = 255;
- m_bChromaKeySpecified = FALSE;
- m_ulChromaKey = 0;
- m_ulChromaKeyTolerance = 0;
- m_ulChromaKeyOpacity = 0;
- m_bAudioDeviceReflushHintNeeded = FALSE;
- m_eHandledBy = HandledByAuto;
- m_bBackgroundColorSpecified = FALSE;
- m_ulLinkTargetDestnLevel_pct = 100;
- m_ulLinkTargetSourceLevel_pct = 100;
- m_ulPrefetchAmount = 0;
- m_typeOfPrefetchAmount = PrefetchUnknown;
- }
- CSmilSource::~CSmilSource()
- {
- }
- HX_RESULT
- CSmilSource::handleElement()
- {
- HX_RESULT rc = HXR_OK;
- if(m_pHandler)
- {
- rc = m_pHandler->handleSource(this);
- }
- return rc;
- }
- void
- CSmilSource::setRange(const char* pRange)
- {
- // parse smpte/npt ranges:
- // smpte:12:03:14.21-12:15:26.03
- // npt:3:02.5-4:38.6
- //
- char* pPtr = (char *)strstr(pRange, "npt:");
- if(pPtr)
- {
- pPtr += 4; // point to beginning of range
- char* pHyphen = (char *)strchr(pRange, '-'); // find '-'
- if(pHyphen > pPtr)
- {
- NPTime beginTime((const char*)CHXString(pPtr, pHyphen-pPtr));
- m_ulAuthoredClipBegin = (UINT32)beginTime;
- m_ulClipBegin = m_ulAuthoredClipBegin;
- if(strlen(pHyphen+1) > 0)
- {
- NPTime endTime((const char*)CHXString(pHyphen+1));
- m_ulClipEnd = (UINT32)endTime;
- }
- }
- else if(pHyphen)
- {
- NPTime endTime((const char*)CHXString(pHyphen+1));
- m_ulClipEnd = (UINT32)endTime;
- }
- }
- else
- {
- pPtr = (char *)strstr(pRange, "smpte:");
- if(pPtr)
- {
- pPtr += 6; // point to beginning of range
- char* pHyphen = (char *)strchr(pRange, '-'); // find '-'
- if(pHyphen > pPtr)
- {
- SMPTETimeCode beginTime =
- ((const char*)CHXString(pPtr, pHyphen-pPtr));
- m_ulAuthoredClipBegin = (UINT32)beginTime;
- m_ulClipBegin = m_ulAuthoredClipBegin;
- if(strlen(pHyphen+1) > 0)
- {
- SMPTETimeCode endTime =
- ((const char*)CHXString(pPtr, pHyphen-pPtr));
- m_ulClipEnd = (UINT32)endTime;
- }
- }
- else if(pHyphen)
- {
- SMPTETimeCode endTime((const char*)CHXString(pHyphen+1));
- m_ulClipEnd = (UINT32)endTime;
- }
- }
- }
- }
- /*
- * CSmilSourceUpdate methods
- */
- CSmilSourceUpdate::CSmilSourceUpdate():
- CSmilElement(NULL)
- {
- m_updateTag = UpdateUnknown;
- m_ulUpdatedDuration = 0;
- m_bDurationIsPureOfDelay = TRUE;
- m_ulUpdatedDelay = 0;
- }
- CSmilSourceUpdate::~CSmilSourceUpdate()
- {
- }
- HX_RESULT
- CSmilSourceUpdate::handleElement()
- {
- HX_RESULT rc = HXR_OK;
- if(m_pHandler)
- {
- rc = m_pHandler->handleSourceUpdate(this);
- }
- return rc;
- }
- #if defined(HELIX_FEATURE_SMIL2_ANIMATION)
- // CSmilAnimateElement methods
- CSmilAnimateElement::CSmilAnimateElement(SMILNode* pNode)
- : CSmilElement(pNode)
- {
- // Set defaults
- m_ulSimpleDuration = ((UINT32) -1);
- m_ulActiveDuration = ((UINT32) -1);
- m_ulADNoSpeed = ((UINT32) -1);
- m_pTargetElementID = NULL;
- m_eTargetElementTag = SMILUnknown;
- m_ulNumValues = 0;
- m_ppValue = NULL;
- m_ucAttributeName = kAttrNameUnknown;
- m_ucCalcMode = kCalcModeLinear;
- m_ucAccumulate = kAccumulateNone;
- m_ucAdditive = kAdditiveReplace;
- m_ucAnimationType = kAnimTypeValues;
- m_dRepeatCount = 1.0;
- m_ulRepeatDur = ((UINT32) -1);
- m_bRepeatDurIsIndefinite = FALSE;
- m_dAccelerate = 0.0;
- m_dDecelerate = 0.0;
- m_bAutoReverse = FALSE;
- m_dSpeed = 1.0;
- m_bIndefiniteSimpleDuration = FALSE;
- m_bIndefiniteActiveDuration = FALSE;
- m_bCancelAnimation = FALSE;
- #if defined(XXXMEH_SPLINE_ANIMATION)
- m_ulNumKeyTimes = 0;
- m_pdKeyTime = NULL;
- m_ulNumKeySplines = 0;
- m_pKeySpline = NULL;
- m_ulNumPathCmds = 0;
- m_ppPathCmd = NULL;
- #endif
- }
- CSmilAnimateElement::~CSmilAnimateElement()
- {
- HX_DELETE(m_pTargetElementID);
- if (m_ppValue)
- {
- for (UINT32 i = 0; i < m_ulNumValues; i++)
- {
- HX_DELETE(m_ppValue[i]);
- }
- HX_VECTOR_DELETE(m_ppValue);
- }
- #if defined(XXXMEH_SPLINE_ANIMATION)
- HX_VECTOR_DELETE(m_pdKeyTime);
- HX_VECTOR_DELETE(m_pKeySpline);
- if (m_ppPathCmd && m_ulNumPathCmds)
- {
- for (UINT32 i = 0; i < m_ulNumPathCmds; i++)
- {
- HX_DELETE(m_ppPathCmd[i]);
- }
- }
- HX_VECTOR_DELETE(m_ppPathCmd);
- #endif
- }
- HX_RESULT CSmilAnimateElement::handleElement()
- {
- HX_RESULT retVal = HXR_OK;
- if(m_pHandler)
- {
- retVal = m_pHandler->handleAnimate(this);
- }
- return retVal;
- }
- HX_RESULT CSmilAnimateElement::getCurrentScheduledStopTime(REF(ULONG32) ulActualStopTime)
- {
- HX_RESULT ret = HXR_OK;
- if (m_ulDelay != ((UINT32) -1))
- {
- if (m_bIndefiniteActiveDuration)
- {
- ulActualStopTime = SMILTIME_INFINITY;
- }
- else
- {
- ulActualStopTime = m_ulDelay + m_ulActiveDuration;
- }
- }
- else
- {
- ret = HXR_NOT_INITIALIZED;
- }
- return ret;
- }
- #endif /* #if defined(HELIX_FEATURE_SMIL2_ANIMATION) */
- CSmilParamElement::CSmilParamElement(SMILNode* pNode)
- : CSmilElement(pNode)
- {
- m_pName = NULL;
- m_pValue = NULL;
- m_eDelivery = DeliveryClient;
- }
- CSmilParamElement::~CSmilParamElement()
- {
- HX_RELEASE(m_pName);
- HX_RELEASE(m_pValue);
- }
- /*
- * CSmilParElement methods
- */
- CSmilParElement::CSmilParElement(SMILNode* pNode):
- CSmilElement(pNode)
- {
- }
- CSmilParElement::~CSmilParElement()
- {
- }
- /*
- * CSmilSeqElement methods
- */
- CSmilSeqElement::CSmilSeqElement(SMILNode* pNode):
- CSmilElement(pNode)
- {
- }
- CSmilSeqElement::~CSmilSeqElement()
- {
- }
- /*
- * CSmilExclElement methods
- */
- CSmilExclElement::CSmilExclElement(SMILNode* pNode):
- CSmilElement(pNode)
- , m_pPauseStack(NULL)
- {
- }
- CSmilExclElement::~CSmilExclElement()
- {
- HX_DELETE(m_pPauseStack);
- }
- /*
- * CSmilPriorityClassElement methods
- */
- CSmilPriorityClassElement::CSmilPriorityClassElement(SMILNode* pNode):
- CSmilElement(pNode)
- , m_pauseDisplay(SMILPriorityClassPauseDisplayShow)
- , m_peers(SMILPriorityClassStop)
- , m_higher(SMILPriorityClassPause)
- , m_lower(SMILPriorityClassDefer)
- {
- }
- CSmilPriorityClassElement::~CSmilPriorityClassElement()
- {
- }
- /*
- * CSmilAAnchor methods
- */
- CSmilAAnchorElement::CSmilAAnchorElement(SMILNode* pNode):
- CSmilElement(pNode),
- m_show("replace")
- , m_ulSourceLevel_pct(100)
- , m_ulDestinationLevel_pct(100)
- // /XXXEH- TODO: make sure that, if show="new", this changes to play:
- , m_sourcePlaystate(SMILLinkPlaystatePause)
- , m_destinationPlaystate(SMILLinkPlaystatePlay)
- , m_bExternal(FALSE)
- , m_actuate("onRequest")
- , m_accesskey("") // /(an ISO10646 character. Default unspecified)
- , m_ulTabindex ((UINT32)-1)
- , m_target("")
- , m_bTargetIsARegion(FALSE)
- , m_bTimeValueSet(FALSE)
- , m_lAnchorBeginOffset(0)
- , m_bAnchorBeginOffsetSet(FALSE)
- , m_lAnchorEndOffset(0)
- , m_bAnchorEndOffsetSet(FALSE)
- , m_ulAnchorDuration((UINT32)-1)
- , m_ulAnchorMinActiveDur(0)
- , m_ulAnchorMaxActiveDur((UINT32)-1)
- {
- }
- CSmilAAnchorElement::~CSmilAAnchorElement()
- {
- }
- BOOL
- CSmilAAnchorElement::isCurrentLink(UINT32 ulTimeOffset,
- UINT32 ulXOffset, UINT32 ulYOffset,
- HXxRect regionRect,
- // /These 3 are ignored for <a> links:
- BOOL bResizeBehaviorIsZoom,
- double dZoomX, double dZoomY)
- {
- BOOL rc = TRUE;
- ULONG32 ulBeginRelativeToSyncBase = (UINT32)-1;
- // coords only - check for out of bounds region
- UINT32 ulRegionWidth = regionRect.right - regionRect.left;
- UINT32 ulRegionHeight = regionRect.bottom - regionRect.top;
- if(ulXOffset > ulRegionWidth ||
- ulYOffset > ulRegionHeight)
- {
- if (ANCHOR_POS_DONTCARE != ulXOffset &&
- ANCHOR_POS_DONTCARE != ulYOffset)
- {
- rc = FALSE;
- goto exit;
- }
- }
- if(m_href.GetLength() == 0)
- {
- rc = FALSE;
- }
- // /In SMIL 2.0, "a" links can also be timed, so check time offset:
- else if (!isLinkActiveAtTime(ulTimeOffset, ulBeginRelativeToSyncBase))
- {
- rc = FALSE;
- }
- exit:
- return rc;
- }
- BOOL
- CSmilAAnchorElement::isLinkActiveAtTime(UINT32 ulTimeOffset,
- REF(ULONG32)rulAnchorRelativeStartTime)
- {
- BOOL bIsActiveAtTimeOffset = TRUE;
- rulAnchorRelativeStartTime = (UINT32)-1;
- if(m_bTimeValueSet)
- {
- bIsActiveAtTimeOffset = FALSE;
- BOOL bValidDelay = m_ulDelay != (UINT32)-1;
- if(m_bAnchorBeginOffsetSet || bValidDelay)
- {
- if((m_bAnchorBeginOffsetSet &&
- (INT32)ulTimeOffset >= m_lAnchorBeginOffset) ||
- (bValidDelay && ulTimeOffset >= m_ulDelay) )
- {
- // /For PR 67170 fix, caller needs anchor's begin time to tell
- // which of multiple, active onLoad anchors to use after a seek:
- if (m_bAnchorBeginOffsetSet &&
- (INT32)ulTimeOffset >= m_lAnchorBeginOffset)
- {
- rulAnchorRelativeStartTime = m_lAnchorBeginOffset;
- }
- else
- {
- rulAnchorRelativeStartTime = m_ulDelay;
- }
- LONG32 lAnchorEndTime = -1;
- if (m_bAnchorEndOffsetSet)
- {
- lAnchorEndTime = m_lAnchorEndOffset;
- }
- else if ((UINT32)-1 != m_ulAnchorDuration)
- {
- lAnchorEndTime = (INT32)m_ulAnchorDuration;
- if (m_bAnchorBeginOffsetSet)
- {
- lAnchorEndTime += m_lAnchorBeginOffset;
- }
- }
- if(-1 != lAnchorEndTime)
- {
- if((INT32)ulTimeOffset <= lAnchorEndTime)
- {
- bIsActiveAtTimeOffset = TRUE;
- }
- }
- else
- {
- bIsActiveAtTimeOffset = TRUE;
- }
- }
- }
- else if(m_bAnchorEndOffsetSet)
- {
- if((INT32)ulTimeOffset <= m_lAnchorEndOffset)
- {
- bIsActiveAtTimeOffset = TRUE;
- }
- }
- }
- return bIsActiveAtTimeOffset;
- }
- BOOL
- CSmilAnchorElement::isLinkActiveAtTime(UINT32 ulTimeOffset,
- REF(ULONG32)rulAnchorRelativeStartTime)
- {
- BOOL bIsActiveAtTimeOffset = TRUE;
- if(m_bTimeValueSet)
- {
- bIsActiveAtTimeOffset = FALSE;
- //[SMIL 1.0 compliance] the following variable and its use, below,
- // helps fix PR 26471. We may have had only our delay set:
- BOOL bValidDelay = m_ulDelay != (UINT32)-1;
- if(m_bBeginOffsetSet || bValidDelay)
- {
- // /First, we need to make sure we're in the same time-coordinate
- // system as our syncbase (parent):
- ULONG32 ulTimeOffsetFromSyncBase = m_ulDelay;
- if (m_bCurBeginIsOffsetFromSyncBase)
- {
- ulTimeOffsetFromSyncBase =
- m_ulBeginOffsetFromSyncBase;
- }
- if ((m_bBeginOffsetSet &&
- (INT32)ulTimeOffset >= m_lBeginOffset) ||
- (bValidDelay && ulTimeOffset >= ulTimeOffsetFromSyncBase) )
- {
- // /For PR 67170 fix, caller needs anchor's begin time to tell
- // which of multiple, active onLoad anchors to use after a seek:
- if (m_bBeginOffsetSet &&
- (INT32)ulTimeOffset >= m_lBeginOffset)
- {
- rulAnchorRelativeStartTime = m_lBeginOffset;
- }
- else
- {
- rulAnchorRelativeStartTime = ulTimeOffsetFromSyncBase;
- }
- LONG32 lAnchorEndTime = -1;
- if (m_bEndOffsetSet)
- {
- lAnchorEndTime = m_lEndOffset;
- }
- else if ((UINT32)-1 != m_ulDuration)
- {
- lAnchorEndTime = (INT32)m_ulDuration;
- if (m_bBeginOffsetSet)
- {
- lAnchorEndTime += m_lBeginOffset;
- }
- }
- if(-1 != lAnchorEndTime)
- {
- if((INT32)ulTimeOffset <= lAnchorEndTime)
- {
- bIsActiveAtTimeOffset = TRUE;
- }
- }
- else
- {
- bIsActiveAtTimeOffset = TRUE;
- }
- }
- }
- else if(m_bEndOffsetSet)
- {
- if((INT32)ulTimeOffset <= m_lEndOffset)
- {
- bIsActiveAtTimeOffset = TRUE;
- }
- }
- }
- return bIsActiveAtTimeOffset;
- }
- void
- CSmilAAnchorElement::rescale(double dXScale, double dYScale,
- BOOL bResetOriginalCoords)
- {
- // nothing to do
- }
- /*
- * CSmilAnchor methods
- */
- CSmilAnchorElement::CSmilAnchorElement(SMILNode* pNode):
- CSmilAAnchorElement(pNode),
- m_zIndex(0),
- m_bCoordsSet(FALSE),
- m_ulLeftX(0),
- m_ulOriginalLeftX(0),
- m_bLeftXIsPercent(FALSE),
- m_ulTopY(0),
- m_ulOriginalTopY(0),
- m_bTopYIsPercent(FALSE),
- m_ulRightX((UINT32)-1),
- m_ulOriginalRightX((UINT32)-1),
- m_bRightXIsPercent(FALSE),
- m_ulBottomY((UINT32)-1),
- m_ulOriginalBottomY((UINT32)-1),
- m_bBottomYIsPercent(FALSE),
- m_ulRadius((UINT32)-1),
- m_ulOriginalRadius((UINT32)-1),
- m_bRadiusIsPercent(FALSE)
- , m_pVertexArray(NULL)
- , m_pOriginalVertexArray(NULL)
- , m_uiNumPoints(0)
- {
- }
- CSmilAnchorElement::~CSmilAnchorElement()
- {
- deleteVertexArrays();
- }
- void CSmilAnchorElement::deleteVertexArrays()
- {
- if (m_pVertexArray)
- {
- delete [] m_pVertexArray;
- m_pVertexArray = NULL;
- }
- if (m_pOriginalVertexArray)
- {
- delete [] m_pOriginalVertexArray;
- m_pOriginalVertexArray = NULL;
- }
- }
- void
- CSmilAnchorElement::rescale(double dXScale, double dYScale,
- BOOL bResetOriginalCoords)
- {
- if(bResetOriginalCoords)
- {
- m_ulLeftX = m_ulOriginalLeftX;
- m_ulRightX = m_ulOriginalRightX;
- m_ulTopY = m_ulOriginalTopY;
- m_ulBottomY = m_ulOriginalBottomY;
- m_ulRadius = m_ulOriginalRadius;
- if (m_pVertexArray)// /is poly shape:
- {
- for (int i=0; i < m_uiNumPoints; i++)
- {
- m_pVertexArray[i].m_lX = m_pOriginalVertexArray[i].m_lX;
- m_pVertexArray[i].m_lY = m_pOriginalVertexArray[i].m_lY;
- }
- }
- }
- else if (!m_pVertexArray)
- {
- if(!m_bLeftXIsPercent)
- {
- m_ulLeftX = (UINT32)(dXScale * (double)m_ulLeftX);
- }
- if(!m_bRightXIsPercent)
- {
- m_ulRightX = (UINT32)(dXScale * (double)m_ulRightX);
- }
- if(!m_bTopYIsPercent)
- {
- m_ulTopY = (UINT32)(dYScale * (double)m_ulTopY);
- }
- if(!m_bBottomYIsPercent)
- {
- m_ulBottomY = (UINT32)(dYScale * (double)m_ulBottomY);
- }
- if(!m_bRadiusIsPercent)
- {
- // /XXXEH- TODO: don't just average x&y scaling, but
- // make an elipse by keeping an x-radius and a y-radius val
- // and then use a formula for an elipse in the hit-test code
- // in isCurrentLink():
- m_ulRadius = (UINT32)(((dXScale+dYScale)/2.0) *
- (double)m_ulRadius);
- }
- }
- else // /is "poly" (polygon) shape:
- {
- for (int i=0; i < m_uiNumPoints; i++)
- {
- m_pVertexArray[i].m_lX =
- (LONG32)((double)((float)m_pVertexArray[i].m_lX) * dXScale);
- m_pVertexArray[i].m_lY =
- (LONG32)((double)((float)m_pVertexArray[i].m_lY) * dYScale);
- }
- }
- }
- BOOL
- CSmilAnchorElement::isCurrentLink(UINT32 ulTimeOffset,
- UINT32 ulXOffset, UINT32 ulYOffset,
- HXxRect regionRect,
- BOOL bResizeBehaviorIsZoom,
- double dZoomX, double dZoomY)
- {
- BOOL bRetval = TRUE;
- UINT32 ulRegionWidth = regionRect.right - regionRect.left;
- UINT32 ulRegionHeight = regionRect.bottom - regionRect.top;
- if(m_href.GetLength() == 0)
- {
- return FALSE;
- }
- ULONG32 ulBeginRelativeToSyncBase = (UINT32)-1;
- // first check time offset:
- if (!isLinkActiveAtTime(ulTimeOffset, ulBeginRelativeToSyncBase))
- {
- return FALSE;
- }
- if(m_bCoordsSet && (!m_shape.GetLength() || m_shape=="rect"))
- {
- UINT32 ulLeftX = m_ulLeftX;
- UINT32 ulRightX = m_ulRightX;
- UINT32 ulTopY = m_ulTopY;
- UINT32 ulBottomY = m_ulBottomY;
- // /Doing this resizing of absolute (not percent) coordinate values
- // fixes PR 77231; the hotspot should scale along with the media
- // when the player is resized:
- // (NOTE: This only fixes "rect" version of PR 77231):
- if (bResizeBehaviorIsZoom && dZoomX != 1.0 && dZoomY != 1.0)
- {
- if (!m_bLeftXIsPercent)
- {
- ulLeftX *= dZoomX;
- }
- if (!m_bRightXIsPercent)
- {
- ulRightX *= dZoomX;
- }
- if (!m_bTopYIsPercent)
- {
- ulTopY *= dZoomX;
- }
- if (!m_bBottomYIsPercent)
- {
- ulBottomY *= dZoomX;
- }
- }
- // normalize to pixel coords
- if(m_bLeftXIsPercent)
- {
- ulLeftX = (UINT32)(((double)m_ulLeftX/100.0) * ulRegionWidth);
- }
- if(m_bRightXIsPercent)
- {
- ulRightX = (UINT32)(((double)m_ulRightX/100.0) * ulRegionWidth);
- }
- if(m_bTopYIsPercent)
- {
- ulTopY = (UINT32)(((double)m_ulTopY/100.0) * ulRegionHeight);
- }
- if(m_bBottomYIsPercent)
- {
- ulBottomY = (UINT32)(((double)m_ulBottomY/100.0) * ulRegionHeight);
- }
- if(ulXOffset >= ulLeftX &&
- ulXOffset <= ulRightX &&
- ulYOffset >= ulTopY &&
- ulYOffset <= ulBottomY)
- {
- return TRUE;
- }
- else
- {
- if (ANCHOR_POS_DONTCARE != ulXOffset &&
- ANCHOR_POS_DONTCARE != ulYOffset)
- {
- return FALSE;
- }
- return TRUE;
- }
- }
- else if(m_bCoordsSet && (m_shape=="circle"))
- {
- UINT32 ulCenterX = m_ulLeftX;
- UINT32 ulCenterY = m_ulTopY;
- UINT32 ulRadius = m_ulRadius;
- // /Doing this resizing of absolute (not percent) coordinate values
- // fixes "circle" version of PR 77231; the hotspot should scale along
- // with the media when the player is resized:
- if (bResizeBehaviorIsZoom && dZoomX != 1.0 && dZoomY != 1.0)
- {
- if (!m_bLeftXIsPercent)
- {
- ulCenterX *= dZoomX;
- }
- if (!m_bTopYIsPercent)
- {
- ulCenterY *= dZoomX;
- }
- if (!m_bRadiusIsPercent)
- {
- ulRadius *= dZoomY;
- }
- }
- // normalize to pixel coords
- if(m_bLeftXIsPercent)
- {
- ulCenterX = (UINT32)(((double)ulCenterX/100.0) * ulRegionWidth);
- }
- if(m_bTopYIsPercent)
- {
- ulCenterY = (UINT32)(((double)ulCenterY/100.0) * ulRegionHeight);
- }
- if(m_bRadiusIsPercent)
- {
- ulRadius = (UINT32)(((double)m_ulRadius/100.0) * ulRegionHeight);
- }
- double dXDistanceToCenter = double( (ulXOffset>ulCenterX)?
- ulXOffset-ulCenterX : ulCenterX-ulXOffset);
- double dYDistanceToCenter = double( (ulYOffset>ulCenterY)?
- ulYOffset-ulCenterY : ulCenterY-ulYOffset);
- // /Compare squared distances rather than doing expensive sqare root:
- double dDistanceToCenterSquared =
- (dXDistanceToCenter*dXDistanceToCenter) +
- (dYDistanceToCenter*dYDistanceToCenter);
- double dRadiusSquared = double(ulRadius*ulRadius);
- // /It's within the circle if it's within the radius:
- if (dDistanceToCenterSquared <= dRadiusSquared)
- {
- return TRUE;
- }
- else
- {
- if (ANCHOR_POS_DONTCARE != ulXOffset &&
- ANCHOR_POS_DONTCARE != ulYOffset)
- {
- return FALSE;
- }
- return TRUE;
- }
- }
- else if (m_bCoordsSet && (m_shape=="poly"))
- {
- bRetval = isPointInPolygon(ulXOffset, ulYOffset, regionRect,
- bResizeBehaviorIsZoom? dZoomX : 1.0,
- bResizeBehaviorIsZoom? dZoomY : 1.0);
- }
- else if(ulXOffset > ulRegionWidth ||
- ulYOffset > ulRegionHeight)
- // assume time OK, coords OK if within bounds of region
- {
- if (ANCHOR_POS_DONTCARE != ulXOffset &&
- ANCHOR_POS_DONTCARE != ulYOffset)
- {
- return FALSE;
- }
- }
- return bRetval;
- }
- BOOL
- CSmilAnchorElement::isPointInPolygon(INT32 lXOffset, INT32 lYOffset,
- HXxRect regionRect,
- double dZoomX, double dZoomY)
- {
- INT32 xnew,ynew;
- INT32 xold,yold;
- INT32 x1,y1;
- INT32 x2,y2;
- BOOL bIsInside=FALSE;
- UINT32 ulRegionWidth = regionRect.right - regionRect.left;
- UINT32 ulRegionHeight = regionRect.bottom - regionRect.top;
- // We must have at least 3 points to have a polygon
- if (m_uiNumPoints >= 3)
- {
- xold = m_pVertexArray[m_uiNumPoints-1].m_lX;
- yold = m_pVertexArray[m_uiNumPoints-1].m_lY;
- // /Convert percentages to coords:
- if(m_pVertexArray[m_uiNumPoints-1].m_bXIsPercent)
- {
- xold = (UINT32)(((double)xold/100.0) * ulRegionWidth);
- }
- // /NOTE: to fix PR 77231 (poly version) it would have been nice to
- // just apply 1/dZoomX and 1/dZoomY to lXOffset and lYOffset but we
- // can't because some vertices could be percentages while others not,
- // so we're stuck multiplying each non-percent value, one at a time:
- else if (dZoomX != 1.0)
- {
- xold *= dZoomX; // /Helps fix poly version of PR 77231.
- }
- if(m_pVertexArray[m_uiNumPoints-1].m_bYIsPercent)
- {
- yold = (UINT32)(((double)yold/100.0) * ulRegionHeight);
- }
- else if (dZoomY != 1.0)
- {
- yold *= dZoomY; // /Helps fix poly version of PR 77231.
- }
- for (UINT16 i=0; i < m_uiNumPoints; i++)
- {
- xnew = m_pVertexArray[i].m_lX;
- ynew = m_pVertexArray[i].m_lY;
- // /Convert percentages to coords:
- if(m_pVertexArray[i].m_bXIsPercent)
- {
- xnew = (UINT32)(((double)xnew/100.0) * ulRegionWidth);
- }
- else if (dZoomX != 1.0)
- {
- xnew *= dZoomX; // /Helps fix poly version of PR 77231.
- }
- if(m_pVertexArray[i].m_bYIsPercent)
- {
- ynew = (UINT32)(((double)ynew/100.0) * ulRegionHeight);
- }
- else if (dZoomY != 1.0)
- {
- ynew *= dZoomY; // /Helps fix poly version of PR 77231.
- }
- if (xnew > xold)
- {
- x1 = xold;
- x2 = xnew;
- y1 = yold;
- y2 = ynew;
- }
- else
- {
- x1 = xnew;
- x2 = xold;
- y1 = ynew;
- y2 = yold;
- }
- if ((xnew < lXOffset) == (lXOffset <= xold) &&
- ((LONG32)lYOffset - (LONG32)y1) * (LONG32)(x2-x1) <
- ((LONG32)y2 - (LONG32)y1) * (LONG32)(lXOffset - x1))
- {
- bIsInside = !bIsInside;
- }
- xold = xnew;
- yold = ynew;
- }
- }
- return bIsInside;
- }
- HX_RESULT
- CSmilAnchorElement::convertRawPolyData(const char* pCoords)
- {
- HX_RESULT retval = HXR_OK;
- const char* pchData = pCoords;
- UINT16 uiNumValues=0;
- UINT16 uiLength=0;
- char* szBuffer=NULL;
- UINT16 uiX=0;
- UINT16 uiY=0;
- if (!pCoords || strlen(pCoords) < 3)
- {
- retval = HXR_INVALID_PARAMETER;
- }
- else
- {
- UINT16 uiNumCommas = 0;
- // /First, get number of points:
- while (*pchData)
- {
- if (',' == *pchData)
- {
- uiNumCommas++;
- }
- pchData++;
- };
- // /There *must* be an odd # of commas in order to have x,y pairs:
- if (0 == (uiNumCommas % 2))
- {
- retval = HXR_INVALID_PARAMETER;
- }
- // /Can't have poly with fewer than 3 pts. It's not an error, but
- // it's useless so we ignore it:
- else if (uiNumCommas < 5)
- {
- retval = HXR_OK;
- }
- else
- {
- deleteVertexArrays();
- // /Get polygon values: (x1,y1,x2,y2,...xn,yn)
- m_uiNumPoints = (uiNumCommas+1) / 2;
- m_pVertexArray = new CSmilAnchorVertex[m_uiNumPoints];
- m_pOriginalVertexArray = new CSmilAnchorVertex[m_uiNumPoints];
- if (!m_pVertexArray || !m_pOriginalVertexArray)
- {
- retval = HXR_OUTOFMEMORY;
- }
- else
- {
- retval = HXR_OK;
- int i = 0;
- char* pCoordCopy = new_string(pCoords);
- char* pTok = strtok(pCoordCopy, ",");
- for(i=0; i<m_uiNumPoints,pTok; ++i)
- {
- char* pEndPtr = 0;
- // /First, get x coord:
- double dVal = strtod(pTok, &pEndPtr);
- m_pOriginalVertexArray[i].m_lX = m_pVertexArray[i].m_lX =
- (INT32)((float)dVal);
- m_pOriginalVertexArray[i].m_bXIsPercent =
- m_pVertexArray[i].m_bXIsPercent =
- (*pEndPtr == '%') ? TRUE: FALSE;
- pTok = strtok(NULL, ",");
- // /Next, get y coord:
- dVal = strtod(pTok, &pEndPtr);
- m_pOriginalVertexArray[i].m_lY = m_pVertexArray[i].m_lY =
- (INT32)((float)dVal);
- m_pOriginalVertexArray[i].m_bYIsPercent =
- m_pVertexArray[i].m_bYIsPercent =
- (*pEndPtr == '%') ? TRUE: FALSE;
- pTok = strtok(NULL, ",");
- } // end for(i...
- delete [] pCoordCopy;
- }
- }
- }
- return retval;
- }
- /*
- * CSmilAddGroup methods
- */
- CSmilAddGroup::CSmilAddGroup():
- CSmilElement(NULL),
- m_nGroup(0),
- m_pValues(NULL),
- m_nTotalTracks(0),
- m_nInitTracks(0),
- m_ulDuration((UINT32)-1)
- {
- }
- CSmilAddGroup::~CSmilAddGroup()
- {
- HX_RELEASE(m_pValues);
- }
- HX_RESULT
- CSmilAddGroup::handleElement()
- {
- HX_RESULT rc = HXR_OK;
- if(m_pHandler)
- {
- rc = m_pHandler->handleAddGroup(this);
- }
- return rc;
- }
- #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS)
- CSmilTransition::CSmilTransition(SMILNode* pNode) :
- CSmilElement(pNode)
- {
- m_dStartProgress = 0.0;
- m_dEndProgress = 1.0;
- m_eDirection = TransitionDirectionForward;
- m_ulFadeColor = 0x00000000; // black
- m_ulHorzRepeat = 1;
- m_ulVertRepeat = 1;
- m_ulBorderWidth = 0;
- m_ulBorderColor = 0;
- m_bBlendBorder = FALSE;
- }
- CSmilTransition::~CSmilTransition()
- {
- }
- HX_RESULT CSmilTransition::handleElement()
- {
- HX_RESULT retVal = HXR_OK;
- if(m_pHandler)
- {
- retVal = m_pHandler->handleTransition(this);
- }
- return retVal;
- }
- #endif /* #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS) */
- CSmilBodyElement::CSmilBodyElement(SMILNode* pNode) :
- CSmilElement(pNode)
- {
- m_eAccessErrorBehavior = AccessErrorBehaviorContinue;
- }
- CSmilBodyElement::~CSmilBodyElement()
- {
- }