sitewatc.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:27k
- /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: sitewatc.cpp,v 1.2.12.2 2004/07/13 18:31:00 bobclark Exp $
- *
- * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file,
- * are subject to the current version of the RealNetworks Public
- * Source License (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the current version of the RealNetworks Community
- * Source License (the "RCSL") available at
- * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
- * will apply. You may also obtain the license terms directly from
- * RealNetworks. You may not use this file except in compliance with
- * the RPSL or, if you have a valid RCSL with RealNetworks applicable
- * to this file, the RCSL. Please see the applicable RPSL or RCSL for
- * the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL") in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your version of
- * this file only under the terms of the GPL, and not to allow others
- * to use your version of this file under the terms of either the RPSL
- * or RCSL, indicate your decision by deleting the provisions above
- * and replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient may
- * use your version of this file under the terms of any one of the
- * RPSL, the RCSL or the GPL.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the
- * portions it created.
- *
- * This file, and the files included with this file, is distributed
- * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
- * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
- * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
- * ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- // system
- #include <math.h>
- #include <time.h> // smlparse.h dependency
- // include
- #include "hxtypes.h"
- #include "hxwintyp.h"
- #include "hxcom.h"
- #include "hxwin.h"
- #include "smiltype.h"
- #include "hxengin.h"
- #include "hxcore.h" // smldoc.h dependency
- #include "hxgroup.h" // smldoc.h dependency
- #include "hxsite2.h" // smldoc.h dependency
- #include "ihxpckts.h" // smldoc.h dependency
- #include "hxvport.h" // smldoc.h dependency
- #include "hxclsnk.h" // smldoc.h dependency
- #include "hxmmrkr.h" // smldoc.h dependency
- #include "hxinter.h" // smldoc.h dependency
- #include "hxxml.h" // smlparse.h dependency
- #include "hxerror.h"
- // pnmisc
- #include "hxwinver.h" // smlparse.h dependency
- #include "hxtick.h"
- // pncont
- #include "hxstring.h"
- #include "hxmap.h"
- #include "hxslist.h"
- // rnxmllib
- #include "hxxmlprs.h" // smlparse.h dependency
- // rmasmil
- #include "smlelem.h"
- #include "smlparse.h"
- // smlrendr
- #include "evnthook.h" // smldoc.h dependency
- #include "siteuser.h" // smldoc.h dependency
- #include "passivsw.h" // smldoc.h dependency
- #include "layout.h"
- #include "smldoc.h"
- #include "sitewatc.h"
- // pndebug
- #include "smlrmlog.h"
- #include "hxheap.h"
- #ifdef _DEBUG
- #undef HX_THIS_FILE
- static const char HX_THIS_FILE[] = __FILE__;
- #endif
- CSmilSiteWatcher::CSmilSiteWatcher(CSmilDocumentRenderer* pDoc,
- const char* pID,
- BOOL bIsChildSite,
- const char* pSourceID) :
- m_id(pID),
- m_SourceID(pSourceID)
- {
- // Initialize the members
- m_lRefCount = 0;
- m_pDoc = pDoc;
- m_pSite = NULL;
- m_Rect.m_dLeft = 0.0;
- m_Rect.m_eLeftType = CSS2TypeAuto;
- m_Rect.m_dTop = 0.0;
- m_Rect.m_eTopType = CSS2TypeAuto;
- m_Rect.m_dRight = 0.0;
- m_Rect.m_eRightType = CSS2TypeAuto;
- m_Rect.m_dBottom = 0.0;
- m_Rect.m_eBottomType = CSS2TypeAuto;
- m_Rect.m_dWidth = 0.0;
- m_Rect.m_eWidthType = CSS2TypeAuto;
- m_Rect.m_dHeight = 0.0;
- m_Rect.m_eHeightType = CSS2TypeAuto;
- m_RegPoint.m_dLeft = 0.0;
- m_RegPoint.m_eLeftType = CSS2TypeAuto;
- m_RegPoint.m_dTop = 0.0;
- m_RegPoint.m_eTopType = CSS2TypeAuto;
- m_RegPoint.m_dRight = 0.0;
- m_RegPoint.m_eRightType = CSS2TypeAuto;
- m_RegPoint.m_dBottom = 0.0;
- m_RegPoint.m_eBottomType = CSS2TypeAuto;
- m_RegPoint.m_eRegAlign = RegAlignTopLeft;
- m_MediaSize.cx = 0;
- m_MediaSize.cy = 0;
- m_eResizeBehavior = ResizeZoom;
- m_dZoomScaleFactorX = 1.0;
- m_dZoomScaleFactorY = 1.0;
- m_bIsChildSite = bIsChildSite;
- m_bChangingSize = FALSE;
- m_bFirstSizeChange = TRUE;
- m_bMediaSizeSet = FALSE;
- m_bMediaIsBrush = FALSE;
- // Initialize the RegPoint
- if(m_pDoc)
- {
- m_pDoc->AddRef();
- // RegPoints can come from two places - they can
- // either be idrefs or they can be predefined
- CSmilSource* pSource = m_pDoc->getSource(pSourceID);
- if (pSource)
- {
- // Check if this is a <brush>
- if (pSource->m_pNode &&
- pSource->m_pNode->m_tag == SMILBrush)
- {
- m_bMediaIsBrush = TRUE;
- }
- // Copy the Layout rect. This is the subregion
- // positioning rect which was specified on the
- // media element (i.e. - <img ... left="20" .../>)
- m_Rect = pSource->m_Rect;
- // Get the regPoint
- if (pSource->m_bRegPointIsPredef)
- {
- // Since the regPoint is predefined, then
- // there is no regAlign from the <regPoint>.
- // Therefore, we need to use the regAlign
- // that was specified with the source
- m_RegPoint.m_eRegAlign = pSource->m_eRegAlign;
- // For predefined regPoints, they are always
- // expressed in percentages, not in absolute lengths
- m_RegPoint.m_eLeftType = CSS2TypePercentage;
- m_RegPoint.m_eTopType = CSS2TypePercentage;
- // Compute the regPoint
- switch (pSource->m_ePredefRegPoint)
- {
- case RegAlignTopLeft:
- {
- m_RegPoint.m_dLeft = 0.0;
- m_RegPoint.m_dTop = 0.0;
- }
- break;
- case RegAlignTopMid:
- {
- m_RegPoint.m_dLeft = 50.0;
- m_RegPoint.m_dTop = 0.0;
- }
- break;
- case RegAlignTopRight:
- {
- m_RegPoint.m_dLeft = 100.0;
- m_RegPoint.m_dTop = 0.0;
- }
- break;
- case RegAlignMidLeft:
- {
- m_RegPoint.m_dLeft = 0.0;
- m_RegPoint.m_dTop = 50.0;
- }
- break;
- case RegAlignCenter:
- {
- m_RegPoint.m_dLeft = 50.0;
- m_RegPoint.m_dTop = 50.0;
- }
- break;
- case RegAlignMidRight:
- {
- m_RegPoint.m_dLeft = 100.0;
- m_RegPoint.m_dTop = 50.0;
- }
- break;
- case RegAlignBottomLeft:
- {
- m_RegPoint.m_dLeft = 0.0;
- m_RegPoint.m_dTop = 100.0;
- }
- break;
- case RegAlignBottomMid:
- {
- m_RegPoint.m_dLeft = 50.0;
- m_RegPoint.m_dTop = 100.0;
- }
- break;
- case RegAlignBottomRight:
- {
- m_RegPoint.m_dLeft = 100.0;
- m_RegPoint.m_dTop = 100.0;
- }
- break;
- }
- }
- else
- {
- // The regPoint is not predefined, but rather
- // is an idref to a <regPoint> element. So look
- // up that element
- CSmilRegPoint* pRegPt = m_pDoc->getRegPoint(pSource->m_RegPoint);
- if (pRegPt)
- {
- // We simply need to copy the RegPoint struct
- // from the CSmilRegPoint element
- m_RegPoint = pRegPt->m_RegPoint;
- // <regPoint> elements have a default "regAlign"
- // attribute. However, the media object element
- // can override this regAlign value.
- if (pSource->m_bRegAlignSpecified)
- {
- // The media object element DID specify
- // a regAlign attribute, so this attribute
- // overrides the regAlign attribute in the
- // <regPoint> element.
- m_RegPoint.m_eRegAlign = pSource->m_eRegAlign;
- }
- }
- }
- // Now we can compute the fit attribute. The default
- // fit attribute is specified with the <region>. However,
- // the media object element can override this attribute.
- // So first we need to get the region.
- CSmilBasicRegion* pRegion = m_pDoc->getRegionByID(m_id);
- if (pRegion)
- {
- // Initially assign the region's fit value
- m_eFit = pRegion->m_eFit;
- }
- // Now if the source has specified a fit
- // value, then override the region's fit value
- if (pSource->m_bFitSpecified)
- {
- m_eFit = pSource->m_eFit;
- }
- }
- }
- }
- CSmilSiteWatcher::~CSmilSiteWatcher()
- {
- close();
- }
- HX_RESULT CSmilSiteWatcher::close()
- {
- HX_RELEASE(m_pDoc);
- HX_RELEASE(m_pSite);
- return HXR_OK;
- }
- void CSmilSiteWatcher::SetZoomScaleFactors(double dX, double dY)
- {
- if (dX > 0.0)
- {
- m_dZoomScaleFactorX = dX;
- }
- if (dY > 0.0)
- {
- m_dZoomScaleFactorY = dY;
- }
- }
- void CSmilSiteWatcher::SetResizeBehavior(ResizeBehavior eBehavior)
- {
- m_eResizeBehavior = eBehavior;
- }
- STDMETHODIMP CSmilSiteWatcher::QueryInterface(REFIID riid, void** ppvObj)
- {
- HX_RESULT retVal = HXR_OK;
- if(IsEqualIID(riid, IID_IUnknown))
- {
- AddRef();
- *ppvObj = this;
- }
- else if(IsEqualIID(riid, IID_IHXSiteWatcher))
- {
- AddRef();
- *ppvObj = (IHXSiteWatcher*) this;
- }
- else
- {
- *ppvObj = NULL;
- retVal = HXR_NOINTERFACE;
- }
- return retVal;
- }
- STDMETHODIMP_(ULONG32) CSmilSiteWatcher::AddRef()
- {
- return InterlockedIncrement(&m_lRefCount);
- }
- STDMETHODIMP_(ULONG32) CSmilSiteWatcher::Release()
- {
- if(InterlockedDecrement(&m_lRefCount) > 0)
- {
- return m_lRefCount;
- }
- delete this;
- return 0;
- }
- STDMETHODIMP CSmilSiteWatcher::AttachSite(IHXSite* pSite)
- {
- HX_RESULT retVal = HXR_OK;
- HX_RELEASE(m_pSite);
- m_pSite = pSite;
- if(m_pSite)
- {
- m_pSite->AddRef();
- }
- return retVal;
- }
- STDMETHODIMP CSmilSiteWatcher::DetachSite()
- {
- HX_RESULT retVal = HXR_OK;
- HX_RELEASE(m_pSite);
- return HXR_OK;
- }
- STDMETHODIMP CSmilSiteWatcher::ChangingPosition(HXxPoint oldPos,
- REF(HXxPoint) newPos)
- {
- HX_RESULT retVal = HXR_OK;
- if(!m_bChangingSize)
- {
- CSmilBasicRegion* pRegion = m_pDoc->getRegionByID(m_id);
- if(pRegion && m_bMediaSizeSet)
- {
- // Pick the rect to use as the parent. If we
- // have a ResizeBehavior of Zoom and are indeed
- // zooming, then use the unzoomed parent width.
- // Otherwise, use the regular zoomed parent width.
- HXxRect cRect = pRegion->m_rect;
- if ((m_dZoomScaleFactorX != 1.0 ||
- m_dZoomScaleFactorY != 1.0) &&
- m_eResizeBehavior == ResizeZoom)
- {
- cRect = pRegion->m_RectNoZoom;
- }
- // First we need to compute the subregion rect. We can't
- // do this just once, since the subregion rect parameters
- // may be getting animated.
- HXxRect cSubRegionRect = {0, 0, 0, 0};
- CSmilBasicRegion::resolveDimension(m_Rect.m_dLeft, m_Rect.m_eLeftType,
- m_Rect.m_dRight, m_Rect.m_eRightType,
- m_Rect.m_dWidth, m_Rect.m_eWidthType,
- TRUE, HXxRECT_WIDTH(cRect),
- cSubRegionRect.left,
- cSubRegionRect.right);
- CSmilBasicRegion::resolveDimension(m_Rect.m_dTop, m_Rect.m_eTopType,
- m_Rect.m_dBottom, m_Rect.m_eBottomType,
- m_Rect.m_dHeight, m_Rect.m_eHeightType,
- TRUE, HXxRECT_HEIGHT(cRect),
- cSubRegionRect.top,
- cSubRegionRect.bottom);
- // The calculation above was done in the space of the
- // region. The calculations below are done in the space
- // of the region's parent, so we need to offset the subregion
- // rect by the region's upper left corner.
- cSubRegionRect.left += cRect.left;
- cSubRegionRect.top += cRect.top;
- cSubRegionRect.right += cRect.left;
- cSubRegionRect.bottom += cRect.top;
- // Now we need to compute the absolute coordinates
- // of the regPoint. Since the regPoint could be in
- // percentage values, and the size of the region
- // could be changing under animation, then we
- // must recompute the absolute coordinates of the
- // regPoint every time. This regPoint is in the
- // space of the region's PARENT and not in the space
- // of the region's rect itself.
- HXxPoint cRegPoint = {0, 0};
- m_pDoc->computeRegPoint(cSubRegionRect,
- m_RegPoint,
- cRegPoint);
- // Now that we know the absolute coordinates
- // of the regPoint, then we can compute the
- // media layout within the region rect. Note
- // that the following calculation takes place
- // in the coordinate space of the region's PARENT,
- // and not the region's rect itself.
- HXxRect cMediaRect = {0, 0, 0, 0};
- retVal = m_pDoc->computeMediaLayout(cSubRegionRect,
- m_eFit,
- cRegPoint,
- m_RegPoint.m_eRegAlign,
- m_MediaSize,
- cMediaRect,
- m_bMediaIsBrush);
- if (SUCCEEDED(retVal))
- {
- // 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
- // coordinate space of the REGION, then we need
- // to translate the media rect to the coordinate
- // space of the region.
- cMediaRect.left -= cRect.left;
- cMediaRect.top -= cRect.top;
- cMediaRect.right -= cRect.left;
- cMediaRect.bottom -= cRect.top;
- // Now we can assign the new position
- newPos.x = cMediaRect.left;
- newPos.y = 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.
- if ((m_dZoomScaleFactorX != 1.0 ||
- m_dZoomScaleFactorY != 1.0) &&
- m_eResizeBehavior == ResizeZoom)
- {
- newPos.x = (INT32) floor(m_dZoomScaleFactorX * ((double) newPos.x) + 0.5);
- newPos.y = (INT32) floor(m_dZoomScaleFactorY * ((double) newPos.y) + 0.5);
- }
- }
- }
- }
- MLOG_LAYOUT(NULL,
- "%lutChangingPosition((%ld,%ld),(%ld,%ld)) m_id=%s m_SourceID=%sn",
- HX_GET_BETTERTICKCOUNT(),
- oldPos.x, oldPos.y, newPos.x, newPos.y,
- (const char*) m_id,
- (const char*) m_SourceID);
- return retVal;
- }
- STDMETHODIMP CSmilSiteWatcher::ChangingSize(HXxSize oldSize,
- REF(HXxSize) newSize)
- {
- HX_RESULT retVal = HXR_OK;
- if(!m_bChangingSize &&
- (newSize.cx != 0 || newSize.cy != 0))
- {
- CSmilBasicRegion* pRegion = m_pDoc->getRegionByID(m_id);
- if(pRegion)
- {
- // For almost all renderers, here's the sequence of
- // events: the core calls them with IHXSite::AttachSite()
- // and in that call, they call IHXSite::SetSize() with
- // the native size of their media. Therefore, we will assume
- // that the first call we get will be the native size of
- // the media.
- BOOL bForceSetPosition = FALSE;
-
- BOOL bHasSiteUser = FALSE;
- IHXSiteUser* pUser = NULL;
- m_pSite->GetUser(pUser);
- if (pUser)
- {
- bHasSiteUser = TRUE;
- }
- HX_RELEASE(pUser);
-
- if (bHasSiteUser && m_bFirstSizeChange)
- {
- MLOG_LAYOUT(NULL,
- "Media size for %s is (%ld,%ld)n",
- (const char*) m_SourceID,
- newSize.cx, newSize.cy);
- // Save off the native media size
- m_MediaSize = newSize;
- m_bMediaSizeSet = TRUE;
- m_bFirstSizeChange = FALSE;
- bForceSetPosition = TRUE;
- if (m_pDoc)
- {
- m_pDoc->setMediaNativeSize(m_SourceID, newSize);
- }
- // XXXMEH - this is legacy, which saves
- // the media size into the region. However,
- // this SHOULD NOT be used, since multiple media
- // can play to the same region. TODO - if we
- // can, make sure this is not used and then
- // delete it from the region object.
- pRegion->m_originalMediaSize = newSize;
- pRegion->m_bMediaSizeSet = TRUE;
- }
- // Pick the rect to use as the parent. If we
- // have a ResizeBehavior of Zoom and are indeed
- // zooming, then use the unzoomed parent width.
- // Otherwise, use the regular zoomed parent width.
- HXxRect cRect = pRegion->m_rect;
- if ((m_dZoomScaleFactorX != 1.0 ||
- m_dZoomScaleFactorY != 1.0) &&
- m_eResizeBehavior == ResizeZoom)
- {
- cRect = pRegion->m_RectNoZoom;
- }
- // First we need to compute the subregion rect. We can't
- // do this just once, since the subregion rect parameters
- // may be getting animated.
- HXxRect cSubRegionRect = {0, 0, 0, 0};
- CSmilBasicRegion::resolveDimension(m_Rect.m_dLeft, m_Rect.m_eLeftType,
- m_Rect.m_dRight, m_Rect.m_eRightType,
- m_Rect.m_dWidth, m_Rect.m_eWidthType,
- TRUE, HXxRECT_WIDTH(cRect),
- cSubRegionRect.left,
- cSubRegionRect.right);
- CSmilBasicRegion::resolveDimension(m_Rect.m_dTop, m_Rect.m_eTopType,
- m_Rect.m_dBottom, m_Rect.m_eBottomType,
- m_Rect.m_dHeight, m_Rect.m_eHeightType,
- TRUE, HXxRECT_HEIGHT(cRect),
- cSubRegionRect.top,
- cSubRegionRect.bottom);
- // The calculation above was done in the space of the
- // region. The calculations below are done in the space
- // of the region's parent, so we need to offset the subregion
- // rect by the region's upper left corner.
- cSubRegionRect.left += cRect.left;
- cSubRegionRect.top += cRect.top;
- cSubRegionRect.right += cRect.left;
- cSubRegionRect.bottom += cRect.top;
- // Now we need to compute the absolute coordinates
- // of the regPoint. Since the regPoint could be in
- // percentage values, and the size of the region
- // could be changing under animation, then we
- // must recompute the absolute coordinates of the
- // regPoint every time. This regPoint is in the
- // space of the region's PARENT and not in the space
- // of the region's rect itself.
- HXxPoint cRegPoint = {0, 0};
- m_pDoc->computeRegPoint(cSubRegionRect,
- m_RegPoint,
- cRegPoint);
- // Now that we know the absolute coordinates
- // of the regPoint, then we can compute the
- // media layout within the region rect. Note
- // that the following calculation takes place
- // in the coordinate space of the region's PARENT,
- // and not the region's rect itself.
- HXxRect cMediaRect = {0, 0, 0, 0};
- retVal = m_pDoc->computeMediaLayout(cSubRegionRect,
- m_eFit,
- cRegPoint,
- m_RegPoint.m_eRegAlign,
- m_MediaSize,
- cMediaRect,
- m_bMediaIsBrush);
- if (SUCCEEDED(retVal))
- {
- // 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
- // coordinate space of the REGION, then we need
- // to translate the media rect to the coordinate
- // space of the region.
- cMediaRect.left -= cRect.left;
- cMediaRect.top -= cRect.top;
- cMediaRect.right -= cRect.left;
- cMediaRect.bottom -= cRect.top;
- // So now the new width and height
- // can be calculated.
- newSize.cx = HXxRECT_WIDTH(cMediaRect);
- newSize.cy = HXxRECT_HEIGHT(cMediaRect);
- // 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.
- if ((m_dZoomScaleFactorX != 1.0 ||
- m_dZoomScaleFactorY != 1.0) &&
- m_eResizeBehavior == ResizeZoom)
- {
- newSize.cx = (INT32) floor(m_dZoomScaleFactorX * ((double) newSize.cx) + 0.5);
- newSize.cy = (INT32) floor(m_dZoomScaleFactorY * ((double) newSize.cy) + 0.5);
- }
- // Set the current media size to this value
- // XXXMEH - TODO is this actually used anywhere? We
- // should not really have a media size set into
- // the region object anywhere, since multiple
- // media can play to the same region
- pRegion->m_mediaSize = newSize;
- // As mentioned above, the renderers will usually
- // call IHXSite::SetSize() when they are FIRST called
- // with IHXSite::AttachSite(). However, since renderers
- // don't have an idea of relative position to other renderers,
- // then they rarely call IHXSite::SetPosition(). Therefore,
- // if this is the first time through, we will need to explicitly
- // call IHXSite::SetPosition().
- if (bForceSetPosition)
- {
- // Since we have a site watcher, then it
- // doesn't matter what we pass in, the site
- // watcher will change it to what it needs to
- // be. So pass in some arbitrary position.
- HXxPoint cPos = {1, 1};
- if (m_pSite)
- {
- m_pSite->SetPosition(cPos);
- }
- }
- // If this is a scrolling site, then set the flag
- if (m_eFit == FitScroll && m_pSite)
- {
- IHXValues* pValues = NULL;
- m_pSite->QueryInterface(IID_IHXValues, (void**) &pValues);
- if (pValues)
- {
- pValues->SetPropertyULONG32("ScrollingSite", 1);
- }
- HX_RELEASE(pValues);
- }
- }
- }
- }
- MLOG_LAYOUT(NULL,
- "%lutChangingSize((%ld,%ld),(%ld,%ld)) m_id=%s m_SourceID=%sn",
- HX_GET_BETTERTICKCOUNT(),
- oldSize.cx, oldSize.cy, newSize.cx, newSize.cy,
- (const char*) m_id,
- (const char*) m_SourceID);
- return retVal;
- }