smlparse.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:879k
- // XXXMEH - illegal accelerate attribute
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadAttribute,
- pName,
- pAnim->m_pNode->m_ulTagStartLine);
- }
- }
- else if(strcmp(pszAttr, "decelerate") == 0)
- {
- retVal = parseAccelDecel(pszVal, pAnim->m_dDecelerate);
- if (FAILED(retVal))
- {
- // XXXMEH - illegal decelerate attribute
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadAttribute,
- pName,
- pAnim->m_pNode->m_ulTagStartLine);
- }
- }
- else if(strcmp(pszAttr, "autoReverse") == 0)
- {
- if (strcmp(pszVal, "true") == 0)
- {
- pAnim->m_bAutoReverse = TRUE;
- }
- else if (strcmp(pszVal, "false") == 0)
- {
- pAnim->m_bAutoReverse = FALSE;
- }
- else
- {
- // XXXMEH - illegal autoReverse
- retVal = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadAttribute,
- pName,
- pAnim->m_pNode->m_ulTagStartLine);
- }
- }
- else if(strcmp(pszAttr, "speed") == 0)
- {
- double dVal = 0.0;
- retVal = HXParseDouble(pszVal, dVal);
- if (SUCCEEDED(retVal))
- {
- // Spec explicitly says to ignore a speed of 0.0,
- // so if we see a 0.0, we simply set it back to
- // the default speed of 1.0
- if (dVal == 0.0)
- {
- dVal = 1.0;
- }
- // Assign to the speed parameter
- pAnim->m_dSpeed = dVal;
- }
- else
- {
- // XXXMEH - illegal speed attribute
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadAttribute,
- pName,
- pAnim->m_pNode->m_ulTagStartLine);
- }
- }
- }
- #if defined(XXXMEH_SPLINE_ANIMATION)
- else if (pNSInfo->m_eNamespace == NamespaceSMIL2SplineAnimation)
- {
- // We need to parse for "keyTimes", "keySplines", "path"
- if(strcmp(pszAttr, "keyTimes") == 0)
- {
- retVal = parseKeyTimes(pszVal, pAnim);
- }
- else if(strcmp(pszAttr, "keySplines") == 0)
- {
- retVal = parseKeySplines(pszVal, pAnim);
- }
- else if(strcmp(pszAttr, "path") == 0)
- {
- retVal = parseSVGPath(pszVal, pAnim);
- }
- else if (strcmp(pszAttr, "calcMode") == 0)
- {
- bGotNSCalcMode = TRUE;
- if (strcmp(pszVal, "discrete") == 0)
- {
- pAnim->m_ucCalcMode = kCalcModeDiscrete;
- }
- else if (strcmp(pszVal, "linear") == 0)
- {
- pAnim->m_ucCalcMode = kCalcModeLinear;
- }
- else if (strcmp(pszVal, "paced") == 0)
- {
- pAnim->m_ucCalcMode = kCalcModePaced;
- }
- else if (strcmp(pszVal, "spline") == 0)
- {
- pAnim->m_ucCalcMode = kCalcModeSpline;
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- if (FAILED(retVal))
- {
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadAttribute,
- pName,
- pAnim->m_pNode->m_ulTagStartLine);
- }
- }
- #endif // #if defined(XXXMEH_SPLINE_ANIMATION)
- }
- }
- }
- HX_RELEASE(pVal);
- if (SUCCEEDED(retVal))
- {
- rc = pAnim->m_pNode->m_pValues->GetNextPropertyCString(pName, pVal);
- }
- }
- // /Fixes animate version of PR 60111: : if this didn't have a "begin"
- // attribute, then set the following to TRUE because default begin is a
- // clock value (if our syncBase isn't an excl):
- if (!pAnim->m_pBeginTimeList)
- {
- SMILNode* pSyncBase = getSyncAncestor(pAnim->m_pNode);
- if (pSyncBase && SMILExcl != pSyncBase->m_tag)
- {
- pAnim->m_bHasAtLeastOneNonEventBasedBegin = TRUE;
- }
- }
- if (SUCCEEDED(retVal))
- {
- // Set the authored dur
- pAnim->m_ulAuthoredDur = pAnim->m_ulDuration;
- // If our "fill" attribute is "default", then we have
- // to resolve it from either our fillDefault attribute
- // (which may involve checking our ancestors).
- resolveFillValue(pAnim);
- // If this element didn't have a "begin" attribute,
- // then set the following to TRUE because default begin is a clock value
- // (if our syncBase isn't an excl):
- if (!pAnim->m_pBeginTimeList)
- {
- SMILNode* pSyncBase = getSyncAncestor(pAnim->m_pNode);
- if (pSyncBase && SMILExcl != pSyncBase->m_tag)
- {
- pAnim->m_bHasAtLeastOneNonEventBasedBegin = TRUE;
- }
- }
- // Now we can do some additional checking
- //
- // SPEC: If the target attribute does not support linear
- // interpolation (e.g. for strings), or if the values attribute
- // has only one value, the calcMode attribute is ignored and
- // discrete interpolation is used.
- // SPEC: This attribute (accumulate) is ignored if the target
- // attribute value does not support addition. (Thus, if it
- // is ignored, it defaults to "none").
- // SPEC: This attribute (additive) is ignored if the target
- // attribute does not support additive animation. (Thus, if
- // it is ignored, then it defaults to "replace").
- if (pAnim->m_ucAttributeName == kAttrNameCoords ||
- pAnim->m_ucAttributeName == kAttrNameValue)
- {
- pAnim->m_ucCalcMode = kCalcModeDiscrete;
- pAnim->m_ucAccumulate = kAccumulateNone;
- pAnim->m_ucAdditive = kAdditiveReplace;
- }
- // If the attribute doesn't have a meaningful notion of distance,
- // then we can't do paced animation. Therefore, if we specified
- // paced for one of these attributes, then we should default
- // back to linear animation. Note that we don't have to worry
- // about coords, since it was handled separately above.
- if (pAnim->m_ucCalcMode == kCalcModePaced &&
- (pAnim->m_ucAttributeName == kAttrNameZIndex ||
- pAnim->m_ucAttributeName == kAttrNameSoundLevel))
- {
- pAnim->m_ucCalcMode = kCalcModeLinear;
- }
- // Check to make sure that accelerate and decelerate attributes
- // don't sum to more than 1.0. Spec says:
- //
- // The sum of accelerate and decelerate must not exceed 1.
- // If the individual values of the accelerate and decelerate
- // attributes are between 0 and 1 and the sum is greater
- // than 1, then both the accelerate and decelerate attributes
- // will be ignored and the timed element will behave as if
- // neither attribute was specified.
- if (pAnim->m_dAccelerate + pAnim->m_dDecelerate > 1.0)
- {
- // Reset them to their defaults, as
- // if they had not been specified.
- pAnim->m_dAccelerate = 0.0;
- pAnim->m_dDecelerate = 0.0;
- }
- // If the target element is not specified, then make
- // the parent element the target element
- if (!bTargetElementSpecified)
- {
- if (pAnim->m_pNode->m_pParent)
- {
- pAnim->m_pTargetElementID = new CHXString(pAnim->m_pNode->m_pParent->m_id);
- if (pAnim->m_pTargetElementID)
- {
- // Check to see if this is a real id
- SMILNode* pNode = NULL;
- if(!m_pIDMap->Lookup((const char*) *pAnim->m_pTargetElementID,
- (void*&)pNode))
- {
- // There's no element with this id in the map
- retVal = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorNonexistentID,
- pName,
- pAnim->m_pNode->m_ulTagStartLine);
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- else
- {
- // XXXMEH - huh? no parent?
- HX_ASSERT(FALSE);
- retVal = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorGeneralError,
- pName,
- pAnim->m_pNode->m_ulTagStartLine);
- }
- }
- // If the attribute was not specified, then we have to
- // be <animateMotion>, since these implicitly target
- // attributes.
- if (SUCCEEDED(retVal) && !bAttrNameSpecified)
- {
- if (pAnim->m_pNode->m_tag == SMILAnimateMotion)
- {
- // If we are <animateMotion>, then we know we are
- // animating "left" and "top" of a region.
- pAnim->m_ucAttributeName = kAttrNameLeftTop;
- }
- else
- {
- // Uh-oh, no attribute name specified, but
- // we are not <animateMotion>. This is an error.
- retVal = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorRequiredAttributeMissing,
- "attributeName",
- pAnim->m_pNode->m_ulTagStartLine);
- }
- }
- if (SUCCEEDED(retVal))
- {
- // Now let's check to see that the animation element,
- // target element, the attribute name match up correctly
- SMILNode* pNode = NULL;
- if(m_pIDMap->Lookup((const char*) *pAnim->m_pTargetElementID,
- (void*&)pNode))
- {
- // Set the target element tag
- pAnim->m_eTargetElementTag = pNode->m_tag;
- // Check the element/attribute combination
- if (pAnim->m_pNode->m_tag == SMILAnimate ||
- pAnim->m_pNode->m_tag == SMILSet)
- {
- if (pNode->m_tag == SMILRegion)
- {
- if (!(pAnim->m_ucAttributeName == kAttrNameSoundLevel ||
- pAnim->m_ucAttributeName == kAttrNameWidth ||
- pAnim->m_ucAttributeName == kAttrNameHeight ||
- pAnim->m_ucAttributeName == kAttrNameZIndex ||
- pAnim->m_ucAttributeName == kAttrNameLeft ||
- pAnim->m_ucAttributeName == kAttrNameRight ||
- pAnim->m_ucAttributeName == kAttrNameTop ||
- pAnim->m_ucAttributeName == kAttrNameBottom ||
- pAnim->m_ucAttributeName == kAttrNameBackgroundColor))
- {
- retVal = HXR_FAIL;
- }
- }
- else if (pNode->m_tag == SMILAnchor ||
- pNode->m_tag == SMILArea)
- {
- if (pAnim->m_ucAttributeName != kAttrNameCoords)
- {
- retVal = HXR_FAIL;
- }
- }
- else if (pNode->m_tag == SMILText ||
- pNode->m_tag == SMILImg ||
- pNode->m_tag == SMILAnimation ||
- pNode->m_tag == SMILRef ||
- pNode->m_tag == SMILAudio ||
- pNode->m_tag == SMILVideo ||
- pNode->m_tag == SMILTextstream)
- {
- if (!(pAnim->m_ucAttributeName == kAttrNameLeft ||
- pAnim->m_ucAttributeName == kAttrNameRight ||
- pAnim->m_ucAttributeName == kAttrNameTop ||
- pAnim->m_ucAttributeName == kAttrNameBottom ||
- pAnim->m_ucAttributeName == kAttrNameWidth ||
- pAnim->m_ucAttributeName == kAttrNameHeight ||
- pAnim->m_ucAttributeName == kAttrNameZIndex ||
- pAnim->m_ucAttributeName == kAttrNameBackgroundColor ||
- pAnim->m_ucAttributeName == kAttrNameMediaOpacity ||
- pAnim->m_ucAttributeName == kAttrNameBackgroundOpacity))
- {
- retVal = HXR_FAIL;
- }
- }
- else if (pNode->m_tag == SMILBrush)
- {
- if (!(pAnim->m_ucAttributeName == kAttrNameLeft ||
- pAnim->m_ucAttributeName == kAttrNameRight ||
- pAnim->m_ucAttributeName == kAttrNameTop ||
- pAnim->m_ucAttributeName == kAttrNameBottom ||
- pAnim->m_ucAttributeName == kAttrNameWidth ||
- pAnim->m_ucAttributeName == kAttrNameHeight ||
- pAnim->m_ucAttributeName == kAttrNameZIndex ||
- pAnim->m_ucAttributeName == kAttrNameColor ||
- pAnim->m_ucAttributeName == kAttrNameBackgroundColor))
- {
- retVal = HXR_FAIL;
- }
- }
- else if (pNode->m_tag == SMILRootLayout ||
- pNode->m_tag == SMILViewport)
- {
- if (!(pAnim->m_ucAttributeName == kAttrNameWidth ||
- pAnim->m_ucAttributeName == kAttrNameHeight))
- {
- retVal = HXR_FAIL;
- }
- }
- else if (pNode->m_tag == SMILParam)
- {
- if (pAnim->m_ucAttributeName != kAttrNameValue)
- {
- retVal = HXR_FAIL;
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- else if (pAnim->m_pNode->m_tag == SMILAnimateMotion)
- {
- if (pNode->m_tag == SMILRegion ||
- pNode->m_tag == SMILText ||
- pNode->m_tag == SMILImg ||
- pNode->m_tag == SMILAnimation ||
- pNode->m_tag == SMILRef ||
- pNode->m_tag == SMILAudio ||
- pNode->m_tag == SMILVideo ||
- pNode->m_tag == SMILTextstream ||
- pNode->m_tag == SMILBrush)
- {
- if (pAnim->m_ucAttributeName != kAttrNameLeftTop)
- {
- retVal = HXR_FAIL;
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- else if (pAnim->m_pNode->m_tag == SMILAnimateColor)
- {
- if (pNode->m_tag == SMILRegion ||
- pNode->m_tag == SMILText ||
- pNode->m_tag == SMILImg ||
- pNode->m_tag == SMILAnimation ||
- pNode->m_tag == SMILRef ||
- pNode->m_tag == SMILAudio ||
- pNode->m_tag == SMILVideo ||
- pNode->m_tag == SMILTextstream)
- {
- if (pAnim->m_ucAttributeName != kAttrNameBackgroundColor)
- {
- retVal = HXR_FAIL;
- }
- }
- else if (pNode->m_tag == SMILBrush)
- {
- if (pAnim->m_ucAttributeName != kAttrNameColor)
- {
- retVal = HXR_FAIL;
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- }
- if (FAILED(retVal))
- {
- // We either had an illegal target element or
- // an illegal attribute name.
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadAttribute,
- "attributeName",
- pAnim->m_pNode->m_ulTagStartLine);
- }
- }
- if (SUCCEEDED(retVal))
- {
- // Did we have a simple dur specified?
- if (pAnim->m_ulSimpleDuration != ((UINT32) -1))
- {
- // Yes the simple duration was specified.
- //
- // Compute active duration. First initialize
- // it to the simple duration
- pAnim->m_ulActiveDuration = pAnim->m_ulSimpleDuration;
- // Did we have repeatDur="indefinite"?
- if (pAnim->m_bRepeatDurIsIndefinite)
- {
- // Yes, we have repeatDur="indefinite"
- //
- // Do we have any repeatCount?
- if (pAnim->m_dRepeatCount != 1.0)
- {
- // Yes, we have a repeatCount specified.
- //
- // Do we have autoReverse?
- double dRC = 0.0;
- if (pAnim->m_bAutoReverse)
- {
- dRC = (double) pAnim->m_dRepeatCount * pAnim->m_ulSimpleDuration * 2;
- }
- else
- {
- dRC = (double) pAnim->m_dRepeatCount * pAnim->m_ulSimpleDuration;
- }
- // This repeatCount-driven active duration will
- // take precedence over the repeatDur="indefinite"
- pAnim->m_ulActiveDuration = (UINT32) floor(dRC + 0.5);
- pAnim->m_bIndefiniteActiveDuration = FALSE;
- // m_ulADNoSpeed is the active duration without taking
- // the speed attribute into account, so we simply initialize
- // it before we make the speed modification
- pAnim->m_ulADNoSpeed = pAnim->m_ulActiveDuration;
- // Now if speed is not 1.0, then we have to adjust
- // the active duration by the absolute value of the speed
- // Speed globally scales the active duration
- if (pAnim->m_dSpeed != 1.0 &&
- pAnim->m_dSpeed != 0.0)
- {
- double dSpeedAbs = fabs(pAnim->m_dSpeed);
- double dNewAD = (double) pAnim->m_ulActiveDuration / dSpeedAbs;
- pAnim->m_ulActiveDuration = (UINT32) floor(dNewAD + 0.5);
- }
- }
- else
- {
- // We don't have a repeatCount, so the active duration
- // is indefinite
- pAnim->m_bIndefiniteActiveDuration = TRUE;
- }
- }
- else
- {
- // Do we repeat at all?
- if (pAnim->m_dRepeatCount != 1.0 ||
- pAnim->m_ulRepeatDur != ((UINT32) -1))
- {
- // Yes we repeat. Compute how long we would
- // repeat from repeatCount
- UINT32 ulADRepeatCount = 0xFFFFFFFF;
- if (pAnim->m_dRepeatCount != 1.0)
- {
- // Do we have autoReverse?
- double dRC = 0.0;
- if (pAnim->m_bAutoReverse)
- {
- dRC = (double) pAnim->m_dRepeatCount * pAnim->m_ulSimpleDuration * 2;
- }
- else
- {
- dRC = (double) pAnim->m_dRepeatCount * pAnim->m_ulSimpleDuration;
- }
- ulADRepeatCount = (UINT32) floor(dRC + 0.5);
- }
- // Get how long we would repeat from repeatDur
- UINT32 ulADRepeatDur = 0xFFFFFFFF;
- if (pAnim->m_ulRepeatDur != ((UINT32) -1))
- {
- ulADRepeatDur = pAnim->m_ulRepeatDur;
- }
- // Now compute the active duration - it will be the minimum
- // of the simple duration, active duration from repeatCount,
- // and active duration from repeatDur.
- pAnim->m_ulActiveDuration = 0xFFFFFFFF;
- if (ulADRepeatCount < pAnim->m_ulActiveDuration)
- {
- pAnim->m_ulActiveDuration = ulADRepeatCount;
- }
- if (ulADRepeatDur < pAnim->m_ulActiveDuration)
- {
- pAnim->m_ulActiveDuration = ulADRepeatDur;
- }
- // If active duration is still 0xFFFFFFFF (shouldn't happen), then
- // the active duration is just the same as the
- // simple duration
- if (pAnim->m_ulActiveDuration == 0xFFFFFFFF)
- {
- pAnim->m_ulActiveDuration = pAnim->m_ulSimpleDuration;
- }
- }
- else
- {
- // Do we have autoReverse?
- if (pAnim->m_bAutoReverse)
- {
- pAnim->m_ulActiveDuration = pAnim->m_ulSimpleDuration * 2;
- }
- }
- // m_ulADNoSpeed is the active duration without taking
- // the speed attribute into account, so we simply initialize
- // it before we make the speed modification
- pAnim->m_ulADNoSpeed = pAnim->m_ulActiveDuration;
- // Now if speed is not 1.0, then we have to adjust
- // the active duration by the absolute value of the speed
- // Speed globally scales the active duration
- if (pAnim->m_dSpeed != 1.0 &&
- pAnim->m_dSpeed != 0.0)
- {
- double dSpeedAbs = fabs(pAnim->m_dSpeed);
- double dNewAD = (double) pAnim->m_ulActiveDuration / dSpeedAbs;
- pAnim->m_ulActiveDuration = (UINT32) floor(dNewAD + 0.5);
- }
- }
- }
- else
- {
- // No simple duration was specified. Therefore, we have
- // an indefinite simple duration.
- pAnim->m_bIndefiniteSimpleDuration = TRUE;
- // Do we have a non-indefinite repeatDur specified?
- if (pAnim->m_ulRepeatDur != ((UINT32) -1))
- {
- // Yes, repeatDur was specified and it was NOT
- // "indefinite". Therefore, our active duration
- // is NOT indefinite.
- pAnim->m_bIndefiniteActiveDuration = FALSE;
- // Our active duration is the repeatDur
- pAnim->m_ulActiveDuration = pAnim->m_ulRepeatDur;
- }
- else
- {
- // Either repeatDur wasn't specified or it was
- // specified and it was "indefinite". Either way,
- // our active duration is going to be indefinite.
- pAnim->m_bIndefiniteActiveDuration = TRUE;
- }
- }
- }
- if (SUCCEEDED(retVal))
- {
- // First let's determine what kind of animation it is
- if (bValuesSpecified)
- {
- // SPEC: If values is specified, from/by/to are ignored
- pAnim->m_ucAnimationType = kAnimTypeValues;
- }
- else
- {
- // No values specified, so let's look at the from/by/to
- //
- // SPEC: "The simpler from/to/by syntax provides for several
- // variants. To use one of these variants, one of by or to must
- // be specified; a from value is optional. It is not legal to
- // specify both by and to attributes; if both are specified, only
- // the to attribute will be used (the by will be ignored)."
- if (bToSpecified)
- {
- if (bFromSpecified)
- {
- // This is a "from-to" animation
- pAnim->m_ucAnimationType = kAnimTypeFromTo;
- }
- else
- {
- // This is a "to" animation
- pAnim->m_ucAnimationType = kAnimTypeTo;
- // Handle special cases for "to" animations -
- // cumulative animations are not defined, so we always
- // for accumulate="none"
- pAnim->m_ucAccumulate = kAccumulateNone;
- }
- }
- else if (bBySpecified)
- {
- if (bFromSpecified)
- {
- // This is a "from-by" animation
- pAnim->m_ucAnimationType = kAnimTypeFromBy;
- }
- else
- {
- // This is a "by" animation
- pAnim->m_ucAnimationType = kAnimTypeBy;
- // SPEC: "A by animation with a by value vb is equivalent
- // to the same animation with a values list with 2 values,
- // 0 and vb, and additive="sum". Any other specification of
- // the additive attribute in a by animation is ignored."
- //
- // So if the additive value is not sum, set it to sum
- if (pAnim->m_ucAdditive != kAdditiveSum)
- {
- pAnim->m_ucAdditive = kAdditiveSum;
- }
- }
- }
- else
- {
- // XXXMEH - no "values", "to", or "by" specified - the
- // animation should do nothing. For now, we fail. We won't
- // throw an error, but we will just not do this
- // animation. I'm just commenting out the error popup,
- // cause I think we should still have it.
- retVal = HXR_FAIL;
- // CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- // errHandler.ReportError(SMILErrorRequiredAttributeMissing,
- // "values",
- // pAnim->m_pNode->m_ulTagStartLine);
- }
- }
- if (SUCCEEDED(retVal))
- {
- // Now we can parse the values of the values/from/to/by attributes
- if (pAnim->m_ucAnimationType == kAnimTypeValues)
- {
- // Get the "values" attribute
- IHXBuffer* pVal = NULL;
- retVal = pAnim->m_pNode->m_pValues->GetPropertyCString("values", pVal);
- if (SUCCEEDED(retVal))
- {
- const char* pszVal = (const char*) pVal->GetBuffer();
- // First count and separate the different values arguments
- char* pStr = NULL;
- char** ppStr = NULL;
- retVal = animCountValues(pszVal, pStr, pAnim->m_ulNumValues, ppStr);
- if (SUCCEEDED(retVal))
- {
- // Allocate the array of CAttr*
- pAnim->m_ppValue = new CAttr* [pAnim->m_ulNumValues];
- if (pAnim->m_ppValue)
- {
- // Zero out the memory
- memset((void*) pAnim->m_ppValue, 0,
- sizeof(CAttr*) * pAnim->m_ulNumValues);
- // Loop through and parse each argument
- for (UINT32 i = 0; i < pAnim->m_ulNumValues && SUCCEEDED(retVal); i++)
- {
- retVal = animParseValue(pAnim, ppStr[i], i);
- }
- }
- else
- {
- pAnim->m_ulNumValues = 0;
- retVal = HXR_OUTOFMEMORY;
- }
- }
- // Free the temporary strings
- HX_VECTOR_DELETE(ppStr);
- HX_VECTOR_DELETE(pStr);
- }
- HX_RELEASE(pVal);
- }
- else
- {
- // If we are not a values type, then there will
- // always be two CAttr*
- pAnim->m_ulNumValues = 2;
- // Allocate the array of CAttr*
- pAnim->m_ppValue = new CAttr* [pAnim->m_ulNumValues];
- if (pAnim->m_ppValue)
- {
- // Zero out the memory
- memset((void*) pAnim->m_ppValue, 0,
- sizeof(CAttr*) * pAnim->m_ulNumValues);
- // Parse the from attribute
- if (pAnim->m_ucAnimationType == kAnimTypeFromTo ||
- pAnim->m_ucAnimationType == kAnimTypeFromBy)
- {
- IHXBuffer* pVal = NULL;
- retVal = pAnim->m_pNode->m_pValues->GetPropertyCString("from", pVal);
- if (SUCCEEDED(retVal))
- {
- const char* pszVal = (const char*) pVal->GetBuffer();
- retVal = animParseValue(pAnim, pszVal, 0);
- }
- HX_RELEASE(pVal);
- }
- // Parse the to attribute
- if (SUCCEEDED(retVal) &&
- (pAnim->m_ucAnimationType == kAnimTypeFromTo ||
- pAnim->m_ucAnimationType == kAnimTypeTo))
- {
- IHXBuffer* pVal = NULL;
- retVal = pAnim->m_pNode->m_pValues->GetPropertyCString("to", pVal);
- if (SUCCEEDED(retVal))
- {
- const char* pszVal = (const char*) pVal->GetBuffer();
- retVal = animParseValue(pAnim, pszVal, 1);
- }
- HX_RELEASE(pVal);
- }
- // Parse the by attribute
- if (SUCCEEDED(retVal) &&
- (pAnim->m_ucAnimationType == kAnimTypeFromBy ||
- pAnim->m_ucAnimationType == kAnimTypeBy))
- {
- IHXBuffer* pVal = NULL;
- retVal = pAnim->m_pNode->m_pValues->GetPropertyCString("by", pVal);
- if (SUCCEEDED(retVal))
- {
- const char* pszVal = (const char*) pVal->GetBuffer();
- retVal = animParseValue(pAnim, pszVal, 1);
- }
- HX_RELEASE(pVal);
- }
- // If this is either a "to" or "by" animation,
- // then we need to fill in m_ppValue[0] with a
- // zero-valued placeholder
- if (pAnim->m_ucAnimationType == kAnimTypeTo ||
- pAnim->m_ucAnimationType == kAnimTypeBy)
- {
- pAnim->m_ppValue[0] = new CAttr(pAnim->m_ucAttributeName);
- if (!pAnim->m_ppValue[0])
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- }
- else
- {
- pAnim->m_ulNumValues = 0;
- retVal = HXR_OUTOFMEMORY;
- }
- }
- }
- // Check if we are animating width
- // or height of a root-layout or topLayout
- if (SUCCEEDED(retVal) &&
- (pAnim->m_eTargetElementTag == SMILRootLayout ||
- pAnim->m_eTargetElementTag == SMILViewport))
- {
- // Make sure that none of the attributes
- // are percentages. It's illegal for a <root-layout>
- // or topLayout to have a percentage value
- // at any time.
- for (UINT32 i = 0; i < pAnim->m_ulNumValues; i++)
- {
- if (pAnim->m_ppValue[i] &&
- pAnim->m_ppValue[i]->GetCSS2Type(0) == CSS2TypePercentage)
- {
- retVal = HXR_FAIL;
- break;
- }
- }
- }
- #if defined(XXXMEH_SPLINE_ANIMATION)
- // Check any SplineAnimation parameters, if there are any
- if (SUCCEEDED(retVal))
- {
- retVal = checkSplineAnimation(pAnim);
- }
- #endif
- }
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- return retVal;
- }
- #if defined(XXXMEH_SPLINE_ANIMATION)
- HX_RESULT CSmilParser::checkSplineAnimation(CSmilAnimateElement* pAnim)
- {
- HX_RESULT retVal = HXR_OK;
- if (pAnim)
- {
- // Do we have a "path" attribute?
- if (pAnim->m_ppPathCmd && pAnim->m_ulNumPathCmds)
- {
- // First, convert all implicit path
- // commands to explicit path commands
- retVal = makeSVGPathExplicit(pAnim);
- }
- if (SUCCEEDED(retVal))
- {
- // Do we have any keyTimes?
- if (pAnim->m_ulNumKeyTimes && pAnim->m_pdKeyTime)
- {
- // Do we have from/to/values attribute or a path specification?
- if (pAnim->m_ulNumValues && pAnim->m_ppValue)
- {
- // SPEC: If a list of keyTimes is specified, there
- // must be exactly as many values in the keyTimes
- // list as in the values list.
- if (pAnim->m_ulNumValues != pAnim->m_ulNumKeyTimes)
- {
- retVal = HXR_FAIL;
- }
- }
- else if (pAnim->m_ppPathCmd && pAnim->m_ulNumPathCmds)
- {
- }
- }
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- return retVal;
- }
- HX_RESULT CSmilParser::makeSVGPathExplicit(CSmilAnimateElement* pAnim)
- {
- HX_RESULT retVal = HXR_OK;
- if (pAnim)
- {
- if (pAnim->m_ppPathCmd && pAnim->m_ulNumPathCmds)
- {
- // Run through and count how many we would
- // have in the completely explicit array
- UINT32 i = 0;
- UINT32 ulNumExplicit = 0;
- for (i = 0; i < pAnim->m_ulNumPathCmds; i++)
- {
- if (pAnim->m_ppPathCmd[i])
- {
- PathCmdType eType = pAnim->m_ppPathCmd[i]->m_eType;
- UINT32 ulNumCoords = pAnim->m_ppPathCmd[i]->m_ulNumCoords;
- switch (eType)
- {
- case PathCmdTypeMoveTo:
- case PathCmdTypeLineTo:
- {
- ulNumExplicit += ulNumCoords / 2;
- }
- break;
- case PathCmdTypeHorzLineTo:
- case PathCmdTypeVertLineTo:
- {
- ulNumExplicit += ulNumCoords;
- }
- break;
- case PathCmdTypeClosePath:
- {
- ++ulNumExplicit;
- }
- break;
- case PathCmdTypeCubicBezierCurveTo:
- {
- ulNumExplicit += ulNumCoords / 6;
- }
- break;
- }
- }
- }
- // Is the completely explicit number the same
- // as the current number? If so, we don't have
- // any work to do
- if (ulNumExplicit != pAnim->m_ulNumPathCmds)
- {
- // Allocate an array of PathCmd*'s
- PathCmd** ppPathCmd = new PathCmd* [ulNumExplicit];
- if (ppPathCmd)
- {
- // NULL out the array
- memset(ppPathCmd, 0, ulNumExplicit & sizeof(PathCmd*));
- // Now run through the existing array. If the PathCmd
- // has no implicit commands in it, then we just copy
- // the pointer. If the PathCmd has implicit commands,
- // then we need to create some number of PathCmd
- // objects and then fill them in
- //
- // Initialize the explicit array index
- UINT32 ulExplicitIndex = 0;
- for (i = 0; i < pAnim->m_ulNumPathCmds; i++)
- {
- if (pAnim->m_ppPathCmd[i])
- {
- PathCmdType eType = pAnim->m_ppPathCmd[i]->m_eType;
- UINT32 ulNumCoords = pAnim->m_ppPathCmd[i]->m_ulNumCoords;
- UINT32 ulNumCmds = 0;
- switch (eType)
- {
- case PathCmdTypeMoveTo:
- {
- ulNumCmds = ulNumCoords / 2;
- if (ulNumCmds == 1)
- {
- // Just copy over the pointer
- ppPathCmd[ulExplicitIndex++] = pAnim->m_ppPathCmd[i];
- }
- else
- {
- for (UINT32 j = 0; j < ulNumCmds && SUCCEEDED(retVal); j++)
- {
- // Create a PathCmd
- PathCmd* pNew = new PathCmd();
- if (pNew)
- {
- // Copy the type and relative members.
- // The first one should be a MoveTo and
- // the rest should be LineTo's.
- pNew->m_eType = (j ? PathCmdTypeLineTo : PathCmdTypeMoveTo);
- pNew->m_bRelative = pAnim->m_ppPathCmd[i]->m_bRelative;
- // Allocate 2 doubles
- pNew->m_ulNumCoords = 2;
- pNew->m_pdCoord = new double [2];
- if (pNew->m_pdCoord)
- {
- // Get the j*2-th and j*2+1-th
- // coordinates from the original
- UINT32 k = j * 2;
- pNew->m_pdCoord[0] = pAnim->m_ppPathCmd[i]->m_pdCoord[k];
- pNew->m_pdCoord[1] = pAnim->m_ppPathCmd[i]->m_pdCoord[k+1];
- // Add this to the new array
- ppPathCmd[ulExplicitIndex++] = pNew;
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- // Now we can delete the old PathCmd
- HX_DELETE(pAnim->m_ppPathCmd[i]);
- }
- }
- break;
- case PathCmdTypeLineTo:
- {
- ulNumCmds = ulNumCoords / 2;
- if (ulNumCmds == 1)
- {
- // Just copy over the pointer
- ppPathCmd[ulExplicitIndex++] = pAnim->m_ppPathCmd[i];
- }
- else
- {
- for (UINT32 j = 0; j < ulNumCmds && SUCCEEDED(retVal); j++)
- {
- // Create a PathCmd
- PathCmd* pNew = new PathCmd();
- if (pNew)
- {
- // Copy the type and relative members
- // from the original PathCmd
- pNew->m_eType = pAnim->m_ppPathCmd[i]->m_eType;
- pNew->m_bRelative = pAnim->m_ppPathCmd[i]->m_bRelative;
- // Allocate 2 doubles
- pNew->m_ulNumCoords = 2;
- pNew->m_pdCoord = new double [2];
- if (pNew->m_pdCoord)
- {
- // Get the j*2-th and j*2+1-th
- // coordinates from the original
- UINT32 k = j * 2;
- pNew->m_pdCoord[0] = pAnim->m_ppPathCmd[i]->m_pdCoord[k];
- pNew->m_pdCoord[1] = pAnim->m_ppPathCmd[i]->m_pdCoord[k+1];
- // Add this to the new array
- ppPathCmd[ulExplicitIndex++] = pNew;
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- // Now we can delete the old PathCmd
- HX_DELETE(pAnim->m_ppPathCmd[i]);
- }
- }
- break;
- case PathCmdTypeHorzLineTo:
- case PathCmdTypeVertLineTo:
- {
- ulNumCmds = ulNumCoords;
- if (ulNumCmds == 1)
- {
- // Just copy over the pointer
- ppPathCmd[ulExplicitIndex++] = pAnim->m_ppPathCmd[i];
- }
- else
- {
- for (UINT32 j = 0; j < ulNumCmds && SUCCEEDED(retVal); j++)
- {
- // Create a PathCmd
- PathCmd* pNew = new PathCmd();
- if (pNew)
- {
- // Copy the type and relative members
- // from the original PathCmd
- pNew->m_eType = pAnim->m_ppPathCmd[i]->m_eType;
- pNew->m_bRelative = pAnim->m_ppPathCmd[i]->m_bRelative;
- // Allocate 2 doubles
- pNew->m_ulNumCoords = 1;
- pNew->m_pdCoord = new double [1];
- if (pNew->m_pdCoord)
- {
- // Get the j-th coordinates
- // from the original
- pNew->m_pdCoord[0] = pAnim->m_ppPathCmd[i]->m_pdCoord[j];
- // Add this to the new array
- ppPathCmd[ulExplicitIndex++] = pNew;
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- // Now we can delete the old PathCmd
- HX_DELETE(pAnim->m_ppPathCmd[i]);
- }
- }
- break;
- case PathCmdTypeClosePath:
- {
- // Just copy over the pointer
- ppPathCmd[ulExplicitIndex++] = pAnim->m_ppPathCmd[i];
- }
- break;
- case PathCmdTypeCubicBezierCurveTo:
- {
- ulNumCmds = ulNumCoords / 6;
- if (ulNumCmds == 1)
- {
- // Just copy over the pointer
- ppPathCmd[ulExplicitIndex++] = pAnim->m_ppPathCmd[i];
- }
- else
- {
- for (UINT32 j = 0; j < ulNumCmds && SUCCEEDED(retVal); j++)
- {
- // Create a PathCmd
- PathCmd* pNew = new PathCmd();
- if (pNew)
- {
- // Copy the type and relative members
- // from the original PathCmd
- pNew->m_eType = pAnim->m_ppPathCmd[i]->m_eType;
- pNew->m_bRelative = pAnim->m_ppPathCmd[i]->m_bRelative;
- // Allocate 2 doubles
- pNew->m_ulNumCoords = 6;
- pNew->m_pdCoord = new double [6];
- if (pNew->m_pdCoord)
- {
- // Get the coordinates from the original
- UINT32 k = j * 6;
- for (UINT32 q = 0; q < 6; q++)
- {
- pNew->m_pdCoord[q] = pAnim->m_ppPathCmd[i]->m_pdCoord[k+q];
- }
- // Add this to the new array
- ppPathCmd[ulExplicitIndex++] = pNew;
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- // Now we can delete the old PathCmd
- HX_DELETE(pAnim->m_ppPathCmd[i]);
- }
- }
- break;
- }
- }
- }
- // Now we can replace the old PathCmd array
- // with the new one
- HX_VECTOR_DELETE(pAnim->m_ppPathCmd);
- pAnim->m_ppPathCmd = ppPathCmd;
- pAnim->m_ulNumPathCmds = ulNumExplicit;
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- return retVal;
- }
- #endif // #if defined(XXXMEH_SPLINE_ANIMATION)
- HX_RESULT CSmilParser::animCountValues(const char* pszStr,
- REF(char*) rpStr,
- REF(UINT32) rulNumValues,
- REF(char**) rppStr)
- {
- HX_RESULT retVal = HXR_OK;
- // Set defaults
- rpStr = NULL;
- rulNumValues = 0;
- rppStr = NULL;
- // Allocate the string
- char* pStr = new char [strlen(pszStr) + 1];
- if (pStr)
- {
- // Copy the string
- strcpy(pStr, pszStr); /* Flawfinder: ignore */
- // Init the count
- UINT32 ulNumValues = 0;
- // Count the values
- char* pszToken = strtok(pStr, ";");
- while (pszToken)
- {
- ulNumValues++;
- pszToken = strtok(NULL, ";");
- }
- // Got to have at least one
- if (ulNumValues)
- {
- // Allocate an array of strings
- char** ppStr = new char* [ulNumValues];
- if (ppStr)
- {
- // Zero out the memory
- memset((void*) ppStr, 0, ulNumValues * sizeof(char*));
- // Recopy the string
- strcpy(pStr, pszStr); /* Flawfinder: ignore */
- // Run through again and find the points
- char* pszToken = strtok(pStr, ";");
- UINT32 i = 0;
- while (pszToken)
- {
- ppStr[i++] = pszToken;
- pszToken = strtok(NULL, ";");
- }
- // Assign the out parameters
- rpStr = pStr;
- rulNumValues = ulNumValues;
- rppStr = ppStr;
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- if (FAILED(retVal))
- {
- HX_VECTOR_DELETE(ppStr);
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- if (FAILED(retVal))
- {
- HX_VECTOR_DELETE(pStr);
- }
- return retVal;
- }
- HX_RESULT CSmilParser::animParseValue(CSmilAnimateElement* pAnim,
- const char* pszVal,
- UINT32 i)
- {
- HX_RESULT retVal = HXR_OK;
- if (pAnim && pszVal && i < pAnim->m_ulNumValues)
- {
- // Allocate a new CAttr
- CAttr* pAttr = new CAttr(pAnim->m_ucAttributeName, pszVal);
- if (pAttr)
- {
- retVal = pAttr->GetLastError();
- if (SUCCEEDED(retVal))
- {
- HX_DELETE(pAnim->m_ppValue[i]);
- pAnim->m_ppValue[i] = pAttr;
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- if (FAILED(retVal))
- {
- HX_DELETE(pAttr);
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- return retVal;
- }
- #endif /* #if defined(HELIX_FEATURE_SMIL2_ANIMATION) */
- CSmilParamElement* CSmilParser::makeParamElement(SMILNode* pNode)
- {
- CSmilParamElement* pRet = NULL;
- HX_RESULT retVal = HXR_OK;
- if (pNode)
- {
- pRet = new CSmilParamElement(pNode);
- if (pRet)
- {
- if (pNode->m_pValues)
- {
- const char* pszName = NULL;
- IHXBuffer* pValue = NULL;
- HX_RESULT rv = pNode->m_pValues->GetFirstPropertyCString(pszName, pValue);
- while (SUCCEEDED(rv) && SUCCEEDED(retVal))
- {
- // Get the string version of the value
- const char* pszValue = (const char*) pValue->GetBuffer();
- // Get the SMIL2Attribute
- SMIL2Attribute eAttr = getSMIL2Attribute(pszName);
- // Switch on attribute name
- switch (eAttr)
- {
- case SMIL2AttrName:
- {
- HX_RELEASE(pRet->m_pName);
- pRet->m_pName = pValue;
- pRet->m_pName->AddRef();
- }
- break;
- case SMIL2AttrValue:
- {
- HX_RELEASE(pRet->m_pValue);
- pRet->m_pValue = pValue;
- pRet->m_pValue->AddRef();
- }
- break;
- default:
- {
- // Find out if this attribute is namespace-prefixed. Since
- // we assume that this document has already been validated,
- // then we don't have to throw an error if it's not - it's
- // probably just an attribute we are not parsing above.
- const char* pszAttr = NULL;
- CNamespaceInfo* pNSInfo = getNamespaceInfo(pszName, pszAttr);
- if (pNSInfo)
- {
- // This attribute IS namespace-prefixed.
- //
- // If this is the Param namespace, then
- // we should parse it for "delivery"
- if (pNSInfo->m_eNamespace == NamespaceParam ||
- pNSInfo->m_eNamespace == NamespaceAllSMIL2Extensions)
- {
- if(!strcmp(pszAttr, "delivery"))
- {
- if (!strcmp(pszValue, "server"))
- {
- pRet->m_eDelivery = DeliveryServer;
- }
- else if (!strcmp(pszValue, "client"))
- {
- pRet->m_eDelivery = DeliveryClient;
- }
- else
- {
- retVal = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadAttribute,
- pszName,
- pRet->m_pNode->m_ulTagStartLine);
- }
- }
- }
- }
- }
- }
- // Get the next attribute
- HX_RELEASE(pValue);
- rv = pNode->m_pValues->GetNextPropertyCString(pszName, pValue);
- }
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- if (FAILED(retVal))
- {
- HX_DELETE(pRet);
- }
- return pRet;
- }
- CSmilBodyElement* CSmilParser::makeBodyElement(SMILNode* pNode)
- {
- CSmilBodyElement* pRet = NULL;
- HX_RESULT retVal = HXR_OK;
- if (pNode)
- {
- pRet = new CSmilBodyElement(pNode);
- if (pRet)
- {
- if (pNode->m_pValues)
- {
- const char* pszName = NULL;
- IHXBuffer* pValue = NULL;
- HX_RESULT rv = pNode->m_pValues->GetFirstPropertyCString(pszName, pValue);
- while (SUCCEEDED(rv) && SUCCEEDED(retVal))
- {
- // Get the string version of the value
- const char* pszValue = (const char*) pValue->GetBuffer();
- // Get the SMIL2Attribute
- SMIL2Attribute eAttr = getSMIL2Attribute(pszName);
- // Switch on attribute name
- switch (eAttr)
- {
- // We currently don't care about other
- // attributes on <body>
- default:
- {
- // Find out if this attribute is namespace-prefixed. Since
- // we assume that this document has already been validated,
- // then we don't have to throw an error if it's not - it's
- // probably just an attribute we are not parsing above.
- const char* pszAttr = NULL;
- CNamespaceInfo* pNSInfo = getNamespaceInfo(pszName, pszAttr);
- if (pNSInfo)
- {
- // This attribute IS namespace-prefixed.
- if (pNSInfo->m_eNamespace == NamespaceAccessErrorBehavior ||
- pNSInfo->m_eNamespace == NamespaceAllSMIL2Extensions)
- {
- if(!strcmp(pszAttr, "accessErrorBehavior"))
- {
- retVal = parseAccessErrorBehavior(pszValue, pRet->m_eAccessErrorBehavior);
- if (FAILED(retVal))
- {
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadAttribute,
- pszName,
- pRet->m_pNode->m_ulTagStartLine);
- }
- }
- }
- }
- }
- }
- // Get the next attribute
- HX_RELEASE(pValue);
- rv = pNode->m_pValues->GetNextPropertyCString(pszName, pValue);
- }
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- if (FAILED(retVal))
- {
- HX_DELETE(pRet);
- }
- return pRet;
- }
- HX_RESULT
- CSmilParser::insertElementByTimestamp(CSmilElement* pPacket)
- {
- LISTPOSITION lPos = m_pPacketQueue->GetHeadPosition();
- LISTPOSITION lPrev = lPos;
- while(lPos)
- {
- CSmilElement* pPkt = (CSmilElement*)m_pPacketQueue->GetNext(lPos);
- if(pPkt->m_ulTimestamp > pPacket->m_ulTimestamp)
- {
- m_pPacketQueue->InsertBefore(lPrev, pPacket);
- return HXR_OK;
- }
- lPrev = lPos;
- }
- m_pPacketQueue->AddTail(pPacket);
- return HXR_OK;
- }
- HX_RESULT
- CSmilParser::mapID(SMILNode* pNode, BOOL bOverWrite)
- {
- HX_RESULT rc = HXR_OK;
- void* pTmp = 0;
- if(!bOverWrite && m_pIDMap->Lookup((const char*)pNode->m_id, (void*&)pTmp))
- {
- rc = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorDuplicateID, pNode->m_id,
- pNode->m_ulTagStartLine);
- }
- else
- {
- (*m_pIDMap)[(const char*)pNode->m_id] = pNode;
- }
- return rc;
- }
- //This function is needed to fix PR 13319. If you have a repeat of greater
- // than 1 in a <seq>, we need a way to map the IDs of the children created
- // when the additional <seq>(s) are created
- HX_RESULT
- CSmilParser::mapChildrenIDs(SMILNodeList* pNodeList, BOOL bOverWrite)
- {
- HX_RESULT rc = HXR_OK;
- if (!pNodeList)
- {
- return rc;
- }
- CHXSimpleList::Iterator i;
- for(i=pNodeList->Begin();rc == HXR_OK && i!=pNodeList->End();++i)
- {
- SMILNode* pNode = (SMILNode*)(*i);
- rc = mapID(pNode, bOverWrite);
- HX_ASSERT(rc == HXR_OK);
- if(pNode->m_pNodeList)
- {
- rc = mapChildrenIDs(pNode->m_pNodeList, bOverWrite);
- }
- }
- return rc;
- }
- HX_RESULT
- CSmilParser::markRepeatReplica(SMILNodeList* pNodeList, RepeatTag repeatTag)
- {
- HX_RESULT rc = HXR_OK;
- if(!pNodeList)
- {
- return rc;
- }
- CHXSimpleList::Iterator i;
- for(i=pNodeList->Begin();rc == HXR_OK && i!=pNodeList->End();++i)
- {
- SMILNode* pNode = (SMILNode*)(*i);
- pNode->m_repeatTag = repeatTag;
- if(pNode->m_pNodeList)
- {
- rc = markRepeatReplica(pNode->m_pNodeList, repeatTag);
- }
- }
- return rc;
- }
- #if defined(HELIX_FEATURE_SMIL2_VALIDATION)
- HX_RESULT CSmilParser::validateContentModel(UINT32 ulElement, SMILNodeList* pChildren)
- {
- HX_RESULT retVal = HXR_OK;
- if (pChildren)
- {
- if (ulElement < NumSMIL2Elements)
- {
- // First just do a check to make sure that
- // there are no illegal elements.
- UINT32 ulNumLegalChildren = 0;
- UINT32 ulNumPCChildren = 0;
- UINT32 ulNumLayoutChildren = 0;
- UINT32 ulHeadIndex = 0;
- UINT32 ulBodyIndex = 0;
- LISTPOSITION pos = pChildren->GetHeadPosition();
- while (pos && SUCCEEDED(retVal))
- {
- SMILNode* pChild = (SMILNode*) pChildren->GetNext(pos);
- if (pChild &&
- !pChild->m_bCloseNode &&
- !pChild->m_bNamespacedElement)
- {
- if (!m_pContentModelMap->IsSet(ulElement, pChild->m_eElement))
- {
- retVal = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorUnexpectedTag,
- pChild->m_name,
- pChild->m_ulTagStartLine);
- }
- else
- {
- if (ulElement == SMIL2ElemExcl &&
- pChild->m_eElement == SMIL2ElemPriorityClass)
- {
- ulNumPCChildren++;
- }
- else if (ulElement == SMIL2ElemSwitch &&
- pChild->m_eElement == SMIL2ElemLayout)
- {
- ulNumLayoutChildren++;
- }
- else if (ulElement == SMIL2ElemSmil)
- {
- if (pChild->m_eElement == SMIL2ElemHead)
- {
- ulHeadIndex = ulNumLegalChildren;
- }
- else if (pChild->m_eElement == SMIL2ElemBody)
- {
- ulBodyIndex = ulNumLegalChildren;
- }
- }
- ulNumLegalChildren++;
- }
- }
- }
- // Now if we succeeded, then there are a few elements with
- // very specific content models.
- if (SUCCEEDED(retVal))
- {
- switch (ulElement)
- {
- case SMIL2ElemCustomAttributes:
- {
- // Must be at least 1 customTest element
- if (!ulNumLegalChildren)
- {
- retVal = HXR_FAIL;
- }
- }
- break;
- case SMIL2ElemExcl:
- {
- // If there are ANY priority class children, then they
- // have to be the ONLY children.
- if (ulNumPCChildren > 0 &&
- ulNumPCChildren < ulNumLegalChildren)
- {
- retVal = HXR_FAIL;
- }
- }
- break;
- case SMIL2ElemHead:
- {
- // XXXMEH - TODO: figure out what
- // is meant by the content model of <head>.
- }
- break;
- case SMIL2ElemSmil:
- {
- // Content model is (head?, body?), so if there's
- // only 1 legal child, then we know we're correct.
- // If there's two, then we have to make sure the
- // first is a <head> and the second is a <body>
- if (ulNumLegalChildren == 2 &&
- ulBodyIndex <= ulHeadIndex)
- {
- retVal = HXR_FAIL;
- }
- }
- break;
- case SMIL2ElemSwitch:
- {
- // If there are ANY layout children, then they
- // have to be the ONLY children.
- if (ulNumLayoutChildren > 0 &&
- ulNumLayoutChildren < ulNumLegalChildren)
- {
- retVal = HXR_FAIL;
- }
- }
- break;
- }
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- return retVal;
- }
- HX_RESULT CSmilParser::validateNode(SMILNode* pNode)
- {
- HX_RESULT retVal = HXR_OK;
- if (pNode &&
- !pNode->m_bCloseNode && // don't care about closing nodes
- !pNode->m_bNamespacedElement) // won't validate namespaced elements
- {
- // Initialize the IHXValues which will hold
- // any attributes which are different from
- // their normalized form
- IHXValues* pNormAttributes = NULL;
- // Initialize error info
- SMILErrorTag eError = SMILErrorNone;
- BOOL bChildFailed = FALSE;
- CHXString cErrStr;
- // Check that all the attributes are legal attributes
- if (pNode->m_pValues)
- {
- const char* pszName = NULL;
- IHXBuffer* pValue = NULL;
- HX_RESULT rv = pNode->m_pValues->GetFirstPropertyCString(pszName, pValue);
- while (SUCCEEDED(rv) && SUCCEEDED(retVal))
- {
- // Is the attribute name valid?
- BOOL bNSAttr = FALSE;
- BOOL bUnknownNS = FALSE;
- SupportedNamespace eNS = NamespaceNotImplemented;
- UINT32 ulAttribute = 0;
- void* pVoid = NULL;
- if (m_pAttributeMap->Lookup(pszName, pVoid))
- {
- // Get the attribute index
- ulAttribute = (UINT32) pVoid;
- }
- else
- {
- // We didn't find the attribute in the SMIL 2 namespace,
- // so let's see if the attribute has a valid namespace prefix
- const char* pszAttr = NULL;
- CNamespaceInfo* pNSInfo = getNamespaceInfo(pszName, pszAttr);
- if (pNSInfo)
- {
- // Set the flag saying this is a namespaced attribute
- bNSAttr = TRUE;
- // Yes, this attribute has a valid namespace prefix
- // But is this a namespace we support?
- if (pNSInfo->m_eNamespace != NamespaceNotImplemented)
- {
- // Set the namespace to use for later
- eNS = pNSInfo->m_eNamespace;
- // Look up the attribute in our
- // extension namespace map
- if (m_pExtAttributeMap->Lookup(pszAttr, pVoid))
- {
- // Get the attribute index
- ulAttribute = (UINT32) pVoid;
- }
- else
- {
- // We don't have this attribute in our
- // namespace map
- retVal = HXR_FAIL;
- eError = SMILErrorUnrecognizedAttribute;
- cErrStr = pszName;
- }
- }
- else
- {
- // Valid namespace, but not one we implement
- bUnknownNS = TRUE;
- }
- }
- else
- {
- // No this attribute doesn't have a namespace
- // prefix that has been declared.
- //
- // Is this the <smil> element and is this an xmlns:foo attribute?
- // If so, then let it go by since we have already processed
- // the namespaces
- if (pNode->m_eElement != SMIL2ElemSmil ||
- strncmp(pszName, "xmlns:", 6) != 0)
- {
- // This is just an error
- retVal = HXR_FAIL;
- eError = SMILErrorUnrecognizedAttribute;
- cErrStr = pszName;
- }
- else
- {
- // We don't want to do validation on xmlns:xx
- // attributes, so treat this as an unknown NS
- bUnknownNS = TRUE;
- }
- }
- }
- if (SUCCEEDED(retVal))
- {
- // Did we recognize the namespace? If we didn't
- // implement the namespace, then we don't need to
- // do anything further
- if (!bUnknownNS)
- {
- // If this was a namespaced attribute, then
- // check the namespace it came from
- if (bNSAttr)
- {
- retVal = checkExtensionAttributeNamespace((SMIL2Attribute) ulAttribute, eNS);
- if (FAILED(retVal))
- {
- eError = SMILErrorUnrecognizedAttribute;
- cErrStr = pszName;
- }
- }
- if (SUCCEEDED(retVal))
- {
- // Check if the attribute is legal for this element
- if (m_pLegalAttrMap->IsSet(pNode->m_eElement, ulAttribute))
- {
- // Legal attribute, now validate the attribute
- const char* pszOrigAttr = (const char*) pValue->GetBuffer();
- char* pszNormAttr = NULL;
- retVal = validateAttribute(pNode->m_eElement, ulAttribute,
- pszOrigAttr, pszNormAttr);
- if (SUCCEEDED(retVal))
- {
- // We validated correctly.
- //
- // Now check if the normalized attribute
- // was different from the original attribute.
- if (strcmp(pszOrigAttr, pszNormAttr))
- {
- if (!pNormAttributes)
- {
- m_pClassFactory->CreateInstance(CLSID_IHXValues,
- (void**) &pNormAttributes);
- }
- addStringProperty(pNormAttributes,
- m_pContext,
- pszName,
- pszNormAttr);
- }
- }
- else
- {
- // Attribute doesn't validate
- eError = SMILErrorBadAttribute;
- cErrStr = pszName;
- }
- HX_VECTOR_DELETE(pszNormAttr);
- }
- else
- {
- // Nope, this attribute is not legal on this element
- retVal = HXR_FAIL;
- eError = SMILErrorUnrecognizedAttribute;
- cErrStr = pszName;
- }
- }
- }
- }
- // Get the next attribute
- HX_RELEASE(pValue);
- rv = pNode->m_pValues->GetNextPropertyCString(pszName, pValue);
- }
- }
- if (SUCCEEDED(retVal))
- {
- // Now check if all REQUIRED attributes are present
- // If there is an entry for our element, then we have
- // required attributes to check. If not, then this
- // element has no required attributes
- if (m_ppReqAttrList &&
- m_ppReqAttrList[pNode->m_eElement])
- {
- // Get the list
- CHXSimpleList* pList = m_ppReqAttrList[pNode->m_eElement];
- // This element does have required attributes - check them
- LISTPOSITION pos = pList->GetHeadPosition();
- while (pos && SUCCEEDED(retVal))
- {
- UINT32 ulAttr = (UINT32) pList->GetNext(pos);
- if (ulAttr < NumSMIL2Attributes)
- {
- // Get the attribute string
- const char* pszStr = g_AttributeTable[ulAttr].m_pszString;
- // Does this element have any attributes?
- if (pNode->m_pValues)
- {
- // Check if this attribute is present
- IHXBuffer* pAttrBuf = NULL;
- retVal = pNode->m_pValues->GetPropertyCString(pszStr, pAttrBuf);
- HX_RELEASE(pAttrBuf);
- }
- else
- {
- // No attributes, so we KNOW it doesn't have
- // this required attribute
- retVal = HXR_FAIL;
- }
- if (FAILED(retVal))
- {
- cErrStr = pszStr;
- }
- }
- }
- if (FAILED(retVal))
- {
- eError = SMILErrorRequiredAttributeMissing;
- }
- }
- if (SUCCEEDED(retVal))
- {
- // Validate the content according to the DTD content model
- retVal = validateContentModel(pNode->m_eElement, pNode->m_pNodeList);
- if (SUCCEEDED(retVal))
- {
- // Now loop through each of the children and
- // validate each of them. First, do we have any children?
- if (pNode->m_pNodeList)
- {
- LISTPOSITION pos = pNode->m_pNodeList->GetHeadPosition();
- while (pos && SUCCEEDED(retVal))
- {
- SMILNode* pChildNode = (SMILNode*) pNode->m_pNodeList->GetNext(pos);
- if (pChildNode)
- {
- retVal = validateNode(pChildNode);
- if (FAILED(retVal))
- {
- bChildFailed = TRUE;
- }
- }
- }
- }
- }
- }
- }
- // Now check if we need to overwrite some of
- // the original attributes with their normalized forms.
- if (SUCCEEDED(retVal) && pNormAttributes)
- {
- // We need to copy all the strings for
- // which the normalized attribute value
- // was different than the original attribute
- // value. Note that this will replace the
- // original attribute value.
- const char* pszName = NULL;
- IHXBuffer* pNormValue = NULL;
- HX_RESULT rv = pNormAttributes->GetFirstPropertyCString(pszName, pNormValue);
- while (SUCCEEDED(rv))
- {
- // Sanity check to make sure the attribute already exists
- // in the current attributes IHXValues
- IHXBuffer* pOrigValue = NULL;
- pNode->m_pValues->GetPropertyCString(pszName, pOrigValue);
- if (pOrigValue)
- {
- pNode->m_pValues->SetPropertyCString(pszName, pNormValue);
- }
- HX_RELEASE(pOrigValue);
- // Get the next normalized attribute
- HX_RELEASE(pNormValue);
- rv = pNormAttributes->GetNextPropertyCString(pszName, pNormValue);
- }
- }
- // Now report any errors, but not if it
- // was just that the child of this node failed, because
- // presumably that node threw an error when it
- // was validated.
- if (FAILED(retVal) && !bChildFailed)
- {
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(eError, cErrStr, pNode->m_ulTagStartLine);
- }
- // Release the normalized attributes
- HX_RELEASE(pNormAttributes);
- }
- return retVal;
- }
- HX_RESULT CSmilParser::validateCDATA(const char* pszStr) const
- {
- HX_RESULT retVal = HXR_OK;
- if (pszStr)
- {
- char* pCh = (char*) pszStr;
- while (*pCh)
- {
- // /Removing the ++ from "...= *pCh++;" fixes bug where
- // HXGetNextChar(pCh), below, otherwise will go on into
- // whatever is past the end of pCh:
- UCHAR c = *pCh;
- if (c < 0x20 &&
- c != 0x09 &&
- c != 0x0A &&
- c != 0x0D)
- {
- retVal = HXR_FAIL;
- break;
- }
- pCh = HXGetNextChar(pCh);
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- return retVal;
- }
- HX_RESULT CSmilParser::validateIDREF(const char* pszStr) const
- {
- HX_RESULT retVal = HXR_OK;
- if (pszStr)
- {
- UINT32 ulLen = (UINT32) strlen(pszStr);
- char* pCh = (char*) pszStr;
- // Check first character
- char c = *pCh++;
- ulLen--;
- if (isXMLLetter(c) ||
- c == '_' ||
- c == ':')
- {
- // Check rest of letters
- while (ulLen--)
- {
- char c = *pCh++;
- if (!isXMLNameChar(c))
- {
- retVal = HXR_FAIL;
- break;
- }
- }
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- return retVal;
- }
- HX_RESULT CSmilParser::validateNMTOKEN(const char* pszStr) const
- {
- HX_RESULT retVal = HXR_OK;
- if (pszStr)
- {
- UINT32 ulLen = (UINT32) strlen(pszStr);
- if (ulLen >= 1)
- {
- char* pCh = (char*) pszStr;
- while (ulLen--)
- {
- char c = *pCh++;
- if (!isXMLNameChar(c))
- {
- retVal = HXR_FAIL;
- break;
- }
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- return retVal;
- }
- HX_RESULT CSmilParser::validateEnumerated(UINT32 ulElem, UINT32 ulAttr, const char* pszStr)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pszStr &&
- ulAttr < NumSMIL2Attributes &&
- m_ppEnumAttrMap &&
- m_ppEnumAttrMap[ulAttr])
- {
- void* pVoid = NULL;
- if (m_ppEnumAttrMap[ulAttr]->Lookup(pszStr, pVoid))
- {
- retVal = HXR_OK;
- }
- else
- {
- // If this is the "type" or "subtype" attribute
- // on the <transition> element, then we also
- // have to check for namespaced attribute values
- if (ulElem == SMIL2ElemTransition &&
- (ulAttr == SMIL2AttrType ||
- ulAttr == SMIL2AttrSubtype))
- {
- // XXXMEH - the spec says that we should not
- // error out on bad transition types or subtypes.
- // Previously, we required that a transition
- // type or subtype be namespaced in order not
- // throw an error. Now we don't require that.
- // if (isNamespacePrefixed(pszStr))
- // {
- retVal = HXR_OK;
- // }
- }
- }
- }
- return retVal;
- }
- BOOL CSmilParser::isNamespacePrefixed(const char* pszStr)
- {
- BOOL bRet = FALSE;
- if (pszStr && m_pValNSList)
- {
- LISTPOSITION pos = m_pValNSList->GetHeadPosition();
- while (pos)
- {
- CNamespaceInfo* pInfo = (CNamespaceInfo*) m_pValNSList->GetNext(pos);
- if (pInfo)
- {
- UINT32 ulPrefixLen = (UINT32) strlen(pInfo->m_pszPrefix);
- if (!strncmp(pszStr, pInfo->m_pszPrefix, ulPrefixLen))
- {
- // We match this namespace prefix
- bRet = TRUE;
- break;
- }
- }
- }
- }
- return bRet;
- }
- HX_RESULT CSmilParser::normalizeAttribute(const char* pszStr,
- BOOL bIsCDATA,
- REF(char*) rpszNormal)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pszStr)
- {
- UINT32 ulLen = (UINT32) strlen(pszStr);
- char* pNormal1 = new char [ulLen + 1];
- if (pNormal1)
- {
- memset(pNormal1, 0, ulLen + 1);
- // Do first part of XML normalization algorithm
- char* pSrc = (char*) pszStr;
- char* pDst = pNormal1;
- while (ulLen--)
- {
- char c = *pSrc++;
- if (c == 0x20 ||
- c == 0x0D ||
- c == 0x0A ||
- c == 0x09)
- {
- *pDst++ = (char) 0x20;
- }
- else
- {
- *pDst++ = c;
- }
- }
- // If the attribute is not CDATA, then we
- // need to remove leading and trailing spaces
- // as well as remove sequences of spaces.
- if (bIsCDATA)
- {
- HX_VECTOR_DELETE(rpszNormal);
- rpszNormal = pNormal1;
- retVal = HXR_OK;
- }
- else
- {
- ulLen = (UINT32) strlen(pNormal1);
- char* pNormal2 = new char [ulLen + 1];
- if (pNormal2)
- {
- memset(pNormal2, 0, ulLen + 1);
- BOOL bFirst = TRUE;
- char* pszToken = strtok(pNormal1, " ");
- while (pszToken)
- {
- if (!bFirst)
- {
- strcat(pNormal2, " "); /* Flawfinder: ignore */
- }
- strcat(pNormal2, pszToken); /* Flawfinder: ignore */
- if (bFirst) bFirst = FALSE;
- pszToken = strtok(NULL, " ");
- }
- // Copy to the out parameter
- HX_VECTOR_DELETE(pNormal1);
- HX_VECTOR_DELETE(rpszNormal);
- rpszNormal = pNormal2;
- retVal = HXR_OK;
- }
- }
- }
- }
- return retVal;
- }
- HX_RESULT CSmilParser::validateAttribute(UINT32 ulElement,
- UINT32 ulAttrib,
- const char* pszStr,
- REF(char*) rpszNormStr)
- {
- HX_RESULT retVal = HXR_OK;
- if (ulElement < NumSMIL2Elements &&
- ulAttrib < NumSMIL2Attributes &&
- pszStr)
- {
- // Look up the attribute type
- XMLAttributeType eType = m_pAttrType[ulAttrib];
- // There are two different elements with
- // two different "type" attributes, so distinguish
- // in between them.
- if (ulAttrib == SMIL2AttrType)
- {
- if (ulElement == SMIL2ElemTransition)
- {
- eType = XMLAttrTypeEnumerated;
- }
- else
- {
- eType = XMLAttrTypeCDATA;
- }
- }
- // Normalize the attribute
- HX_VECTOR_DELETE(rpszNormStr);
- retVal = normalizeAttribute(pszStr, (eType == XMLAttrTypeCDATA), rpszNormStr);
- if (SUCCEEDED(retVal))
- {
- switch (eType)
- {
- case XMLAttrTypeCDATA:
- retVal = validateCDATA(rpszNormStr);
- break;
- case XMLAttrTypeEnumerated:
- retVal = validateEnumerated(ulElement, ulAttrib, rpszNormStr);
- break;
- case XMLAttrTypeID:
- case XMLAttrTypeIDREF:
- retVal = validateIDREF(rpszNormStr);
- break;
- case XMLAttrTypeNMTOKEN:
- retVal = validateNMTOKEN(rpszNormStr);
- break;
- default:
- HX_ASSERT(FALSE);
- break;
- }
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- return retVal;
- }
- HX_RESULT CSmilParser::validateElementName(SMILNode* pNode)
- {
- HX_RESULT retVal = HXR_OK;
- if (pNode && !pNode->m_bCloseNode)
- {
- // Is the element name legal?
- void* pVoid = NULL;
- UINT32 ulElement = 0;
- BOOL bUnknownNS = FALSE;
- BOOL bChildFailed = FALSE;
- SupportedNamespace eNS = NamespaceNotImplemented;
- if (m_pElementMap->Lookup(pNode->m_name, pVoid))
- {
- // We found the element in our SMIL 2 namespace
- //
- // Get the element index
- ulElement = (UINT32) pVoid;
- }
- else
- {
- // We didn't find the element in our SMIL 2 namespace
- //
- // This element name didn't look up in the legal list, so
- // we should first check if it is a namespaced element
- const char* pszElem = NULL;
- CNamespaceInfo* pNSInfo = getNamespaceInfo(pNode->m_name, pszElem);
- if (pNSInfo)
- {
- // Yes, this is a namespaced element, so set
- // the flag so we can remember this later
- pNode->m_bNamespacedElement = TRUE;
- // Is this a recognized RN namespace?
- if (pNSInfo->m_eNamespace != NamespaceNotImplemented)
- {
- // Save the namespace for later
- eNS = pNSInfo->m_eNamespace;
- // Now that we know we are in a namespace that
- // we have implemented, then let's look up
- // the element name in our map
- if (m_pExtElementMap->Lookup(pszElem, pVoid))
- {
- // Get the element index
- ulElement = (UINT32) pVoid;
- }
- else
- {
- // This element claims to be in the above
- // extension namespaces, but is not an extension
- // element we recognize
- retVal = HXR_FAIL;
- }
- }
- else
- {
- // Properly namespaced, but not a namespace
- // we recognize. So ignore it.
- bUnknownNS = TRUE;
- }
- }
- }
- // At this point if we have retVal == HXR_FAIL, then
- // we have an illegal element name. If we have retVal == HXR_OK
- // and bUnknownNS == TRUE, then this element is properly namespaced
- // with an namespace we don't recognize.
- if (SUCCEEDED(retVal) && !bUnknownNS)
- {
- // Do a sanity check on the index
- if (ulElement < NumSMIL2Elements)
- {
- // Assign the element enum
- pNode->m_eElement = g_ElementEnumMap[ulElement];
- // If we are an rn:param, then we treat this
- // as a normal <param>
- if (pNode->m_eElement == SMIL2ElemRNParam)
- {
- pNode->m_tag = SMILParam;
- }
- // If we are an extension element, then check
- // our namespace
- if (pNode->m_bNamespacedElement)
- {
- retVal = checkExtensionElementNamespace(pNode->m_eElement,
- eNS);
- }
- // Recursively check our children
- if (SUCCEEDED(retVal))
- {
- if (pNode->m_pNodeList)
- {
- LISTPOSITION pos = pNode->m_pNodeList->GetHeadPosition();
- while (pos && SUCCEEDED(retVal))
- {
- SMILNode* pChildNode = (SMILNode*) pNode->m_pNodeList->GetNext(pos);
- retVal = validateElementName(pChildNode);
- if (FAILED(retVal))
- {
- bChildFailed = TRUE;
- }
- }
- }
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- // If we failed somewhere along the way, then throw an error.
- // However, since error returns bubble up, then we don't
- // need to throw an error on this element if its child failed.
- if (FAILED(retVal) && !bChildFailed)
- {
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorUnrecognizedTag,
- pNode->m_name,
- pNode->m_ulTagStartLine);
- }
- }
- return retVal;
- }
- HX_RESULT CSmilParser::setupValidationNamespaces(SMILNode* pNode)
- {
- HX_RESULT retVal = HXR_OK;
- if (pNode &&
- pNode->m_tag == SMILSmil &&
- pNode->m_pValues)
- {
- // Clear out any existing namespaces
- deleteValidationNamespaceList();
- // Loop through the attributes, looking for xmlns:foo attributes
- const char* pszName = NULL;
- IHXBuffer* pValue = NULL;
- HX_RESULT rv = pNode->m_pValues->GetFirstPropertyCString(pszName, pValue);
- while (SUCCEEDED(rv) && SUCCEEDED(retVal))
- {
- // Is this an xmlns:foo attribute?
- if (strncmp(pszName, "xmlns:", 6) == 0)
- {
- // This is a namespace declaration, so we need to
- // record the namespace abbreviation
- //
- // If we don't already have a list of namespace
- // declarations, then create one
- if (!m_pValNSList)
- {
- m_pValNSList = new CHXSimpleList();
- }
- if (m_pValNSList)
- {
- // Create a CNamespaceInfo object
- CNamespaceInfo* pInfo = new CNamespaceInfo();
- if (pInfo)
- {
- // Make a copy of the namespace abbreviation
- const char* pszNS = pszName + 6;
- UINT32 ulLen = (UINT32) strlen(pszNS);
- pInfo->m_pszPrefix = new char [ulLen + 2];
- if (pInfo->m_pszPrefix)
- {
- // Copy the abbreviation
- strcpy(pInfo->m_pszPrefix, pszNS); /* Flawfinder: ignore */
- // Concatenate the ":" character to the prefix
- strcat(pInfo->m_pszPrefix, ":"); /* Flawfinder: ignore */
- // Now copy the URL
- const char* pszURL = (const char*) pValue->GetBuffer();
- pInfo->m_pszURL = new char [strlen(pszURL) + 1];
- if (pInfo->m_pszURL)
- {
- // Copy into the member
- strcpy(pInfo->m_pszURL, pszURL); /* Flawfinder: ignore */
- // Now map this string to a supported namespace
- if (m_pNamespaceMap)
- {
- void* pVoid = NULL;
- if (m_pNamespaceMap->Lookup(pszURL, pVoid))
- {
- pInfo->m_eNamespace = (SupportedNamespace) (UINT32) pVoid;
- pInfo->m_bImplemented = TRUE;
- }
- }
- // Append the namespace info object to the list
- m_pValNSList->AddTail((void*) pInfo);
- }
- }
- }
- }
- }
- // Get the next attribute
- HX_RELEASE(pValue);
- rv = pNode->m_pValues->GetNextPropertyCString(pszName, pValue);
- }
- }
- return retVal;
- }
- HX_RESULT CSmilParser::validateAgainstDTD()
- {
- HX_RESULT retVal = HXR_FAIL;
- if (m_pElementMap && m_pAttributeMap &&
- m_pExtElementMap && m_pExtAttributeMap &&
- m_pLegalAttrMap && m_pContentModelMap)
- {
- SMILNode* pSmilNode = findFirstNode(SMILSmil);
- if (pSmilNode)
- {
- retVal = setupValidationNamespaces(pSmilNode);
- if (SUCCEEDED(retVal))
- {
- retVal = validateElementName(pSmilNode);
- if (SUCCEEDED(retVal))
- {
- retVal = validateNode(pSmilNode);
- }
- }
- }
- }
- return retVal;
- }
- HX_RESULT CSmilParser::checkExtensionElementNamespace(SMIL2Element eElem,
- SupportedNamespace eNS)
- {
- HX_RESULT retVal = HXR_FAIL;
- switch (eElem)
- {
- case SMIL2ElemRNParam:
- {
- if (eNS == NamespaceAllSMIL2Extensions ||
- eNS == NamespaceParam)
- {
- retVal = HXR_OK;
- }
- }
- break;
- case SMIL2ElemRNRendererList:
- case SMIL2ElemRNRenderer:
- {
- if (eNS == NamespaceAllSMIL2Extensions ||
- eNS == NamespaceRendererList)
- {
- retVal = HXR_OK;
- }
- }
- break;
- }
- return retVal;
- }
- HX_RESULT CSmilParser::checkExtensionAttributeNamespace(SMIL2Attribute eAttr,
- SupportedNamespace eNS)
- {
- HX_RESULT retVal = HXR_FAIL;
- switch (eAttr)
- {
- case SMIL2AttrRNBackgroundOpacity:
- case SMIL2AttrRNChromaKey:
- case SMIL2AttrRNChromaKeyOpacity:
- case SMIL2AttrRNChromaKeyTolerance:
- case SMIL2AttrRNMediaOpacity:
- case SMIL2AttrRNOpacity:
- {
- if (eNS == NamespaceAllSMIL2Extensions ||
- eNS == NamespaceAlphaControl)
- {
- retVal = HXR_OK;
- }
- }
- break;
- case SMIL2AttrRNDelivery:
- {
- if (eNS == NamespaceAllSMIL2Extensions ||
- eNS == NamespaceParam)
- {
- retVal = HXR_OK;
- }
- }
- break;
- case SMIL2AttrRNHandledBy:
- {
- if (eNS == NamespaceAllSMIL2Extensions ||
- eNS == NamespaceHandledBy)
- {
- retVal = HXR_OK;
- }
- }
- break;
- case SMIL2AttrRNSendTo:
- case SMIL2AttrRNContextWindow:
- {
- if (eNS == NamespaceAllSMIL2Extensions ||
- eNS == NamespaceSendTo)
- {
- retVal = HXR_OK;
- }
- }
- break;
- case SMIL2AttrRNSystemComponent:
- {
- if (eNS == NamespaceSystemComponent)
- {
- retVal = HXR_OK;
- }
- }
- break;
- case SMIL2AttrRNResizeBehavior:
- {
- if (eNS == NamespaceAllSMIL2Extensions ||
- eNS == NamespaceSizeControl)
- {
- retVal = HXR_OK;
- }
- }
- break;
- case XMLEventsAttrHandler:
- {
- if (eNS == NamespaceXMLEvents)
- {
- retVal = HXR_OK;
- }
- }
- break;
- case SMIL2AttrRNAccessErrorBehavior:
- {
- if (eNS == NamespaceAllSMIL2Extensions ||
- eNS == NamespaceAccessErrorBehavior)
- {
- retVal = HXR_OK;
- }
- }
- break;
- }
- return retVal;
- }
- #endif /* #if defined(HELIX_FEATURE_SMIL2_VALIDATION) */
- CNamespaceInfo* CSmilParser::getNamespaceInfo(const char* pszStr,
- REF(const char*) rpszAttr)
- {
- CNamespaceInfo* pRet = NULL;
- if (pszStr && m_pValNSList)
- {
- LISTPOSITION pos = m_pValNSList->GetHeadPosition();
- while (pos)
- {
- CNamespaceInfo* pInfo = (CNamespaceInfo*) m_pValNSList->GetNext(pos);
- if (pInfo)
- {
- UINT32 ulPrefixLen = (UINT32) strlen(pInfo->m_pszPrefix);
- if (!strncmp(pszStr, pInfo->m_pszPrefix, ulPrefixLen))
- {
- pRet = pInfo;
- rpszAttr = pszStr + ulPrefixLen;
- break;
- }
- }
- }
- }
- return pRet;
- }
- HX_RESULT
- CSmilParser::createElements()
- {
- HX_RESULT rc = HXR_OK;
- SMILNode* pSmilNode = findFirstNode(SMILSmil);
- if(!pSmilNode) // dangerwillrobinson!!!
- {
- rc = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorNotSMIL, NULL, 0);
- return rc;
- }
- rc = addToNamespaceScope(pSmilNode);
- if (SUCCEEDED(rc))
- {
- // XXXJEFFA Hardcode "cv" namespace prefix for Redstone alpha 7
- // XXXMEH - remove for SMIL 2
- // rc = addGlobalNamespace(SYSTEM_COMPONENT_NAMESPACE, "cv");
- // /Now, fix Structure Interop #2.1 (unrecognized smil-tag namespace)
- // and #2.3 (SMIL 2.0-module namespaces in the smil tag):
- BOOL bFailedTest = testAttributeFailed(pSmilNode);
- if (bFailedTest)
- {
- // / systemRequired was specified on the whole document, via the
- // <smil ...> tag, and the associated namespace was not specified
- // or is not a supported one. Helps fix SMIL 2.0 Interop
- // Structure Module tests #2.1-#2.3. Is NOT an error condition:
- rc = HXR_OK;
- return rc;
- }
- }
- if (FAILED(rc))
- {
- return rc;
- }
- SMILNode* pHeadNode = findFirstNode(SMILHead);
- if(pHeadNode)
- {
- rc = markTestAttributeNodes(pHeadNode->m_pNodeList);
- if (SUCCEEDED(rc))
- {
- rc = addToNamespaceScope(pHeadNode);
- }
- if(SUCCEEDED(rc))
- {
- rc = createHeadElements(pHeadNode->m_pNodeList);
- }
- if (SUCCEEDED(rc))
- {
- rc = removeFromNamespaceScope(pHeadNode);
- }
- }
- if(rc == HXR_OK)
- {
- SMILNode* pBodyNode = findFirstNode(SMILBody);
- if(pBodyNode &&
- pBodyNode->m_pNodeList)
- {
- CSmilBodyElement* pBodyEl = makeBodyElement(pBodyNode);
- if (pBodyEl)
- {
- pBodyNode->m_pElement = pBodyEl;
- }
- rc = addToNamespaceScope(pBodyNode);
- if (SUCCEEDED(rc))
- {
- SMILNode* pTopNode = getTimelineDescendent(pBodyNode, NULL);
- // /XXXEH- TODO: need to look at body element's m_pValues and
- // see if it has any timing attributes explicitly set; if
- // so, set the following to TRUE, else to FALSE:
- BOOL bBodyTagHasTimingAttributes = TRUE;
- m_bAllowPlaylistBehavior = TRUE;
- #if defined(ALLOW_PLAYLIST_STYLE_SEQ)
- #if defined(DONT_ALLOW_PLAYLIST_STYLE_SEQ_IF_EXPLICIT_OUTER_TIMECONTAINER)
- // /Here's the deal: if pTopNode is an ancestor of *all*
- // media elements, then we don't play as a playlist; the
- // *only* case where we play as a playlist is if there are
- // multiple timed children of the body element, where a
- // child of the body, for these purposes, is defined as a
- // timeline element that has no timeline ancestors other
- // than the body element:
- // /First, look for sibling of pTopNode:
- if (pTopNode)
- {
- SMILNode* pSiblingTopNode =
- getTimelineDescendent(pBodyNode, pTopNode);
- if (pSiblingTopNode &&
- SMILUnknown != pSiblingTopNode->m_tag)
- {
- SMILNode* pSyncAncestorTopNode =
- getSyncAncestor(pTopNode);
- SMILNode* pSyncAncestorSiblingTopNode =
- getSyncAncestor(pSiblingTopNode);
- // /If the sync bases are different, or if each is
- // the body element, then do playlist, else don't:
- if ((pSyncAncestorTopNode !=
- pSyncAncestorSiblingTopNode) ||
- (!pSyncAncestorTopNode &&
- !pSyncAncestorSiblingTopNode) ||
- (SMILBody == pSyncAncestorTopNode->m_tag &&
- SMILBody ==
- pSyncAncestorSiblingTopNode->m_tag) )
- {
- m_bAllowPlaylistBehavior = TRUE;
- }
- else
- {
- m_bAllowPlaylistBehavior = FALSE;
- }
- }
- else
- {
- m_bAllowPlaylistBehavior = FALSE;
- }
- }
- #endif /* DONT_ALLOW_PLAYLIST_STYLE_SEQ_IF_EXPLICIT_OUTER_TIMECONTAINER. */
- // adjust context based on itself position within its parent
- // in nested meta
- if (m_elementWithinTag == WithinPar ||
- m_elementWithinTag == WithinSeqInPar)
- {
- m_bAllowPlaylistBehavior = FALSE;
- }
- if(pTopNode &&
- (pTopNode->m_tag != SMILSeq ||
- // /If body tag has timing attributes, we need to
- // create an outer tag no matter what's already there
- // so this outer tag can take the body's timing:
- bBodyTagHasTimingAttributes) )
- {
- createSeqWrapper(pBodyNode->m_pNodeList,
- !m_bAllowPlaylistBehavior);
- }
- //[SMIL 1.0 compliance] fix for PR 23050:
- // if first descendent of body is a <switch> and its first child
- // is a <seq> that did not get chosen in the switch, then we
- // would be tricked into thinking we already had a valid outer
- // seq, but we wouldn't. Let's put one there in this case,
- // noting that we don't yet know if that seq is valid or not.
- // However, it doesn't matter either way:
- if(pTopNode && SMILSeq == pTopNode->m_tag &&
- pTopNode->m_pParent &&
- pTopNode->m_pParent->m_tag == SMILSwitch)
- {
- createSeqWrapper(pBodyNode->m_pNodeList, FALSE);
- }
- #else
- if (SMILSeq == pTop->m_tag)
- {
- m_bAllowPlaylistBehavior = TRUE;
- }
- else
- {
- m_bAllowPlaylistBehavior = FALSE;
- }
- // adjust context based on itself position within its parent
- // in nested meta
- if (m_elementWithinTag == WithinPar ||
- m_elementWithinTag == WithinSeqInPar)
- {
- m_bAllowPlaylistBehavior = FALSE;
- }
- // /We no longer care if it's a seq or not; we have to
- // respect any timing attributes that have been put on
- // the body element, and we also have to stop doing the
- // playlist-style seq handling:
- if(pTopNode)
- {
- createSeqWrapper(pBodyNode->m_pNodeList,
- m_bAllowPlaylistBehavior);
- }
- #endif
- if(HXR_OK != markTestAttributeNodes(pBodyNode->m_pNodeList) ||
- HXR_OK != expandRepeatElements(pBodyNode->m_pNodeList) ||
- HXR_OK != createBodyElements(pBodyNode->m_pNodeList) ||
- HXR_OK != resolveSyncBaseElements() ||
- HXR_OK != assignGroupIndexes(pBodyNode->m_pNodeList) ||
- HXR_OK != constructTimelineElements(pBodyNode->m_pNodeList) ||
- HXR_OK != setInitialDelays(pBodyNode->m_pNodeList) ||
- //HXR_OK != updateEventElements(pBodyNode->m_pNodeList) ||
- HXR_OK != handleExclDescendants() ||
- #ifdef _DEBUG
- HXR_OK != printBodyElements(pBodyNode->m_pNodeList) ||
- #endif
- HXR_OK != insertGroups())
- {
- rc = HXR_FAIL;
- }
- }
- if (SUCCEEDED(rc))
- {
- rc = removeFromNamespaceScope(pBodyNode);
- }
- }
- if(rc == HXR_OK && !m_bContainsSource)
- {
- rc = HXR_OK;
- //[SMIL 1.0 compliance] fixes PR 27672:
- // don't call SMILErrorNoBodyElements error as it is not one
- // per the SMIL 1.0 spec.
- }
- }
- // Check for any custom events
- if (SUCCEEDED(rc))
- {
- checkForExternalEvents();
- // Check to see if any of the sources
- // had the "handler" attribute defined,
- // and if so, then set corresponding info in
- // the the source which is the handler
- checkForEventHandlers();
- }
- return rc;
- }
- HX_RESULT
- CSmilParser::createSeqWrapper(SMILNodeList* pNodeList, BOOL bMakeInnerPar)
- {
- // /Create a default <seq></seq> wrapper within the <body></body>
- // and move all children as well as attributes of the body to the seq.
- // Then, make an internal par within that seq to get rid of the
- // "playlist" behavior that we've all come to love to hate when the
- // outer time container is a seq:
- HX_RESULT rc = HXR_OK;
- SMILNode* pSeqNode = new SMILNode;
- SMILNode* pParNode = NULL;
- SMILNode* pEndParNode = NULL;
- SMILNode* pWrapperNodeThatGetsTheChildren = pSeqNode;
- int count = pNodeList->GetCount();
- SMILNode* pEndBodyNode = NULL;
- SMILNode* pEndSeqNode = NULL;
- if (!pSeqNode)
- {
- rc = HXR_FAIL;
- goto cleanup;
- }
- pSeqNode->m_name = "seq";
- pSeqNode->m_pParent = pNodeList->m_pParentNode;
- pSeqNode->m_id = assignID("seq");
- pSeqNode->m_tag = SMILSeq;
- pSeqNode->m_pNodeList = new SMILNodeList;
- // /XXXEH- TODO: fix SMIL 2.0 Interop Structure Module #1.2 which needs
- // the following var to be set to FALSE if and only if there really is
- // explicit dur or end on the body element (and we don't want to do
- // playlist behavior in that case either):
- pSeqNode->m_bIsOuterWrapperTimeContainer = TRUE;
- HX_ASSERT(pSeqNode->m_pParent);
- if (pSeqNode->m_pParent && SMILBody == pSeqNode->m_pParent->m_tag)
- {
- // /Copy all of body element's timing to this seq element:
- pSeqNode->m_pParent->m_pValues->AddRef();
- pSeqNode->m_pValues = pSeqNode->m_pParent->m_pValues;
- // /Give seq wrapper the id of the body since it is now the
- // acting body container:
- HX_ASSERT(pSeqNode->m_pParent->m_id.GetLength() > 0);
- if (pSeqNode->m_pParent->m_id.GetLength() > 0)
- {
- pSeqNode->m_id = pSeqNode->m_pParent->m_id;
- (*m_pIDMap)[(const char*)pSeqNode->m_id] =
- pSeqNode;
- pSeqNode->m_pParent->m_id = assignID("body");
- (*m_pIDMap)[(const char*)pSeqNode->m_pParent->m_id] =
- pSeqNode->m_pParent;
- }
- }
- if (bMakeInnerPar)
- {
- pParNode = new SMILNode;
- if (!pParNode)
- {
- HX_DELETE(pSeqNode);
- rc = HXR_FAIL;
- goto cleanup;
- }
- pParNode->m_name = "par";
- pParNode->m_pParent = pSeqNode;
- pParNode->m_id = assignID("par");
- pParNode->m_tag = SMILPar;
- pParNode->m_pNodeList = new SMILNodeList;
- pParNode->m_bIsOuterWrapperTimeContainer = TRUE;
- if (!pParNode->m_pNodeList)
- {
- HX_DELETE(pSeqNode);
- HX_DELETE(pParNode);
- rc = HXR_FAIL;
- goto cleanup;
- }
- // /This par will be the one that adopts the children of the body:
- pWrapperNodeThatGetsTheChildren = pParNode;
- // /The par is a child of the seq wrapper:
- pSeqNode->m_pNodeList->AddTail(pParNode);
- // /Create a </par> node and add it to the new par's list:
- pEndParNode = new SMILNode;
- pEndParNode->m_name = "par";
- pEndParNode->m_pParent = pParNode;
- pEndParNode->m_id = "CLOSE-par";
- pEndParNode->m_tag = SMILEndSeq;
- }
- // move children from bodyNode list to seq list
- while( count > 0) // don't reparent </body> tag
- {
- SMILNode* pChildNode = (SMILNode*)pNodeList->RemoveHead();
- // /Don't reparent the </body> tag...
- if ( pChildNode->m_id != "CLOSE-body" )
- {
- pChildNode->m_pParent = pWrapperNodeThatGetsTheChildren;
- pWrapperNodeThatGetsTheChildren->m_pNodeList->AddTail(pChildNode);
- }
- else
- {
- pEndBodyNode = pChildNode;
- }
- --count;
- }
- // set the persistent duration on this wrapper node to
- // restrain the whole SMIL presentation
- //
- // XXX HP need to remove setting m_ulPersistentComponentDuration
- // explicitly to the group object in ::addGroup() after
- // Erik fix body duration
- if (m_ulPersistentComponentDuration)
- {
- if (!pWrapperNodeThatGetsTheChildren->m_pValues)
- {
- pWrapperNodeThatGetsTheChildren->m_pValues = new CHXHeader();
- pWrapperNodeThatGetsTheChildren->m_pValues->AddRef();
- }
- char szValue[MAX_DISPLAY_NAME] = {0}; /* Flawfinder: ignore */
- IHXBuffer* pBuffer = new CHXBuffer();
- pBuffer->AddRef();
- sprintf(szValue, "%lums", m_ulPersistentComponentDuration); /* Flawfinder: ignore */
- pBuffer->Set((const UCHAR*)szValue, strlen(szValue) + 1);
- pWrapperNodeThatGetsTheChildren->m_pValues->SetPropertyCString("dur", pBuffer);
- HX_RELEASE(pBuffer);
- }
- if (pParNode)
- {
- HX_ASSERT(pEndParNode);
- if (pEndParNode)
- {
- pParNode->m_pNodeList->AddTail(pEndParNode);
- }
- }
- pEndSeqNode = new SMILNode;
- pEndSeqNode->m_name = "seq";
- pEndSeqNode->m_id = "CLOSE-seq";
- pEndSeqNode->m_pParent = pSeqNode;
- pEndSeqNode->m_tag = SMILEndSeq;
- pSeqNode->m_pNodeList->AddTail(pEndSeqNode);
- // now add it to the <body> parent...
- pNodeList->AddHead(pSeqNode);
- pNodeList->AddTail(pEndBodyNode);
- cleanup:
- return rc;
- }
- // /This handles creating a node for the case where an anchor (a or area) tag
- // has a target="x" where "x" is the id of an existing region: (PR 52891)
- HX_RESULT
- CSmilParser::createElementForAnchorTarget(CSmilAAnchorElement* pAnchor,
- SMILNodeList* pNodeList)
- {
- HX_RESULT rc = HXR_OK;
- SMILNode* pRefNode = NULL;
- SMILNode* pTailNode = NULL;
- IHXValues* pAttribs = NULL;
- int count = -1;
- if (!pAnchor || !pAnchor->m_pNode || !(const char*)pAnchor->m_pNode->m_id ||
- !pNodeList || !m_pClassFactory || pAnchor->m_href.IsEmpty())
- {
- HX_ASSERT(pAnchor && pAnchor->m_pNode && (const char*)pAnchor->m_pNode->m_id &&
- pNodeList && m_pClassFactory && !pAnchor->m_href.IsEmpty());
- rc = HXR_FAIL;
- goto cleanup;
- }
- pRefNode = new SMILNode;
- count = pNodeList->GetCount();
- if (!pRefNode || count<2) // /2 <= a|area + CLOSE-par + ...
- {
- HX_ASSERT(pRefNode && count>=2);
- rc = HXR_FAIL;
- goto cleanup;
- }
- pRefNode->m_name = "ref";
- pRefNode->m_pParent = pNodeList->m_pParentNode;
- pRefNode->m_id = assignID("ref_forLinkTarget");
- pRefNode->m_tag = SMILRef;
- // /Now, set the begin and src properties:
- if (HXR_OK == m_pClassFactory->CreateInstance(IID_IHXValues,
- (void**)&pAttribs))
- {
- pRefNode->m_pValues = pAttribs;
- IHXBuffer* pBufBegin = NULL;
- IHXBuffer* pBufSrc = NULL;
- IHXBuffer* pBufRegion = NULL;
- IHXBuffer* pBufLinkDestnSndLevel = NULL;
- IHXBuffer* pBufLinkSourceSndLevel = NULL;
- if ((HXR_OK == m_pClassFactory->CreateInstance(IID_IHXBuffer,
- (void**)&pBufBegin)) &&
- (HXR_OK == m_pClassFactory->CreateInstance(IID_IHXBuffer,
- (void**)&pBufSrc)) &&
- (HXR_OK == m_pClassFactory->CreateInstance(IID_IHXBuffer,
- (void**)&pBufRegion)) &&
- (HXR_OK == m_pClassFactory->CreateInstance(IID_IHXBuffer,
- (void**)&pBufLinkDestnSndLevel)) &&
- (HXR_OK == m_pClassFactory->CreateInstance(IID_IHXBuffer,
- (void**)&pBufLinkSourceSndLevel)) )
- {
- CHXString valStr = (const char*)(pAnchor->m_pNode->m_id);
- valStr += ".activateEvent";
- valStr += ' ';
- const char* pVal = valStr;
- pBufBegin->Set((const unsigned char*)pVal, strlen(valStr)+1);
- pRefNode->m_pValues->SetPropertyCString("begin", pBufBegin);
- pBufSrc->Set((const unsigned char*)((const char*)pAnchor->m_href),
- pAnchor->m_href.GetLength()+1);
- pRefNode->m_pValues->SetPropertyCString("src", pBufSrc);
- pBufRegion->Set((const unsigned char*)((const char*)pAnchor->m_target),
- pAnchor->m_target.GetLength()+1);
- pRefNode->m_pValues->SetPropertyCString("region", pBufRegion);
- // /Helps fix PR 66650: set "soundLevel" here using the anchor's
- // destinationLevel and then use it if|when this source gets added
- char* pszTmp = new char[64];
- if (!pszTmp)
- {
- rc = HXR_OUTOFMEMORY;
- }
- else
- {
- sprintf(pszTmp, "%lu", pAnchor->m_ulDestinationLevel_pct); /* Flawfinder: ignore */
- pBufLinkDestnSndLevel->Set((const unsigned char*)pszTmp,
- strlen(pszTmp)+1);
- pRefNode->m_pValues->SetPropertyCString(
- TARGET_OF_LINK_DESTINATION_SOUND_LEVEL_STR,
- pBufLinkDestnSndLevel);
- sprintf(pszTmp, "%lu", pAnchor->m_ulSourceLevel_pct); /* Flawfinder: ignore */
- pBufLinkSourceSndLevel->Set((const unsigned char*)pszTmp,
- strlen(pszTmp)+1);
- pRefNode->m_pValues->SetPropertyCString(
- TARGET_OF_LINK_SOURCE_SOUND_LEVEL_STR,
- pBufLinkSourceSndLevel);
- delete [] pszTmp;
- // /This is needed for PR 55120, PR 66650, and PR 55791; a link
- // that has sourcePlaystate="play"|"pause" and messes with audio
- // level of either player will require reflush hint to be set:
- if (pAnchor->m_ulSourceLevel_pct !=
- pAnchor->m_ulDestinationLevel_pct &&
- (SMILLinkPlaystatePlay == pAnchor->m_sourcePlaystate ||
- SMILLinkPlaystatePause == pAnchor->m_sourcePlaystate) )
- {
- m_bAllTracksNeedReflushHint = TRUE;
- }
- }
- HX_RELEASE(pBufBegin);
- HX_RELEASE(pBufSrc);
- HX_RELEASE(pBufRegion);
- }
- }
- // /Now add it to the par ancestor after first removing the "CLOSE-par"
- // node from the tail (adding it back afterwards):
- pTailNode = (SMILNode*)pNodeList->RemoveTail();
- pNodeList->AddTail(pRefNode);
- (*m_pIDMap)[(const char*)pRefNode->m_id] = pRefNode;
- if (pTailNode)
- {
- pNodeList->AddTail(pTailNode);
- }
- // /Set this in here since we know this setup was successful:
- pAnchor->m_bTargetIsARegion = TRUE;
- cleanup:
- return rc;
- }
- #if 0 /*XXXEH- I wrote this and then didn't need it but it may come in
- handy later so #if(0) it out: */
- BOOL
- CSmilParser::hasNoSourceChildren(SMILNode* pNode)
- {
- BOOL bNoSourceChildrenFound = TRUE;
- if (pNode && pNode->m_pNodeList)
- {
- int count = pNode->m_pNodeList->GetCount();
- while( count > 0)
- {
- SMILNode* pChildNode =(SMILNode*)(pNode->m_pNodeList->GetHead());
- if (!pChildNode)
- {
- break;
- }
- if (isMediaObject(pChildNode))
- {
- bNoSourceChildrenFound = FALSE;
- break;
- }
- // /Recurse on down:
- else if (!hasNoSourceChildren(pChildNode))
- {
- bNoSourceChildrenFound = FALSE;
- break;
- }
- --count;
- }
- }
- return bNoSourceChildrenFound;
- }
- #endif /* 0 */
- #if 0
- //XXXBAB - useful for debugging
- void
- CSmilParser::PrintNode(SMILNode* pNode, FILE* fp, int level)
- {
- for(int tab=0;tab<level;++tab)
- {
- fprintf(fp, "t");
- }
- fprintf(fp, "%sn", (const char*)pNode->m_id);
- if(pNode->m_pNodeList)
- {
- CHXSimpleList::Iterator i = pNode->m_pNodeList->Begin();
- for(; i != pNode->m_pNodeList->End(); ++i)
- {
- SMILNode* pChildNode = (SMILNode*)(*i);
- PrintNode(pChildNode, fp, level+1);
- }
- }
- }
- void
- CSmilParser::PrintNodes()
- {
- FILE* fp = fopen("nodes.txt", "w");
- SMILNode* pNode = (SMILNode*)m_pNodeList->GetHead();
- PrintNode(pNode, fp, 0);
- fclose(fp);
- }
- #endif
- HX_RESULT
- CSmilParser::printBodyElements(SMILNodeList* pNodeList)
- {
- // debugging code...
- HX_RESULT rc = HXR_OK;
- //#define FOR_DEBUGGING_ONLY
- #if defined(_DEBUG) && defined(FOR_DEBUGGING_ONLY)
- static int level = 0;
- if(!pNodeList)
- {
- return rc;
- }
- CHXSimpleList::Iterator i;
- for(i=pNodeList->Begin();i!=pNodeList->End();++i)
- {
- if(HXR_OK != rc)
- {
- return rc;
- }
- SMILNode* pNode = (SMILNode*)(*i);
- FILE* fp=fopen("c:\temp\smil.txt", "a+");
- if (!fp)
- {
- break;
- }
- for(int i=0;i<level;++i)
- {
- fprintf(fp, "t");
- }
- UINT32 ulDelay = (UINT32)-1;
- UINT32 ulDuration = (UINT32)-1;
- if(pNode->m_pElement &&
- pNode->m_pElement->m_pTimelineElement)
- {
- ulDelay = pNode->m_pElement->m_pTimelineElement->getDelay();
- ulDuration = pNode->m_pElement->m_pTimelineElement->getDuration();
- }
- fprintf(fp, "%s tag=%d group=%d repeatid=%s delay=%d duration=%d deleted=%dn", (const char*)pNode->m_id,
- pNode->m_tag, pNode->m_nGroup, (const char*)pNode->m_repeatid, ulDelay, ulDuration, pNode->m_bDelete);
- fclose(fp);
- if(pNode->m_pNodeList)
- {
- ++level;
- rc = printBodyElements(pNode->m_pNodeList);
- --level;
- }
- }
- #endif
- return rc;
- }
- HX_RESULT
- CSmilParser::insertGroups()
- {
- HX_RESULT rc = HXR_OK;
- if(!m_pAddGroupMap)
- {
- rc = HXR_UNEXPECTED;
- }
- else
- {
- UINT32 ulGroupNo = 0;
- CSmilAddGroup* pAddGroup = 0;
- BOOL bGroupInserted = FALSE;
- while(m_pAddGroupMap->Lookup(ulGroupNo++, (void*&)pAddGroup))
- {
- bGroupInserted = TRUE;
- pAddGroup->m_ulDelay = 0;
- pAddGroup->m_ulTimestamp = INITIAL_STREAM0_TIMESTAMP;
- insertElementByTimestamp(pAddGroup);
- }
- }
- return rc;
- }
- BOOL
- CSmilParser::inLanguagePreference(const char* pLang)
- {
- // return FALSE if language preference is not in m_pLanguagePreferenceList
- BOOL rc = FALSE;
- // pLang can be comma separated lists,
- // with '*' accepting all languages
- // copy the string so strtok doesn't modify something bad...
- char* pLangCopy = new_string(pLang);
- char* pLangFrag = strtok(pLangCopy, ",");
- while(pLangFrag)
- {
- // /Fixes the SMIL-file part of PR 58151: sometimes this list will
- // have tokens that are padded w/whitespaces or are separated by ", "
- // instead of just ",", so first remove all whitespace chars after
- // the ',' (or at the start of the first token) and, if we run
- // into a whitespace-only string, go past the next comma:
- while (isspace(*pLangFrag) || ',' == *pLangFrag)
- {
- *pLangFrag++;
- }
- if (' ' == *pLangFrag)
- {
- break; // /Whitespace-only or emtpy string is not valid.
- }
- if(*pLangFrag == '*') // wildcard
- {
- rc = TRUE;
- break;
- }
- // copy the primary tag part of the language (up to '-')
- char* pPrimaryTag = new char[strlen(pLang)+1];
- char* pTagPtr = pPrimaryTag;
- char* pFragPtr = pLangFrag;
- while(*pFragPtr && *pFragPtr != '-')
- {
- *pTagPtr++ = *pFragPtr++;
- }
- *pTagPtr = ' ';
- CHXSimpleList::Iterator i = m_pLanguagePreferenceList->Begin();
- for(; i != m_pLanguagePreferenceList->End(); ++i)
- {
- char* pPrefLang = (char*)(*i);
- if(*pPrefLang == '*' && // wildcard
- // /Adding this check for "*"-only string "fixes" TLC's
- // PR 64646 that they don't want to fix for fear it will
- // break other things; only allow "*[x]" where [x] is one
- // or more characters since TLC sends (has since 1998) a
- // solo "*" at the end of the language list (for purposes
- // other than SMIL). Without this fix, every language
- // (like systemLanguage="holwerMonkey") evaluates to TRUE:
- *(pPrefLang+1) != ' ')
- {
- rc = TRUE;
- }
- else if(strcmp(pPrefLang, pLangFrag) == 0)
- {
- rc = TRUE;
- }
- else if(strncmp(pPrefLang, pPrimaryTag, strlen(pPrimaryTag)) == 0)
- {
- rc = TRUE;
- }
- if(rc)
- {
- break;
- }
- }
- delete[] pPrimaryTag;
- if(rc)
- {
- break;
- }
- pLangFrag = strtok(NULL, ",");
- }
- delete[] pLangCopy;
- return rc;
- }
- BOOL
- CSmilParser::systemComponentFailed(IHXBuffer* pRequiredValue)
- {
- BOOL bFailed = TRUE;
- if (m_pContext)
- {
- IHXUpgradeCollection* pUpgradeCollection = NULL;
- m_pContext->QueryInterface(IID_IHXUpgradeCollection,
- (void**) &pUpgradeCollection);
- if (pUpgradeCollection)
- {
- UINT32 ulIndexOfAddedValue =
- pUpgradeCollection->Add(eUT_Required, pRequiredValue, 0, 0);
- if (!m_pISystemRequired)
- {
- m_pContext->QueryInterface(IID_IHXSystemRequired,
- (void**) &m_pISystemRequired);
- }
- if (m_pISystemRequired)
- {
- bFailed = FAILED(m_pISystemRequired->HasFeatures(pUpgradeCollection));
- }
- if (bFailed)
- {
- // /Removing failed component fixes PR 95617. The
- // (persistent m_pContext's) upgradeCollection will fail the
- // next time, too, even if the next value should succeed, if
- // the current non-supported value remains in it:
- pUpgradeCollection->Remove(ulIndexOfAddedValue);
- }
- }
- HX_RELEASE(pUpgradeCollection);
- }
- return bFailed;
- }
- BOOL
- CSmilParser::testAttributeFailed(SMILNode* pNode)
- {
- HX_RESULT rc = HXR_OK;
- BOOL bFailed = FALSE;
- IHXBuffer* pBuf = 0;
- if(pNode->m_pValues)
- {
- rc = pNode->m_pValues->GetPropertyCString("system-required", pBuf);
- if (FAILED(rc))
- {
- rc = pNode->m_pValues->GetPropertyCString("systemRequired", pBuf);
- }
- if(HXR_OK == rc)
- {
- const char* pActualString = (const char*)pBuf->GetBuffer();
- // Check with the core first
- if(m_pRequireTagsMap)
- {
- void* pTag = 0;
- // /In SMIL 2.0, this may be a list of logically ANDed values
- // separated by a '+', e.g., "HostLanguage+BrushMedia". We
- // need to look up all of them and, if any in the list are
- // not found, we fail on the whole thing. (See SMIL 2.0
- // Interop Structure Module test #2.2 & #2.3):
- // /XXXEH- do whitespace removal on either side of '+'s:
- const char* pStrWalker = pActualString;
- char* pNextPlusSign = (char*)(strchr(pStrWalker,'+'));
- do
- {
- if (pNextPlusSign)
- {
- *pNextPlusSign = ' ';
- }
- if (!m_pRequireTagsMap->Lookup(pStrWalker, (void*&)pTag))
- {
- bFailed = TRUE;
- }
- if (pNextPlusSign)
- {
- *pNextPlusSign = '+';
- pStrWalker = pNextPlusSign+1;
- pNextPlusSign = (char*)(strchr(pStrWalker,'+'));
- }
- else
- {
- pStrWalker = NULL;
- }
- } while (!bFailed && pStrWalker);
- }
- else // no required list, can't parse it
- {
- bFailed = TRUE;
- }
- pBuf->Release();
- if(bFailed)
- {
- goto exit;
- }
- }
- rc = pNode->m_pValues->GetPropertyCString("systemBitrate", pBuf);
- if (FAILED(rc))
- {
- rc = pNode->m_pValues->GetPropertyCString("system-bitrate", pBuf);
- }
- if(HXR_OK == rc)
- {
- UINT32 ulBandwidth = atol((const char*)pBuf->GetBuffer());
- if(m_ulBandwidthPreference < ulBandwidth)
- {
- bFailed = TRUE;
- }
- pBuf->Release();
- if(bFailed)
- {
- goto exit;
- }
- }
- rc = pNode->m_pValues->GetPropertyCString("systemLanguage", pBuf);
- if (FAILED(rc))
- {
- rc = pNode->m_pValues->GetPropertyCString("system-language", pBuf);
- }
- if(HXR_OK == rc)
- {
- if(m_pLanguagePreferenceList)
- {
- const char* pLang = (const char*)pBuf->GetBuffer();
- if(!inLanguagePreference(pLang))
- {
- bFailed = TRUE;
- }
- }
- else // no preference, can't do it...
- {
- bFailed = TRUE;
- }
- pBuf->Release();
- if(bFailed)
- {
- goto exit;
- }
- }
- rc = pNode->m_pValues->GetPropertyCString("systemCaptions", pBuf);
- if (FAILED(rc))
- {
- rc = pNode->m_pValues->GetPropertyCString("system-captions", pBuf);
- }
- if(HXR_OK == rc)
- {
- const char* pActualValue = (const char*)pBuf->GetBuffer();
- if(strcmp(pActualValue, "on") == 0)
- {
- if(!m_bCaptionsPreference)
- {
- bFailed = TRUE;
- }
- }
- else
- {
- if(m_bCaptionsPreference)
- {
- bFailed = TRUE;
- }
- }
- pBuf->Release();
- if(bFailed)
- {
- goto exit;
- }
- }
- rc = pNode->m_pValues->GetPropertyCString("systemOverdubOrSubtitle",
- pBuf);
- if (FAILED(rc))
- {
- rc = pNode->m_pValues->GetPropertyCString(
- "system-overdub-or-caption", pBuf);
- }
- if (rc == HXR_OK)
- {
- if(m_pOverdubOrCaptionPreference)
- {
- const char* pActualValue = (const char*)pBuf->GetBuffer();
- if(strcmp(pActualValue, "caption") == 0)
- {
- if(strcmp(m_pOverdubOrCaptionPreference, "caption") != 0)
- {
- bFailed = TRUE;
- }
- }
- else if(strcmp(pActualValue, "overdub") == 0)
- {
- if(strcmp(m_pOverdubOrCaptionPreference, "overdub") != 0)
- {
- bFailed = TRUE;
- }
- }
- }
- else
- {
- bFailed = TRUE;
- }
- pBuf->Release();
- if(bFailed)
- {
- goto exit;
- }
- }
- rc = pNode->m_pValues->GetPropertyCString("systemScreenSize", pBuf);
- if (FAILED(rc))
- {
- rc = pNode->m_pValues->GetPropertyCString("system-screen-size",
- pBuf);
- }
- if(HXR_OK == rc)
- {
- UINT32 ulScreenHeight = 0;
- UINT32 ulScreenWidth = 0;
- const char* pScreenSize = (const char*)pBuf->GetBuffer();
- // format is screen-height "X" screen-width
- char tmp[256]; /* Flawfinder: ignore */
- SafeStrCpy(tmp, pScreenSize, 256);
- char* pScreenHeight = strtok(tmp, "X");
- if(pScreenHeight)
- {
- ulScreenHeight = atol(pScreenHeight);
- char* pScreenWidth = strtok(NULL, "");
- if(pScreenWidth)
- {
- ulScreenWidth = atol(pScreenWidth);
- }
- }
- // /If it's (0,0) in our system, then we failed to get the values
- // from the OS via GetSystemScreenInfo() & thus don't support this
- // in this OS. SMIL 2.0 spec says to return "TRUE" if you don't
- // support a test attribute:
- if((!m_ulScreenHeightPreference && !m_ulScreenWidthPreference))
- {
- bFailed = FALSE;
- }
- else if((m_ulScreenHeightPreference < ulScreenHeight) ||
- (m_ulScreenWidthPreference < ulScreenWidth))
- {
- bFailed = TRUE;
- }
- pBuf->Release();
- if(bFailed)
- {
- goto exit;
- }
- }
- rc = pNode->m_pValues->GetPropertyCString("systemScreenDepth", pBuf);
- if (FAILED(rc))
- {
- rc = pNode->m_pValues->GetPropertyCString("system-screen-depth",
- pBuf);
- }
- if(HXR_OK == rc)
- {
- UINT32 ulScreenDepth = atol((const char*)pBuf->GetBuffer());
- // /If it's 0 in our system, then our player does not (in this
- // current build) support this. The SMIL 2.0 spec says to
- // return "TRUE" if you don't support a test attribute:
- if(!m_ulScreenDepthPreference)
- {
- bFailed = FALSE;
- }
- else if(m_ulScreenDepthPreference < ulScreenDepth)
- {
- bFailed = TRUE;
- }
- pBuf->Release();
- if(bFailed)