[prev in list] [next in list] [prev in thread] [next in thread] 

List:       helix-datatype-cvs
Subject:    [Datatype-cvs] smil/renderer/smil2 animattr.cpp, 1.4,
From:       ehyche () helixcommunity ! org
Date:       2007-12-04 21:33:44
Message-ID: 200712042134.lB4LYDdW007387 () mailer ! progressive-comp ! com
[Download RAW message or body]

Update of /cvsroot/datatype/smil/renderer/smil2
In directory cvs01.internal.helixcommunity.org:/tmp/cvs-serv24561/renderer/smil2

Modified Files:
	animattr.cpp sitewatc.cpp sitewatc.h smldoc.cpp smlelem.cpp 
	smlparse.cpp 
Log Message:
Description
--------------------------------------------------
SMIL 3 adds a neat feature to media elements called panZoom,
which you can use to get "Ken Burns" style effects on
any media. For instance, you can do the following:

<head>
  <layout>
    <root-layout width="232" height="232" backgroundColor="blue"/>
    <region id="reg1" left="16" top="16" width="400" height="300" fit="fill"/>
  </layout>
</head>
<body>
  <par>
    <ref id="sunset" src="sunset_800x600.jpg" region="reg1" dur="10s" \
panZoom="200,150,400,300"/>  <animate begin="3s" dur="5s" targetElement="sunset" \
attributeName="panZoom"  from="200,150,400,300" to="0,0,800,600" fill="freeze"/>
  </par>
</body>

This will start off showing a 400x300 window of in the
center of an 800x600 image and then zoom out starting 
at 3s into the presentation until it has zoomed out
all the way, showing the entire image from 8s to 10s.
These changes add support for this feature.

Note that in some cases, support is also required from
the site, where some changes had to be made as well.
I will be sending a separate CR for the site changes.

Files Modified
--------------------------------------------------
datatype/smil/include/smiltype.h
datatype/smil/renderer/smil2/animattr.cpp
datatype/smil/renderer/smil2/sitewatc.cpp
datatype/smil/renderer/smil2/sitewatc.h
datatype/smil/renderer/smil2/smldoc.cpp
datatype/smil/renderer/smil2/smlelem.cpp
datatype/smil/renderer/smil2/smlparse.cpp
datatype/smil/renderer/smil2/pub/animattr.h
datatype/smil/renderer/smil2/pub/parstabl.h
datatype/smil/renderer/smil2/pub/smldoc.h
datatype/smil/renderer/smil2/pub/smlelem.h
datatype/smil/renderer/smil2/pub/smlparse.h

Branches
--------------------------------------------------
HEAD only



Index: smlelem.cpp
===================================================================
RCS file: /cvsroot/datatype/smil/renderer/smil2/smlelem.cpp,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- smlelem.cpp	21 Nov 2007 20:01:41 -0000	1.26
+++ smlelem.cpp	4 Dec 2007 21:33:41 -0000	1.27
@@ -2500,7 +2500,7 @@
     m_ulLinkTargetSourceLevel_pct   = 100;
     m_ulPrefetchAmount              = 0;
     m_typeOfPrefetchAmount          = PrefetchUnknown;
-
+    SetPanZoomToDefault(m_PanZoomRect);
 }
 
 CSmilSource::~CSmilSource()
@@ -2577,6 +2577,41 @@
     }
 }
 
+void CSmilSource::SetPanZoomToDefault(LayoutRect& rRect)
+{
+    rRect.m_dLeft           = 0.0;
+    rRect.m_eLeftType       = CSS2TypeLength;
+    rRect.m_dTop            = 0.0;
+    rRect.m_eTopType        = CSS2TypeLength;
+    rRect.m_dRight          = 0.0;
+    rRect.m_eRightType      = CSS2TypeAuto;
+    rRect.m_dBottom         = 0.0;
+    rRect.m_eBottomType     = CSS2TypeAuto;
+    rRect.m_dWidth          = 100.0;
+    rRect.m_eWidthType      = CSS2TypePercentage;
+    rRect.m_dHeight         = 100.0;
+    rRect.m_eHeightType     = CSS2TypePercentage;
+}
+
+HXBOOL CSmilSource::IsPanZoomDefault(LayoutRect& rRect)
+{
+    HXBOOL bRet = FALSE;
+
+    if (rRect.m_dLeft       == 0.0                &&
+        rRect.m_eLeftType   == CSS2TypeLength     &&
+        rRect.m_dTop        == 0.0                &&
+        rRect.m_eTopType    == CSS2TypeLength     &&
+        rRect.m_dWidth      == 100.0              &&
+        rRect.m_eWidthType  == CSS2TypePercentage &&
+        rRect.m_dHeight     == 100.0              &&
+        rRect.m_eHeightType == CSS2TypePercentage)
+    {
+        bRet = TRUE;
+    }
+
+    return bRet;
+}
+
 /*
  * CSmilSourceUpdate methods
  */

Index: sitewatc.h
===================================================================
RCS file: /cvsroot/datatype/smil/renderer/smil2/sitewatc.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- sitewatc.h	6 Jul 2007 22:01:52 -0000	1.4
+++ sitewatc.h	4 Dec 2007 21:33:41 -0000	1.5
@@ -76,22 +76,25 @@
 
     // CSmilSiteWatcher methods
     HX_RESULT   close();
-    IHXSite*   GetSite()                    { return m_pSite; }
+    IHXSite*    GetSite()                    { return m_pSite; }
     void        SiteChangingSize(HXBOOL bFlag) { m_bChangingSize = bFlag; }
     void        GetSubRegionRect(REF(LayoutRect) rcRect) { rcRect = m_Rect; }
     void        SetSubRegionRect(LayoutRect cRect)       { m_Rect = cRect;  }
     void        SetZoomScaleFactors(double dX, double dY);
     void        SetResizeBehavior(ResizeBehavior eBehavior);
     const char* GetSourceID() { return (const char*) m_SourceID; }
+    void        SetPanZoomRect(LayoutRect& rRect) { m_PanZoomRect = rRect; }
 private:
     INT32                  m_lRefCount;
     CSmilDocumentRenderer* m_pDoc;
-    IHXSite*              m_pSite;
+    IHXSite*               m_pSite;
+    IHXSite3*              m_pSite3;
     CHXString              m_id;
     CHXString              m_SourceID;
     RegPoint               m_RegPoint;
     Fit                    m_eFit;
     LayoutRect             m_Rect;
+    LayoutRect             m_PanZoomRect;
     HXxSize                m_MediaSize;
     double                 m_dZoomScaleFactorX;
     double                 m_dZoomScaleFactorY;

Index: smlparse.cpp
===================================================================
RCS file: /cvsroot/datatype/smil/renderer/smil2/smlparse.cpp,v
retrieving revision 1.48
retrieving revision 1.49
diff -u -d -r1.48 -r1.49
--- smlparse.cpp	26 Nov 2007 21:49:42 -0000	1.48
+++ smlparse.cpp	4 Dec 2007 21:33:41 -0000	1.49
@@ -393,7 +393,8 @@
     m_bSubtitlesPreference(FALSE),
 #endif //  HELIX_FEATURE_PRESENTATION_FEATURE_SELECTION.
     m_pEncoding(0),
-    m_pLanguagePreferenceList(0),
+    m_pLanguagePreferenceList(NULL),
+    m_pLanguagePreferenceQList(NULL),
     m_pErrors(NULL),
     m_ulPlatformVer(HX_PLATFORM_UNKNOWN),
     m_pElementMap(NULL),
@@ -557,16 +558,8 @@
     HX_DELETE(m_pNodeDependencies);
     HX_DELETE(m_pAnchorStack);
     HX_VECTOR_DELETE(m_pEncoding);
-    if(m_pLanguagePreferenceList)
-    {
-	CHXSimpleList::Iterator i = m_pLanguagePreferenceList->Begin();
-	for(; i != m_pLanguagePreferenceList->End(); ++i)
-	{
-	    char* pLang = (char*)(*i);
-	    delete[] pLang;
-	}
-	HX_DELETE(m_pLanguagePreferenceList);
-    }
+    HX_DELETE(m_pLanguagePreferenceList);
+    HX_DELETE(m_pLanguagePreferenceQList);
     HX_DELETE(m_pOverdubOrCaptionPreference);
     HX_DELETE(m_pBasePath);
 
@@ -670,39 +663,95 @@
     if(HXR_OK == m_pContext->QueryInterface(
 	IID_IHXPreferences, (void**)&pPrefs))
     {
-	IHXBuffer* pBuf = 0;
+        // Get the registry entry name for language
 	CHXString strTemp;
-	strTemp.Format("%s.%s",HXREGISTRY_PREFPROPNAME,"Language");
-
+	strTemp.Format("%s.%s", HXREGISTRY_PREFPROPNAME, "Language");
+        // Get the Language registry entry
+	IHXBuffer* pBuf = NULL;
 	if(pRegistry && HXR_OK == pRegistry->GetStrByName(strTemp, pBuf))
 	{
-	    // language preference can be a comma-separated list
-
-	    const char* pLang = (const char*)pBuf->GetBuffer();
-	    // gonna call strtok, so copy the string...
-	    char* pLangCopy = new_string(pLang);
-	    m_pLanguagePreferenceList = new CHXSimpleList;
-	    char* pTok = strtok(pLangCopy, ",");
-	    while(pTok)
-	    {
-		// /Fixes TLC-set part of PR 58151: sometimes this list will
-		// have tokens separated by ", " instead of just ",", so first
-		// remove all whitespace chars after the ',' (and, if we run
-		// into a whitespace-only string, go past the next comma):
-		while (isspace(*pTok)  ||  ',' == *pTok)
-		{
-		    pTok++;
-		}
-		if ('\0' == *pTok)
-		{
-		    break; // /Whitespace-only or emtpy string is not valid.
-		}
-
-		char* pLangString = new_string(pTok);
-		m_pLanguagePreferenceList->AddTail(pLangString);
-		pTok = strtok(NULL, ",");
-	    }
-	    delete[] pLangCopy;
+            // The format of this registry entry is the same
+            // as the "Accept-Language" HTTP header, which is
+            // specified by RFC3282 here:
+            // http://www.ietf.org/rfc/rfc3282.txt
+            //
+            // We will use this definition:
+            //
+            // Obs-accept-language = "Accept-Language" *WSP ":" [CFWS]
+            //                       obs-language-q *( "," [CFWS] obs-language-q ) \
[CFWS] +            //  obs-language-q     = language-range [ [CFWS] ";" [CFWS] "q" \
[CFWS] "=" qvalue ] +            //  qvalue             = ( "0" [ "." 0*3DIGIT ] )
+            //                       / ( "1" [ "." 0*3("0") ] )
+            //
+            // where CFWS is defined by RFC822 and is essentially whitespace.
+            //
+            // Copy the Language registry entry into a CHXString
+            CHXString strLanguage((const char*)pBuf->GetBuffer());
+            // Get the number of tokens if we delimit by the comma
+            UINT32 ulNumCommaFields = strLanguage.CountFields(',');
+            for (UINT32 i = 1; i <= ulNumCommaFields; i++)
+            {
+                // Get the i-th field when separated by commas.
+                // CHXString::NthField() uses 1-based field indices
+                // instead of 0-based.
+                CHXString strIthField = strLanguage.NthField(',', i);
+                // Now see if this field can be split by a semi-colon delimiter
+                UINT32 ulNumSemiColonFields = strIthField.CountFields(';');
+                // The first field is the language
+                CHXString strLang = strIthField.NthField(';', 1);
+                // Trim any leading or trailing whitespace
+                strLang.TrimLeft();
+                strLang.TrimRight();
+                // Get the language q-value (not required). If
+                // there are no q-values, then all the language
+                // values take a q-value of 1.0.
+                double dLangQ = 1.0;
+                if (ulNumSemiColonFields > 1)
+                {
+                    // Get the second field
+                    CHXString strQEquals = strIthField.NthField(';', 2);
+                    // This field should look something like "  q  = 0.9  "
+                    // so we will split this field along the equals sign.
+                    UINT32 ulNumQFields = strQEquals.CountFields('=');
+                    if (ulNumQFields > 1)
+                    {
+                        // Get the second field
+                        CHXString strQValue = strQEquals.NthField('=', 2);
+                        // Trim any leading or trailing whitespace
+                        strQValue.TrimLeft();
+                        strQValue.TrimRight();
+                        // Now convert to a double
+                        double dQValue = atof((const char*) strQValue);
+                        // Make sure this value is in the range [0.0,1.0]
+                        if (dQValue >= 0.0 && dQValue <= 1.0)
+                        {
+                            dLangQ = dQValue;
+                        }
+                    }
+                }
+                // Do we have a language preference list?
+                if (!m_pLanguagePreferenceList)
+                {
+                    // Create the language preference list
+                    m_pLanguagePreferenceList = new CHXStringList();
+                }
+                // Add the language to the language pref list
+                if (m_pLanguagePreferenceList)
+                {
+                    m_pLanguagePreferenceList->AddTailString((const char*) strLang);
+                }
+                // Do we have a language Q-value list?
+                if (!m_pLanguagePreferenceQList)
+                {
+                    // Create the language Q-value list
+                    m_pLanguagePreferenceQList = new CHXSimpleList();
+                }
+                if (m_pLanguagePreferenceQList)
+                {
+                    UINT32 ulQValue = (UINT32) (dLangQ * 1000.0);
+                    m_pLanguagePreferenceQList->AddTail((void*) ulQValue);
+                }
+            }
 	    HX_RELEASE(pBuf);
 	}
 	if(HXR_OK == pPrefs->ReadPref("bandwidth", pBuf)  ||
@@ -4443,10 +4492,14 @@
                 pos = m_pLanguagePreferenceList->GetHeadPosition();
                 while (pos)
                 {
-                    pszLang = (char*)m_pLanguagePreferenceList->GetNext(pos);
-                    if (pszLang  &&  *pszLang)
+                    CHXString* pStrLang = m_pLanguagePreferenceList->GetNext(pos);
+                    if (pStrLang)
                     {
-                        break; //  Found the first preferred language
+                        pszLang = (char*) (const char*) *pStrLang;
+                        if (pszLang  &&  *pszLang)
+                        {
+                            break; //  Found the first preferred language
+                        }
                     }
                 }
             }
@@ -9395,6 +9448,50 @@
     return bSomeoneIsListeningForActivateEvent;
 }
 
+HXBOOL CSmilParser::IsPanZoomUsedForMedia(const char* pszMediaID)
+{
+    HXBOOL bRet = FALSE;
+
+    if (pszMediaID)
+    {
+        // Look up the element with this id
+        CSmilSource* pSource = (CSmilSource*) findElement(pszMediaID);
+        if (pSource)
+        {
+            // Is the panZoom attribute of the source all default values?
+            HXBOOL bPanZoomDefault = \
CSmilSource::IsPanZoomDefault(pSource->m_PanZoomRect); +            // Now we have to \
see if any animations are done on +            // the panZoom attribute of this \
element. So loop through +            // all of the animation elements
+            HXBOOL bPanZoomAnimated = FALSE;
+            if (m_pAnimateElementList)
+            {
+                LISTPOSITION pos = m_pAnimateElementList->GetHeadPosition();
+                while (pos)
+                {
+                    CSmilAnimateElement* pAnim = (CSmilAnimateElement*) \
m_pAnimateElementList->GetNext(pos); +                    if (pAnim && \
pAnim->m_pTargetElementID && +                        *(pAnim->m_pTargetElementID) == \
pszMediaID && +                        pAnim->m_ucAttributeName == kAttrNamePanZoom)
+                    {
+                        bPanZoomAnimated = TRUE;
+                        break;
+                    }
+                }
+            }
+            // If the panZoom attribute of this source is not all default
+            // values OR the panZoom attribute is animated by another element,
+            // then we will use panZoom for this media.
+            if (!bPanZoomDefault || bPanZoomAnimated)
+            {
+                bRet = TRUE;
+            }
+        }
+    }
+
+    return bRet;
+}
+
 #if defined(HELIX_FEATURE_PRESENTATION_FEATURE_SELECTION)
 //  Returns "true" if the media element has the attribute
 // changeFeatureOnActivateEvent([ANY PF].[ANY VALUE])
@@ -14043,6 +14140,11 @@
                         rc = HXParseColorUINT32(pszValue, \
pSource->m_ulChromaKeyTolerance);  }
                     break;
+                case SMIL3AttrPanZoom:
+                    {
+                        rc = parsePanZoom(pszValue, pSource->m_PanZoomRect);
+                    }
+                    break;
                 default:
                     {
                         if(!bFoundCB && strcmp(pName, "clip-begin") == 0)
@@ -15685,6 +15787,10 @@
                         {
                             pAnim->m_ucAttributeName = kAttrNameValue;
                         }
+                        else if (strcmp(pszVal, "panZoom") == 0)
+                        {
+                            pAnim->m_ucAttributeName = kAttrNamePanZoom;
+                        }
                         else
                         {
                             // Find out if this attributeName is namespace-prefixed.
@@ -16287,6 +16393,7 @@
                                   pAnim->m_ucAttributeName == kAttrNameWidth         \
                ||
                                   pAnim->m_ucAttributeName == kAttrNameHeight        \
                ||
                                   pAnim->m_ucAttributeName == kAttrNameZIndex        \
|| +                                  pAnim->m_ucAttributeName == kAttrNamePanZoom    \
                ||
                                   pAnim->m_ucAttributeName == \
                kAttrNameBackgroundColor ||
                                   pAnim->m_ucAttributeName == kAttrNameMediaOpacity  \
                ||
                                   pAnim->m_ucAttributeName == \
kAttrNameBackgroundOpacity)) @@ -19313,7 +19420,7 @@
 }
 
 HXBOOL
-CSmilParser::inLanguagePreference(const char* pLang)
+CSmilParser::inLanguagePreference(const char* pLang, INT32* plQValue)
 {
     // return FALSE if language preference is not in m_pLanguagePreferenceList
 
@@ -19358,40 +19465,69 @@
 	}
 	*pTagPtr = '\0';
 
+        UINT32 ulIndx = 0;
 	CHXSimpleList::Iterator i = m_pLanguagePreferenceList->Begin();
-	for(; i != m_pLanguagePreferenceList->End(); ++i)
+	for(; i != m_pLanguagePreferenceList->End(); ++i, ulIndx++)
 	{
-	    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="howlerMonkey") evaluates to TRUE:
-		    *(pPrefLang+1) != '\0')
-	    {
-		rc = TRUE;
-	    }
-	    else if(strcmp(pPrefLang, pLangFrag) == 0)
-	    {
-		rc = TRUE;
-	    }
-	    else if(strncmp(pPrefLang, pPrimaryTag, strlen(pPrimaryTag)) == 0)
-	    {
-		rc = TRUE;
-	    }
-	    if(rc)
-	    {
-		break;
-	    }
+            CHXString* pStrPrefLang = (CHXString*) (*i);
+            if (pStrPrefLang)
+            {
+	        const char* pPrefLang = (const char*) *pStrPrefLang;
+	        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="howlerMonkey") evaluates to TRUE:
+		        *(pPrefLang+1) != '\0')
+	        {
+		    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)
 	{
+            // Did the user request a q-value?
+            if (plQValue)
+            {
+                // Do we have a q-value list?
+                if (m_pLanguagePreferenceQList &&
+                    ulIndx < m_pLanguagePreferenceQList->GetCount())
+                {
+                    // Get the position of the ulIndx-th entry in the list.
+                    LISTPOSITION pos = \
m_pLanguagePreferenceQList->FindIndex(ulIndx); +                    // Get the entry \
at this position. +                    *plQValue = 1000;
+                    if (pos)
+                    {
+                        *plQValue = (INT32) m_pLanguagePreferenceQList->GetAt(pos);
+                    }
+                }
+                else
+                {
+                    // We don't have a q-list, so just return 1000 (1.0)
+                    // for the q-value
+                    *plQValue = 1000;
+                }
+            }
+
 	    break;
 	}
 	pLangFrag = strtok(NULL, ",");
@@ -20264,11 +20400,51 @@
 	return rc;
     }
 
+    // Copy the switch's node list into a CHXSimpleList.
+    // We do not use a SMILNodeList here since when a 
+    // SMILNodeList destructs it deletes the nodes.
+    CHXSimpleList listNodeCopy;
+    LISTPOSITION pos = pNodeList->GetHeadPosition();
+    while (pos)
+    {
+        void* pEntry = pNodeList->GetNext(pos);
+        listNodeCopy.AddTail(pEntry);
+    }
+
+    // Does this switch element have allowReorder="yes"
+    HXBOOL bAllowReorder = FALSE;
+    if (pSwitchNode->m_pValues)
+    {
+        // Get the "allowReorder" attribute
+        IHXBuffer* pBuf = NULL;
+        HX_RESULT rv = pSwitchNode->m_pValues->GetPropertyCString("allowReorder", \
pBuf); +        if (SUCCEEDED(rv))
+        {
+            // Put this into a CHXString
+            CHXString strAllowReorder((const char*) pBuf->GetBuffer());
+            // Trim any whitespace
+            strAllowReorder.TrimLeft();
+            strAllowReorder.TrimRight();
+            // Is this equal to "yes"
+            if (strAllowReorder == "yes")
+            {
+                bAllowReorder = TRUE;
+            }
+        }
+        HX_RELEASE(pBuf);
+    }
+    // Are we supposed to re-order the node list?
+    if (bAllowReorder)
+    {
+        // Re-order the nodes according to user preference
+        ProcessSwitchReOrdering(&listNodeCopy);
+    }
+
     SMILNode* pSelectedNode = 0;
     CHXSimpleList* pRejectedNodeList = new CHXSimpleList;
 
     CHXSimpleList::Iterator i;
-    for(i=pNodeList->Begin();i!=pNodeList->End();++i)
+    for(i = listNodeCopy.Begin(); i != listNodeCopy.End(); ++i)
     {
 	SMILNode* pNode = (SMILNode*)(*i);
 
@@ -20321,6 +20497,92 @@
     return rc;
 }
 
+HX_RESULT CSmilParser::ProcessSwitchReOrdering(CHXSimpleList* pList)
+{
+    HX_RESULT retVal = HXR_FAIL;
+
+    if (pList && !pList->IsEmpty())
+    {
+        // When a switch has allowReorder="yes", then it means we can
+        // feel free to re-order the switch's children to provide
+        // the best user experience. The only system test that we
+        // currently have enough information in order to be able to 
+        // re-order is systemLanguage, where we may have a prioritized
+        // ranking of languages. So if the switch is not on systemLanguage,
+        // then we don't re-order at all.
+        //
+        // Does this switch use systemLanguage?
+        if (DoesSwitchNodeUseSystemLanguage(pList))
+        {
+            // Copy each node into the re-ordered list and
+            // assign a sort value to each one. The sort value
+            // will be the q-value from the language preference list.
+            LISTPOSITION pos = pList->GetHeadPosition();
+            while (pos)
+            {
+                SMILNode* pChildNode = (SMILNode*) pList->GetNext(pos);
+                if (pChildNode)
+                {
+                    // Init the sorting value
+                    INT32 lSortValue = 0;
+                    // Do we have attributes?
+                    if (pChildNode->m_pValues)
+                    {
+                        // Get the systemLanguage attribute
+                        IHXBuffer* pValue     = NULL;
+                        HX_RESULT rv = \
pChildNode->m_pValues->GetPropertyCString("systemLanguage", pValue); +                \
if (SUCCEEDED(rv)) +                        {
+                            // Is this language in the language preference list?
+                            inLanguagePreference((const char*) pValue->GetBuffer(), \
&lSortValue); +                        }
+                        HX_RELEASE(pValue);
+                    }
+                    // Set the sort value into the node
+                    pChildNode->m_lSortValue = lSortValue;
+                }
+            }
+            // Now sort the re-ordered list
+            pList->InsertionSort(SMILNodeSortFuncINT32, TRUE);
+            // Clear the return value
+            retVal = HXR_OK;
+        }
+    }
+
+    return retVal;
+}
+
+HXBOOL CSmilParser::DoesSwitchNodeUseSystemLanguage(CHXSimpleList* pList)
+{
+    HXBOOL bRet = FALSE;
+
+    if (pList && !pList->IsEmpty())
+    {
+        LISTPOSITION pos = pList->GetHeadPosition();
+        while (pos)
+        {
+            SMILNode* pChild = (SMILNode*) pList->GetNext(pos);
+            if (pChild && pChild->m_pValues)
+            {
+                // Does the child have a systemLanguage attribute?
+                IHXBuffer* pBuf = NULL;
+                HX_RESULT rv = \
pChild->m_pValues->GetPropertyCString("systemLanguage", pBuf); +                if \
(SUCCEEDED(rv)) +                {
+                    bRet = TRUE;
+                }
+                HX_RELEASE(pBuf);
+                if (bRet)
+                {
+                    break;
+                }
+            }
+        }
+    }
+
+    return bRet;
+}
+
 HX_RESULT
 CSmilParser::markTestAttributeNodes(SMILNodeList* pNodeList)
 {
@@ -24753,6 +25015,55 @@
     return retVal;
 }
 
+HX_RESULT CSmilParser::parsePanZoom(const char* pszStr, REF(LayoutRect) rPanZoom)
+{
+    HX_RESULT retVal = HXR_FAIL;
+
+    if (pszStr)
+    {
+        // Copy the string into a CHXString
+        CHXString strPanZoom(pszStr);
+        // Find out how many fields we have if we
+        // tokenize the string with a comma as delimiter
+        UINT32 ulNumFields = strPanZoom.CountFields(',');
+        // If we don't have 4 fields, then we fail
+        if (ulNumFields == 4)
+        {
+            // Get the left field
+            CHXString strField = strPanZoom.NthField(',', 1);
+            retVal = parseRegionDimension((const char*) strField,
+                                          rPanZoom.m_dLeft,
+                                          rPanZoom.m_eLeftType);
+            if (SUCCEEDED(retVal))
+            {
+                // Get the top field
+                strField = strPanZoom.NthField(',', 2);
+                retVal = parseRegionDimension((const char*) strField,
+                                              rPanZoom.m_dTop,
+                                              rPanZoom.m_eTopType);
+                if (SUCCEEDED(retVal))
+                {
+                    // Get the width field
+                    strField = strPanZoom.NthField(',', 3);
+                    retVal = parseRegionDimension((const char*) strField,
+                                                  rPanZoom.m_dWidth,
+                                                  rPanZoom.m_eWidthType);
+                    if (SUCCEEDED(retVal))
+                    {
+                        // Get the height field
+                        strField = strPanZoom.NthField(',', 4);
+                        retVal = parseRegionDimension((const char*) strField,
+                                                      rPanZoom.m_dHeight,
+                                                      rPanZoom.m_eHeightType);
+                    }
+                }
+            }
+        }
+    }
+
+    return retVal;
+}
+
 HX_RESULT CSmilParser::parseZIndex(const char*   pszStr,
                                    REF(INT32)    rlValue,
                                    REF(CSS2Type) reType)
@@ -28258,6 +28569,7 @@
     m_pNamespaceList(NULL),
     m_pContentList(NULL),
     m_eElement(NumSMIL2Elements),
+    m_lSortValue(0),
     m_bLastInGroup(FALSE),
     m_bDelete(FALSE),
     m_bSkipContent(FALSE),
@@ -28509,3 +28821,19 @@
     }
     return pNewList;
 }
+
+int SMILNodeSortFuncINT32(void* pValue1, void* pValue2)
+{
+    int iRet = 0;
+
+    if (pValue1 && pValue2)
+    {
+        // Cast to SMILNode
+        SMILNode* pNode1 = (SMILNode*) pValue1;
+        SMILNode* pNode2 = (SMILNode*) pValue2;
+        // The return value will be the difference in the sort values
+        iRet = pNode1->m_lSortValue - pNode2->m_lSortValue;
+    }
+
+    return iRet;
+}

Index: sitewatc.cpp
===================================================================
RCS file: /cvsroot/datatype/smil/renderer/smil2/sitewatc.cpp,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- sitewatc.cpp	6 Jul 2007 22:01:52 -0000	1.8
+++ sitewatc.cpp	4 Dec 2007 21:33:41 -0000	1.9
@@ -99,7 +99,7 @@
 
 CSmilSiteWatcher::CSmilSiteWatcher(CSmilDocumentRenderer* pDoc,
                                    const char*            pID,
-                                   HXBOOL                   bIsChildSite,
+                                   HXBOOL                 bIsChildSite,
                                    const char*            pSourceID) :
     m_id(pID),
     m_SourceID(pSourceID)
@@ -108,6 +108,7 @@
     m_lRefCount              = 0;
     m_pDoc                   = pDoc;
     m_pSite                  = NULL;
+    m_pSite3                 = NULL;
     m_Rect.m_dLeft           = 0.0;
     m_Rect.m_eLeftType       = CSS2TypeAuto;
     m_Rect.m_dTop            = 0.0;
@@ -139,6 +140,8 @@
     m_bFirstSizeChange       = TRUE;
     m_bMediaSizeSet          = FALSE;
     m_bMediaIsBrush          = FALSE;
+    // Set the panZoom rect to default
+    CSmilSource::SetPanZoomToDefault(m_PanZoomRect);
     // Initialize the RegPoint
     if(m_pDoc)
     {
@@ -158,6 +161,8 @@
             // positioning rect which was specified on the
             // media element (i.e. - <img ... left="20" .../>)
             m_Rect = pSource->m_Rect;
+            // Copy the panZoom rect
+            m_PanZoomRect = pSource->m_PanZoomRect;
             // Get the regPoint
             if (pSource->m_bRegPointIsPredef)
             {
@@ -282,6 +287,7 @@
 {
     HX_RELEASE(m_pDoc);
     HX_RELEASE(m_pSite);
+    HX_RELEASE(m_pSite3);
 
     return HXR_OK;
 }
@@ -351,7 +357,11 @@
     m_pSite = pSite;
     if(m_pSite)
     {
+        // AddRef the site
         m_pSite->AddRef();
+        // QI the site for IHXSite3
+        HX_RELEASE(m_pSite3);
+        m_pSite->QueryInterface(IID_IHXSite3, (void**) &m_pSite3);
     }
 
     return retVal;
@@ -359,6 +369,7 @@
 
 STDMETHODIMP CSmilSiteWatcher::DetachSite()
 {
+    HX_RELEASE(m_pSite3);
     HX_RELEASE(m_pSite);
 
     return HXR_OK;
@@ -428,15 +439,41 @@
             // in the coordinate space of the region's PARENT,
             // and not the region's rect itself.
             HXxRect  cMediaRect = {0, 0, 0, 0};
+            HXxRect  cClipRect  = {0, 0, 0, 0};
             retVal = m_pDoc->computeMediaLayout(cSubRegionRect,
                                                 m_eFit,
                                                 cRegPoint,
                                                 m_RegPoint.m_eRegAlign,
                                                 m_MediaSize,
+                                                m_PanZoomRect,
+                                                m_bMediaIsBrush,
                                                 cMediaRect,
-                                                m_bMediaIsBrush);
+                                                cClipRect);
             if (SUCCEEDED(retVal))
             {
+                // Determine if we actually need the clipRect. Most of
+                // the time the clipping can simply be taken care of
+                // by the region site. However, in some cases of panZoom,
+                // we need to clip further than the parent will clip.
+                HXBOOL bClipRectNeeded = FALSE;
+                if (!HXxRect_IsEmpty(cClipRect) && (cMediaRect != cClipRect))
+                {
+                    // We need to intersect the region's rect with the
+                    // media rect. This will give us the clip rect that
+                    // the region itself will do automatically. If the
+                    // clipRect is within that rect, then we actually
+                    // do need to apply the clip rect to the site.
+                    HXxRect rectRegionClip = {0, 0, 0, 0};
+                    HXxRect_Intersection(cRect, cMediaRect, &rectRegionClip);
+                    // Is this intersetion the same as the clipRect?
+                    if (rectRegionClip != cClipRect)
+                    {
+                        // The determined clipRect is different than the
+                        // clipping that the region will do automatically,
+                        // so we need to use it.
+                        bClipRectNeeded = TRUE;
+                    }
+                }
                 // Now since the calculation of the media size was
                 // done in the space of the region's PARENT, then
                 // and we need to set the size of the media in the
@@ -447,9 +484,33 @@
                 cMediaRect.top    -= cRect.top;
                 cMediaRect.right  -= cRect.left;
                 cMediaRect.bottom -= cRect.top;
+                // Offset the clipRect as well
+                cClipRect.left   -= cRect.left;
+                cClipRect.top    -= cRect.top;
+                cClipRect.right  -= cRect.left;
+                cClipRect.bottom -= cRect.top;
                 // Now we can assign the new position
                 newPos.x = cMediaRect.left;
                 newPos.y = cMediaRect.top;
+                // Do we need to set the site's clipRect?
+                HXxRect rectSiteClip = cClipRect;
+                if (bClipRectNeeded)
+                {
+                    // The clipRect that we pass into IHXSite3::SetClipRect()
+                    // should be in the site's coordinate space. That is,
+                    // we call the upper-left corner of the site (0,0)
+                    // and the lower-right corner (width,height) and 
+                    // the clipRect should be within that rectangle.
+                    // Right now, cClipRect is in the coordinate system
+                    // of the site's parent, which is the region.
+                    // So we need to subtract off the position of our
+                    // site. Remember to use the new position we 
+                    // just calculated.
+                    rectSiteClip.left   -= newPos.x;
+                    rectSiteClip.top    -= newPos.y;
+                    rectSiteClip.right  -= newPos.x;
+                    rectSiteClip.bottom -= newPos.y;
+                }
                 // If we have a resize behavior of Zoom, then
                 // we compute everything off of the original root-layout
                 // size, and then simply scale by the zoom factors.
@@ -457,8 +518,24 @@
                      m_dZoomScaleFactorY != 1.0) &&
                     m_eResizeBehavior == ResizeZoom)
                 {
+                    // Scale the new position
                     newPos.x = (INT32) floor(m_dZoomScaleFactorX * ((double) \
                newPos.x) + 0.5);
                     newPos.y = (INT32) floor(m_dZoomScaleFactorY * ((double) \
newPos.y) + 0.5); +                    // Are we using a site clip rect?
+                    if (bClipRectNeeded)
+                    {
+                        // Scale the site clip rect
+                        rectSiteClip.left   = (INT32) floor(m_dZoomScaleFactorX * \
((double) rectSiteClip.left) + 0.5); +                        rectSiteClip.top    = \
(INT32) floor(m_dZoomScaleFactorY * ((double) rectSiteClip.top) + 0.5); +             \
rectSiteClip.right  = (INT32) floor(m_dZoomScaleFactorX * ((double) \
rectSiteClip.right) + 0.5); +                        rectSiteClip.bottom = (INT32) \
floor(m_dZoomScaleFactorY * ((double) rectSiteClip.bottom) + 0.5); +                  \
} +                }
+                // Are we using a site clip rect?
+                if (bClipRectNeeded && m_pSite3)
+                {
+                    // Set the clip rect into the site
+                    m_pSite3->SetClipRect(rectSiteClip);
                 }
             }
         }
@@ -580,15 +657,41 @@
             // in the coordinate space of the region's PARENT,
             // and not the region's rect itself.
             HXxRect  cMediaRect = {0, 0, 0, 0};
+            HXxRect  cClipRect  = {0, 0, 0, 0};
             retVal = m_pDoc->computeMediaLayout(cSubRegionRect,
                                                 m_eFit,
                                                 cRegPoint,
                                                 m_RegPoint.m_eRegAlign,
                                                 m_MediaSize,
+                                                m_PanZoomRect,
+                                                m_bMediaIsBrush,
                                                 cMediaRect,
-                                                m_bMediaIsBrush);
+                                                cClipRect);
             if (SUCCEEDED(retVal))
             {
+                // Determine if we actually need the clipRect. Most of
+                // the time the clipping can simply be taken care of
+                // by the region site. However, in some cases of panZoom,
+                // we need to clip further than the parent will clip.
+                HXBOOL bClipRectNeeded = FALSE;
+                if (!HXxRect_IsEmpty(cClipRect) && (cMediaRect != cClipRect))
+                {
+                    // We need to intersect the region's rect with the
+                    // media rect. This will give us the clip rect that
+                    // the region itself will do automatically. If the
+                    // clipRect is within that rect, then we actually
+                    // do need to apply the clip rect to the site.
+                    HXxRect rectRegionClip = {0, 0, 0, 0};
+                    HXxRect_Intersection(cRect, cMediaRect, &rectRegionClip);
+                    // Is this intersetion the same as the clipRect?
+                    if (rectRegionClip != cClipRect)
+                    {
+                        // The determined clipRect is different than the
+                        // clipping that the region will do automatically,
+                        // so we need to use it.
+                        bClipRectNeeded = TRUE;
+                    }
+                }
                 // Now since the calculation of the media size was
                 // done in the space of the region's PARENT, then
                 // and we need to set the size of the media in the
@@ -599,10 +702,34 @@
                 cMediaRect.top    -= cRect.top;
                 cMediaRect.right  -= cRect.left;
                 cMediaRect.bottom -= cRect.top;
+                // Offset the clipRect as well
+                cClipRect.left   -= cRect.left;
+                cClipRect.top    -= cRect.top;
+                cClipRect.right  -= cRect.left;
+                cClipRect.bottom -= cRect.top;
                 // So now the new width and height
                 // can be calculated.
                 newSize.cx = HXxRECT_WIDTH(cMediaRect);
                 newSize.cy = HXxRECT_HEIGHT(cMediaRect);
+                // Do we need to set the site's clipRect?
+                HXxRect rectSiteClip = cClipRect;
+                if (bClipRectNeeded)
+                {
+                    // The clipRect that we pass into IHXSite3::SetClipRect()
+                    // should be in the site's coordinate space. That is,
+                    // we call the upper-left corner of the site (0,0)
+                    // and the lower-right corner (width,height) and 
+                    // the clipRect should be within that rectangle.
+                    // Right now, cClipRect is in the coordinate system
+                    // of the site's parent, which is the region.
+                    // So we need to subtract off the position of our
+                    // site. Remember to use the new position we 
+                    // just calculated.
+                    rectSiteClip.left   -= cMediaRect.left;
+                    rectSiteClip.top    -= cMediaRect.top;
+                    rectSiteClip.right  -= cMediaRect.left;
+                    rectSiteClip.bottom -= cMediaRect.top;
+                }
                 // If we have a resize behavior of Zoom, then
                 // we compute everything off of the original root-layout
                 // size, and then simply scale by the zoom factors.
@@ -610,8 +737,24 @@
                      m_dZoomScaleFactorY != 1.0) &&
                     m_eResizeBehavior == ResizeZoom)
                 {
+                    // Scale the new size
                     newSize.cx = (INT32) floor(m_dZoomScaleFactorX * ((double) \
                newSize.cx) + 0.5);
                     newSize.cy = (INT32) floor(m_dZoomScaleFactorY * ((double) \
newSize.cy) + 0.5); +                    // Are we using a site clip rect?
+                    if (bClipRectNeeded)
+                    {
+                        // Scale the site clip rect
+                        rectSiteClip.left   = (INT32) floor(m_dZoomScaleFactorX * \
((double) rectSiteClip.left) + 0.5); +                        rectSiteClip.top    = \
(INT32) floor(m_dZoomScaleFactorY * ((double) rectSiteClip.top) + 0.5); +             \
rectSiteClip.right  = (INT32) floor(m_dZoomScaleFactorX * ((double) \
rectSiteClip.right) + 0.5); +                        rectSiteClip.bottom = (INT32) \
floor(m_dZoomScaleFactorY * ((double) rectSiteClip.bottom) + 0.5); +                  \
} +                }
+                // Are we using a site clip rect?
+                if (bClipRectNeeded && m_pSite3)
+                {
+                    // Set the clip rect into the site
+                    m_pSite3->SetClipRect(rectSiteClip);
                 }
                 // Set the current media size to this value
                 // XXXMEH - TODO is this actually used anywhere? We

Index: smldoc.cpp
===================================================================
RCS file: /cvsroot/datatype/smil/renderer/smil2/smldoc.cpp,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -d -r1.46 -r1.47
--- smldoc.cpp	21 Nov 2007 20:01:41 -0000	1.46
+++ smldoc.cpp	4 Dec 2007 21:33:41 -0000	1.47
@@ -10477,7 +10477,7 @@
             pRegion->addRendererSiteChild(pRendererSite);
             // Add to the media id to site map
             addRendererSiteToMap((const char*) pPlayToAssoc->m_id,
-                                 pRendererSite);
+                                pRendererSite);
             // Now create a site watcher for this renderer site
             CSmilSiteWatcher* pRendererWatch = new CSmilSiteWatcher(this,
                                                                     \
pRegion->m_region, @@ -10514,7 +10514,7 @@
                     {
                         // Add the site watcher to the site watcher map
                         m_pSiteWatcherMap->SetAt((void*) pRendererSite,
-                                                 (void*) pRendererWatch);
+                                                (void*) pRendererWatch);
                         // Add to the media id to site watcher map
                         addRendererSiteWatcherToMap((const char*) \
pPlayToAssoc->m_id,  pRendererWatch);
@@ -10535,8 +10535,8 @@
 
                         // Set "channel" in the site's properties
                         retVal = setSiteProperty(pRendererSite,
-                                                 "channel",
-                                                 pSMILSourceInfo->m_childTunerName);
+                                                "channel",
+                                                pSMILSourceInfo->m_childTunerName);
                         if (SUCCEEDED(retVal))
                         {
 //                            setSiteProperty(pRendererSite,
@@ -10567,15 +10567,15 @@
 
                                 CSmilShowSiteEvent* pShowEvent =
                                     new \
                CSmilShowSiteEvent(pPlayToAssoc->m_uGroupIndex,
-                                                           ulShowTime,
-                                                           pRendererSite,
-                                                           pRegion->m_pSite,
-                                                           TRUE,
-                                                           FALSE,
-                                                           this,
-                                                           pPlayToAssoc->m_id,
-                                                           pRegion->m_region,
-                                                           \
pRegion->m_eShowBackground); +                                                        \
ulShowTime, +                                                        pRendererSite,
+                                                        pRegion->m_pSite,
+                                                        TRUE,
+                                                        FALSE,
+                                                        this,
+                                                        pPlayToAssoc->m_id,
+                                                        pRegion->m_region,
+                                                        pRegion->m_eShowBackground);
                                 insertEvent(pShowEvent);
 
                                 // Compute the time at which to remove the element. \
Here @@ -10622,15 +10622,15 @@
                                 {
                                     CSmilShowSiteEvent* pHideEvent =
                                         new \
                CSmilShowSiteEvent(pPlayToAssoc->m_uGroupIndex,
-                                                               ulRemoveTime,
-                                                               pRendererSite,
-                                                               pRegion->m_pSite,
-                                                               FALSE,
-                                                               bIgnorHide,
-                                                               this,
-                                                               pPlayToAssoc->m_id,
-                                                               pRegion->m_region,
-                                                               \
pRegion->m_eShowBackground); +                                                        \
ulRemoveTime, +                                                            \
pRendererSite, +                                                            \
pRegion->m_pSite, +                                                            FALSE,
+                                                            bIgnorHide,
+                                                            this,
+                                                            pPlayToAssoc->m_id,
+                                                            pRegion->m_region,
+                                                            \
pRegion->m_eShowBackground);  insertEvent(pHideEvent);
                                     // Set the event time into the element
                                     setElementRemoveTime(pPlayToAssoc->m_id, \
ulRemoveTime); @@ -10642,7 +10642,7 @@
                                 pSiteInfo->m_uGroupIndex    = \
                pPlayToAssoc->m_uGroupIndex;
                                 pSiteInfo->m_ulDelay        = \
                pSMILSourceInfo->m_ulDelay;
                                 pSiteInfo->m_ulDuration     = \
                pSMILSourceInfo->m_ulDuration +
-                                                              \
pSMILSourceInfo->m_ulDelay; +                                                         \
pSMILSourceInfo->m_ulDelay;  pSiteInfo->m_ulResumeTime   = 0;
                                 pSiteInfo->m_bRemoveSite    = \
pPlayToAssoc->m_bRemoveSite;  pSiteInfo->m_bNoRegion      = bNoRegion;
@@ -10673,14 +10673,14 @@
                                     if (pSrc->m_bBackgroundOpacitySpecified)
                                     {
                                         setSitePropertyULONG32(pRendererSite,
-                                                               "backgroundOpacity",
-                                                               \
pSrc->m_ulBackgroundOpacity); +                                                       \
"backgroundOpacity", +                                                            \
pSrc->m_ulBackgroundOpacity);  }
                                     if (pSrc->m_bMediaOpacitySpecified)
                                     {
                                         setSitePropertyULONG32(pRendererSite,
-                                                               "mediaOpacity",
-                                                               \
pSrc->m_ulMediaOpacity); +                                                            \
"mediaOpacity", +                                                            \
pSrc->m_ulMediaOpacity);  }
                                 }
 
@@ -10690,10 +10690,10 @@
                                 {
                                     // Create a begin transition event
                                     CSmilTransitionEvent* pTransEvent = new \
                CSmilTransitionEvent(pSMILSourceInfo->m_ulDelay,
-                                                                                     \
                pPlayToAssoc,
-                                                                                     \
                pSiteInfo,
-                                                                                     \
                TRUE,
-                                                                                     \
this); +                                                                              \
pPlayToAssoc, +                                                                       \
pSiteInfo, +                                                                          \
TRUE, +                                                                               \
                this);
                                     // Insert this event in the event queue
                                     insertEvent(pTransEvent);
 
@@ -10707,12 +10707,12 @@
                                     {
                                         CSmilTransitionEvent* pTransEvent =
                                             new \
                CSmilTransitionEvent(pSMILSourceInfo->m_ulDelay +
-                                                                     \
                pSMILSourceInfo->m_ulDuration -
-                                                                     \
                pTInfo->m_pTrans->m_ulDuration,
-                                                                     pPlayToAssoc,
-                                                                     pSiteInfo,
-                                                                     FALSE,
-                                                                     this);
+                                                                    \
pSMILSourceInfo->m_ulDuration - +                                                     \
pTInfo->m_pTrans->m_ulDuration, +                                                     \
pPlayToAssoc, +                                                                    \
pSiteInfo, +                                                                    \
FALSE, +                                                                    this);
                                         insertEvent(pTransEvent);
                                     }
                                 }
@@ -13051,6 +13051,57 @@
                     HX_RELEASE(pRendererSite);
                 }
             }
+            else if (ulAttr == kAttrNamePanZoom)
+            {
+                // Get the source
+                CSmilSource* pSource = getSource(pszID);
+                if (pSource)
+                {
+                    // Set a LayoutRect to default values
+                    LayoutRect cPanZoom;
+                    CSmilSource::SetPanZoomToDefault(cPanZoom);
+                    // Set the values of the LayoutRect from the animation value
+                    cPanZoom.m_dLeft       = pValue->GetValueDouble(0);
+                    cPanZoom.m_eLeftType   = pValue->GetCSS2Type(0);
+                    cPanZoom.m_dTop        = pValue->GetValueDouble(1);
+                    cPanZoom.m_eTopType    = pValue->GetCSS2Type(1);
+                    cPanZoom.m_dWidth      = pValue->GetValueDouble(2);
+                    cPanZoom.m_eWidthType  = pValue->GetCSS2Type(2);
+                    cPanZoom.m_dHeight     = pValue->GetValueDouble(3);
+                    cPanZoom.m_eHeightType = pValue->GetCSS2Type(3);
+                    // XXXMEH - animation optimization
+                    // We will go ahead and copy the new values to the site
+                    // watcher, although it would be more efficient to collect
+                    // the changes to the end and execute them together.
+                    CSmilSiteWatcher* pWatcher = getRendererSiteWatcher(pszID);
+                    if (pWatcher)
+                    {
+                        // Set the panZoom rect into the site watcher
+                        pWatcher->SetPanZoomRect(cPanZoom);
+                        // Get the renderer site
+                        IHXSite* pSite = NULL;
+                        getRendererSite(pszID, pSite);
+                        if (pSite)
+                        {
+                            // Re-position the site. It doesn't matter what
+                            // position we pass in, because the site watcher's
+                            // ChangingPosition() method will override it.
+                            HXxPoint cPos = {1, 1};
+                            pSite->SetPosition(cPos);
+                            // Re-size the site. It doesn't matter what
+                            // size we pass in, because the site watcher's
+                            // ChangingSize() method will override it.
+                            HXxSize cSize = {1, 1};
+                            pSite->SetSize(cSize);
+                        }
+                        HX_RELEASE(pSite);
+                    }
+                }
+                else
+                {
+                    retVal = HXR_FAIL;
+                }
+            }
         }
         else if (eTag == SMILRootLayout)
         {
@@ -16473,13 +16524,15 @@
     }
 }
 
-HX_RESULT CSmilDocumentRenderer::computeMediaLayout(HXxRect      cRegionRect,
-                                                    Fit          eFit,
-                                                    HXxPoint     cRegPoint,
-                                                    RegAlign     eRegAlign,
-                                                    HXxSize      cMediaSize,
-                                                    REF(HXxRect) rcMediaRect,
-                                                    HXBOOL         bMediaIsBrush)
+HX_RESULT CSmilDocumentRenderer::computeMediaLayout(HXxRect         cRegionRect,
+                                                    Fit             eFit,
+                                                    HXxPoint        cRegPoint,
+                                                    RegAlign        eRegAlign,
+                                                    HXxSize         cMediaSize,
+                                                    REF(LayoutRect) rPanZoomRect,
+                                                    HXBOOL          bMediaIsBrush,
+                                                    REF(HXxRect)    rcMediaRect,
+                                                    REF(HXxRect)    rcClipRect)
 {
     HX_RESULT retVal = HXR_OK;
 
@@ -16493,6 +16546,47 @@
         {
             eFit = FitFill;
         }
+        // Is the panZoom rect being used?
+        HXBOOL bUsePanZoom = (CSmilSource::IsPanZoomDefault(rPanZoomRect) ? FALSE : \
TRUE); +        // If we are using panZoom, then the "media size" is actually
+        // the panZoom width and height, not the actual media size.
+        // So save the media size, since if we are using panZoom,
+        // we will overwrite it with the panZoom size.
+        HXxSize sizeMedia      = cMediaSize;
+        double  dPanZoomX      = 0.0;
+        double  dPanZoomY      = 0.0;
+        double  dPanZoomWidth  = 0.0;
+        double  dPanZoomHeight = 0.0;
+        if (bUsePanZoom)
+        {
+            // Compute the panZoom x
+            dPanZoomX = rPanZoomRect.m_dLeft;
+            if (rPanZoomRect.m_eLeftType == CSS2TypePercentage)
+            {
+                dPanZoomX = ((double) cMediaSize.cx) * dPanZoomX / 100.0;
+            }
+            // Compute the panZoom y
+            dPanZoomY = rPanZoomRect.m_dTop;
+            if (rPanZoomRect.m_eTopType == CSS2TypePercentage)
+            {
+                dPanZoomY = ((double) cMediaSize.cy) * dPanZoomY / 100.0;
+            }
+            // Compute the panZoom width
+            dPanZoomWidth = rPanZoomRect.m_dWidth;
+            if (rPanZoomRect.m_eWidthType == CSS2TypePercentage)
+            {
+                dPanZoomWidth = ((double) cMediaSize.cx) * dPanZoomWidth / 100.0;
+            }
+            // Compute the panZoom height
+            dPanZoomHeight = rPanZoomRect.m_dHeight;
+            if (rPanZoomRect.m_eHeightType == CSS2TypePercentage)
+            {
+                dPanZoomHeight = ((double) cMediaSize.cy) * dPanZoomHeight / 100.0;
+            }
+            // Round to nearest integers
+            cMediaSize.cx = (UINT32) (dPanZoomWidth + 0.5);
+            cMediaSize.cy = (UINT32) (dPanZoomHeight + 0.5);
+        }
         // Switch based on fit
         switch (eFit)
         {
@@ -16895,6 +16989,45 @@
                     }
                 }
                 break;
+        } // switch (eFit)
+        // Are we using panZoom?
+        if (bUsePanZoom)
+        {
+            // Get the media rect scales
+            double dScaleX = 1.0;
+            if (dPanZoomWidth != 0.0)
+            {
+                dScaleX = ((double) HXxRECT_WIDTH(rcMediaRect)) / dPanZoomWidth;
+            }
+            double dScaleY = 1.0;
+            if (dPanZoomHeight != 0.0)
+            {
+                dScaleY = ((double) HXxRECT_HEIGHT(rcMediaRect)) / dPanZoomHeight;
+            }
+            // Save the original mediaRect computed above
+            HXxRect cOrigMediaRect = rcMediaRect;
+            // If we are using panZoom, then rcMediaRect now contains the
+            // location of the panZoom rect in the region parent's coordinate
+            // system. So then we need to compute the rectangle of the actual
+            // media instead of the panZoom subrect of that media.
+            double dMediaX = ((double) rcMediaRect.left) - dPanZoomX * dScaleX;
+            double dMediaY = ((double) rcMediaRect.top)  - dPanZoomY * dScaleY;
+            double dMediaW = ((double) sizeMedia.cx) * dScaleX;
+            double dMediaH = ((double) sizeMedia.cy) * dScaleY;
+            // Round to the nearest integer
+            rcMediaRect.left   = (UINT32) (dMediaX);
+            rcMediaRect.top    = (UINT32) (dMediaY);
+            rcMediaRect.right  = (UINT32) (dMediaX + dMediaW);
+            rcMediaRect.bottom = (UINT32) (dMediaY + dMediaH);
+            // The clipRect is the mediaRect that we computed above intersected
+            // with the new mediaRect we have now.
+            HXxRect_Intersection(cOrigMediaRect, rcMediaRect, &rcClipRect);
+        }
+        else
+        {
+            // We are not using panZoom, so just set the clipRect to
+            // the same as the mediaRect
+            rcClipRect = rcMediaRect;
         }
     }
     else

Index: animattr.cpp
===================================================================
RCS file: /cvsroot/datatype/smil/renderer/smil2/animattr.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- animattr.cpp	6 Jul 2007 22:01:52 -0000	1.4
+++ animattr.cpp	4 Dec 2007 21:33:41 -0000	1.5
@@ -65,6 +65,7 @@
 #include "hxxmlprs.h"
 // rmasmil
 #include "smlparse.h"
+#include "smlelem.h"
 #include "animattr.h"
 
 CAttr::CAttr(UINT32 ulAttrName, const char* pszStr)
@@ -225,6 +226,29 @@
             }
         }
     }
+    else if (m_ulAttrName == kAttrNamePanZoom)
+    {
+        m_ulAttrType = kAttrTypeRealVector;
+        if (pszStr)
+        {
+            // Set a LayoutRect to its default values
+            LayoutRect cPanZoom;
+            CSmilSource::SetPanZoomToDefault(cPanZoom);
+            // Parse the panZoom value
+            m_lLastError = CSmilParser::parsePanZoom(pszStr, cPanZoom);
+            if (SUCCEEDED(m_lLastError))
+            {
+                m_dValue[0] = cPanZoom.m_dLeft;
+                m_eType[0]  = cPanZoom.m_eLeftType;
+                m_dValue[1] = cPanZoom.m_dTop;
+                m_eType[1]  = cPanZoom.m_eTopType;
+                m_dValue[2] = cPanZoom.m_dWidth;
+                m_eType[2]  = cPanZoom.m_eWidthType;
+                m_dValue[3] = cPanZoom.m_dHeight;
+                m_eType[3]  = cPanZoom.m_eHeightType;
+            }
+        }
+    }
 }
 
 CAttr::CAttr(UINT32 ulAttrName,


_______________________________________________
Datatype-cvs mailing list
Datatype-cvs@helixcommunity.org
http://lists.helixcommunity.org/mailman/listinfo/datatype-cvs


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic