📄 smlparse.cpp
字号:
HX_RESULTCSmilParser::init(BOOL bStoreErrors){ HX_RESULT rc = HXR_OK; close(); m_pNodeListStack = new CHXStack; m_pPacketQueue = new CHXSimpleList; m_pIDMap = new CHXMapStringToOb; m_pAddGroupMap = new CHXMapLongToObj; m_bStoreErrors = bStoreErrors; if (m_bStoreErrors) { // XXXJHUG error stuff. // In the future if there was any reason, we could // store the errors in the nodes that the errors occurred in. // for now when we get an error notification, we will // just call the storeError function which will add // a new IHXBuffer to this array.. This will also be // called when problems are found with tags... // this will save having to walk the tree when it // is time to dump the errors. m_pErrors = new CHXPtrArray; } SMILNode* pRootNode = new SMILNode; pRootNode->m_id = "root"; pRootNode->m_name = "root"; m_pNodeList = new SMILNodeList; pRootNode->m_pNodeList = m_pNodeList; m_pNodeList->m_pParentNode = pRootNode; m_pNodeListStack->Push(pRootNode);#if !defined(USE_EXPAT_FOR_SMIL)//#define USE_EXPAT_FOR_SMIL#endif#ifdef USE_EXPAT_FOR_SMIL rc = m_pClassFactory->CreateInstance(CLSID_IHXXMLParser, (void**)&m_pParser); if (FAILED(rc)) { // they don't have the parser... use old one? // Don't QI core for IID_IHXXMLParser; use our own instance. m_pParser = new HXXMLParser; if (m_pParser) { rc = HXR_OK; m_pParser->AddRef(); } else { rc = HXR_OUTOFMEMORY; } } if (SUCCEEDED(rc)) { m_pResponse = new CSmilParserResponse(this); m_pResponse->AddRef(); // Expat is created off the CCF. // In strict mode it requires 100% compliant XML. rc = m_pParser->Init(m_pResponse, "iso-8859-1", TRUE); }#else // Don't QI core for IID_IHXXMLParser; use our own instance. HXXMLParser* parser = new HXXMLParser(); if (parser) { parser->AddRef(); } else { rc = HXR_OUTOFMEMORY; } if (SUCCEEDED(rc)) { m_pResponse = new CSmilParserResponse(this); m_pResponse->AddRef(); rc = parser->Init(m_pResponse, NULL, TRUE); // strict parser } if (m_bStoreErrors && parser) { parser->InitErrorNotifier(m_pResponse); } m_pParser = (IHXXMLParser*)parser;#endif return rc;}HX_RESULTCSmilParser::parse(IHXBuffer* pBuffer, BOOL bIsFinal){ HX_RESULT rc = HXR_OK; if (m_bFirstPacket) { m_bFirstPacket = FALSE; time(&m_tRefTime); } rc = m_pParser->Parse(pBuffer, bIsFinal); if (SUCCEEDED(rc) && FAILED(m_lParseError)) { rc = m_lParseError; } if(HXR_OK != rc) { m_pParser->GetCurrentLineNumber(m_ulErrorLineNumber); m_pParser->GetCurrentColumnNumber(m_ulErrorColumnNumber); HX_RELEASE(m_pErrorText); m_pParser->GetCurrentErrorText(m_pErrorText); } return rc;}HX_RESULTCSmilParser::durationResolved(const char* pID, UINT32 ulDuration, // /Defaults to FALSE: BOOL bSetByParent, BOOL bDurationExtendingDueToPause){ HX_RESULT rc = HXR_OK; SMILNode* pNode = NULL; if(m_pIDMap->Lookup(pID, (void*&)pNode)) { if (pNode->m_pElement->m_bIndefiniteDuration) {#if defined(XXXEH_OLD_SPECIAL_CASE_HANDLING_OF_INDEF_DUR) goto cleanup;#endif } // add duration to parent element if(pNode && pNode->m_pElement && pNode->m_pElement->m_pTimelineElement) { pNode->m_pElement->m_pTimelineElement->setDuration(ulDuration, bSetByParent, bDurationExtendingDueToPause); } }#if defined(XXXEH_OLD_SPECIAL_CASE_HANDLING_OF_INDEF_DUR)cleanup:#endif return rc;}BOOL AncestorEventsAreResolved(SMILNode* pNode, SMILNode* pOriginalChildNode){ if (!pNode || !pNode->m_pElement || !pNode->m_pParent || pNode->m_tag == SMILBody) { return TRUE; } // /For any parent that's not a timeline element, e.g., priorityClass, // just ignore and return its parent's results: else if (!pNode->m_pElement->m_pTimelineElement) { return AncestorEventsAreResolved(pNode->m_pParent, pOriginalChildNode); } //Now, look to see if its duration and delay events, if any, are // resolved: if ( ( (pNode->m_pElement->m_pTimelineElement->durationEvent() && !pNode->m_pElement->m_pTimelineElement->durationSet() && // /Fixes 1/2 of PR 50535: don't care about duration event for child // itself; it's OK to add a timeline element that has an unresolved // end; (but if parent has unresolved end, we may need to wait): pNode != pOriginalChildNode) || (pNode->m_pElement->m_pTimelineElement->delayEvent() && !pNode->m_pElement->m_pTimelineElement->initialDelaySet()) ) && //[SMIL 1.0 compliance] Helps fix PR 32578: //However, if we have a duration event and it's based on a child's // timing (as can happen via endsync="id(child)", then we want to // avoid this element waiting for its parent to be resolved while // the parent is waiting for this element to be resolved: (!pNode->m_pElement->m_pTimelineElement->durationEvent() || SMILEventSourceID != pNode->m_pElement->m_nEndsyncEventSourceTag) ) { return FALSE; //We still need to await event resolution. } //pNode is ok but its dependency ancestors may still be unresolved and // thus pNode may still have timing constraints from its dependency // ancestors due to their unresolved event(s): return AncestorEventsAreResolved(pNode->m_pParent, pOriginalChildNode);}HX_RESULTCSmilParser::adjustForNegativeOffset(const char* pID){ HX_RESULT pnresult = HXR_OK; SMILNode* pNode = 0; if(!m_pIDMap->Lookup(pID, (void*&)pNode)) { pnresult = HXR_FAILED; } else if (pNode && pNode->m_pElement && !pNode->m_pElement->m_bInsertedIntoTimeline && pNode->m_pParent && pNode->m_pParent->m_pElement) { // /Use syncBase, not parent here (in case parent is <a>, <switch>, // or <priorityClass> element); this fixes bug (PR 56233 repro case) // where clipBegin was calculted wrong, below, because priorityClass // was being used as syncbase and it had a begin time later than this: SMILNode* pSyncBaseNode = getSyncAncestor(pNode); if (!pSyncBaseNode || !pSyncBaseNode->m_pElement) { pnresult = HXR_FAILED; goto cleanup; } // /If we have a negative begin offset or delay which starts us // earlier than the begin offset or delay of our syncbase, we need // to do a clip-begin equal to the difference, and we need to // update our duration as well: LONG32 lParentBegin = // /If delay is valid, use it otherwise use valid beginOffset pSyncBaseNode->m_pElement->m_ulDelay != ((UINT32)-1) ? (LONG32)pSyncBaseNode->m_pElement->m_ulDelay : pSyncBaseNode->m_pElement->m_bBeginOffsetSet? pSyncBaseNode->m_pElement->m_lBeginOffset : 0; LONG32 lCurElementBegin = pNode->m_pElement->m_ulDelay != ((UINT32)-1) ? (LONG32)pNode->m_pElement->m_ulDelay : pNode->m_pElement->m_bBeginOffsetSet? pNode->m_pElement->m_lBeginOffset : // /In adjustForNegativeOffset(): // /Fixes case where parent has explicit dur, explicit // begin offset, and pNode's element begins on an event; // this used to set lCurElementBegin to 0 and erroneous // clip-begin equal to parent's begin offset would ensue: MAX_LONG32; // /First, we need to see if this is happening during playback; if // so, our begin may have resolved to a time in the past that is // later than our sync-parent's begin; in that case, we need to // adjust the clip-begin and delay to account for the diff between // now and lCurElementBegin: if (m_lLastCheckPendingTime > (lCurElementBegin + // /(re)Fixes broken long-sync-arc test file // BUG-20001110_BeginOffsetInPar...BeginningOnClickAllowsSync.smi // where the clipBegin was being *re*-computed here, after // having already been adjusted in setDelay() for a long-sync- // arc negative offset. We shouldn't do any adjustment here // if the difference is very small (which is not due to // user or authored delay clipping, but is due to processor // time between when our parent resolved and when the last // check pending time): CHECKPENDING_TIME_VS_CURTIME_FUDGE_FACTOR)) { lParentBegin = m_lLastCheckPendingTime; } if (lCurElementBegin < lParentBegin) { LONG32 lDiff = lParentBegin - lCurElementBegin; HX_ASSERT(lDiff >= 0); if (lDiff > 0) { ULONG32 ulPriorPureDuration = pNode->m_pElement->getPureDuration(); ULONG32 ulDiff = (ULONG32)lDiff; // /If clip-begin is invalid, set it otherwise add to it: pNode->m_pElement->m_ulClipBegin = ((UINT32)-1 == pNode->m_pElement->m_ulAuthoredClipBegin? ulDiff : ulDiff+pNode->m_pElement->m_ulAuthoredClipBegin); if ((UINT32)-1 != pNode->m_pElement->m_ulDuration) { if (pNode->m_pElement->m_ulDuration > ulDiff) { pNode->m_pElement->m_ulDuration -= ulDiff; } // /else duration is negative; it can't ever play: else { pNode->m_pElement->m_ulDuration = 0; } } // /And, we should now begin when our parent does: pNode->m_pElement->m_ulDelay = lParentBegin; // /Only reset duration if it's not 0xFFFFFFFF and // if it's not the same as it was before: if ((UINT32)-1 != pNode->m_pElement->m_ulDuration && ulPriorPureDuration != pNode->m_pElement->getPureDuration()) { resetTimelineElementDuration(pID, pNode->m_pElement->getPureDuration(), ulPriorPureDuration); } if (m_pTimelineElementManager) m_pTimelineElementManager->notify(pID); } } }cleanup: return pnresult;}voidCSmilParser::insertTimelineElement(const char* pID, UINT32 ulDelay){#if defined(_DEBUG) && defined(XXXEH_DEBUGOUT_ADDDURATION){ FILE* f1 = ::fopen("c:\\smil2AddDuration.txt", "a+"); ::fprintf(f1, "CSmilParser::insertTimelineElement(%s, delay=%lu) _-_-_-_-_-_-_-_-_\n", (const char*)pID, ulDelay); ::fclose(f1);}#endif SMILNode* pNode = 0; if(m_pIDMap->Lookup(pID, (void*&)pNode)) { if(pNode && pNode->m_pElement && // /XXXEH- TODO: we need to handle restart!="never" which // means that the following if condition should take this // into account: !pNode->m_pElement->m_bInsertedIntoTimeline && //[SMIL 1.0 compliance] Helps fix PR 16629: // We don't want to insert a node into the timeline if // its begin is dependent on another (not-yet- // resolved) element: ((!pNode->m_pElement->m_pTimelineElement->delayEvent() || pNode->m_pElement->m_pTimelineElement->initialDelaySet()) ) //[SMIL 1.0 compliance] Helps fix 14420: // First, we need to look all the way up the tree of ancestors // to see if any of them have event-based delays or durations // and to make sure the appropriate time(s) are resolved. If // not, we'll have to await those event resolutions before // inserting this element into the timeline: && AncestorEventsAreResolved(pNode, pNode) // /For SMIL 2.0, we can have begin="indefinite" which should // be treated as un unresolved event (but only if that's the // sole begin time specified; begin="indefinite; 5s" should be // treated as begin="5s"): && !pNode->m_pElement->m_bIndefiniteBegin ) { ULONG32 ulDelayBeyondParentDelay = 0; ULONG32 ulSyncBaseDelay = 0; SMILNode* pSyncAncestor = getSyncAncestor(pNode); HX_ASSERT((UINT32)-1 != pSyncAncestor->m_pElement->m_ulDelay); // /Check hard time boundaries set by parent: if (pSyncAncestor && pSyncAncestor->m_pElement && (UINT32)-1 != pSyncAncestor->m_pElement->m_ulDelay) { ulSyncBaseDelay = pSyncAncestor->m_pElement->m_ulDelay; ulDelayBeyondParentDelay = ulDelay - ulSyncBaseDelay; HX_ASSERT(ulDelay >= ulSyncBaseDelay); if (ulDelay < ulSyncBaseDelay) { ulDelayBeyondParentDelay = 0; } // /If child has delay beyond parent's delay+duration, i.e., // begin resolved on an event or sync arc, then don't insert it: else { if (pSyncAncestor->m_pElement->m_bHasExplicitDur && !pSyncAncestor->m_pElement->m_bIndefiniteDuration && !pSyncAncestor->m_pElement->m_bIndefiniteEnd && (ulDelayBeyondParentDelay >= pSyncAncestor->m_pElement->m_ulDuration) ) { goto cleanup; //It can't ever play. } else if (pSyncAncestor->m_pElement->m_bEndOffsetSet && !pSyncAncestor->m_pElement->m_bIndefiniteDuration && !pSyncAncestor->m_pElement->m_bIndefiniteEnd) { if (ulDelayBeyondParentDelay >= pSyncAncestor->m_pElement->m_ulDuration) { goto cleanup; //It can't ever play. } } } } else { // /Fixes PR 50411: long sync-arc begin resolved before parent // begin resolved and is thus not adjusted for any offset // from parent begin; dur:=0 if it ends before parent begin: if (pSyncAncestor) { pNode->m_pElement->m_bAwaitingSyncAncestorBeginNotification= TRUE; } goto cleanup; // /Wait to insert this until parent is resolved. }#define XXXEH_ABOVE_SHOULD_HANDLE_THIS__REMOVE_IF_NO_ASSERT0_BY_20010530#if defined(XXXEH_ABOVE_SHOULD_HANDLE_THIS__REMOVE_IF_NO_ASSERT0_BY_20010530) // /[SMIL 1.0 Compliance] Fixes PR 27644: // if our begin offset is same or greater than our parent's // end offset, then we should be ignored: if ( pNode->m_pParent && pNode->m_pParent->m_pElement && pNode->m_pElement->m_bBeginOffsetSet && pNode->m_pParent->m_pElement->m_bEndOffsetSet && (pNode->m_pElement->m_lBeginOffset > pNode->m_pParent->m_pElement->m_lEndOffset) ) { // /See if above replaces this code; if no assert reported by // 2001-05-20, then I'm going to remove this whole if() block: HX_ASSERT(0 && "mailto: ehodge@real.com"); goto cleanup; //Don't insert this because it can't ever play. } // /Also, need to check parent *dur* and make sure we don't // exceed it if it's been explicitly set to a finite amount: if ( pNode->m_pParent && pNode->m_pParent->m_pElement && pNode->m_pElement->m_bBeginOffsetSet && pNode->m_pParent->m_pElement->m_bHasExplicitDur && !pNode->m_pParent->m_pElement->m_bIndefiniteDuration && (pNode->m_pElement->m_lBeginOffset > 0 && (UINT32)pNode->m_pElement->m_lBeginOffset > pNode->m_pParent->m_pElement->m_ulDuration) ) { // /See if above replaces this code; if no assert reported by // 2001-05-20, then I'm going to remove this whole if() block: HX_ASSERT(0 && "mailto: ehodge@real.com"); goto cleanup; //Don't insert this because it can't ever play. }#endif // If this element uses media markers for clipBegin // then those markers need to be resolved if (pNode->m_pElement->m_bClipBeginUsesMarker && !pNode->m_pElement->m_bClipBeginMarkerResolved) { // Set the flag saying we WOULD have scheduled // this element except the clip begin marker wasn't
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -