A Fast Bresenham Type Algorithm For Drawing Ellipses by John Kennedy
[xy_vsfilter.git] / src / apps / mplayerc / RealMediaWindowlessSite.cpp
blob9891f5e71672e15a8d0ea277cae0ab3f7dd4aeeb
1 /*
2 * Copyright (C) 2003-2006 Gabest
3 * http://www.gabest.org
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GNU Make; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
22 #include "stdafx.h"
23 #include "mplayerc.h"
24 #include <math.h>
25 #include <atlbase.h>
26 #include <atlcoll.h>
27 #include "realmediawindowlesssite.h"
28 #include "..\..\DSUtil\DSUtil.h"
30 void DSObjects::ExtractRects(REGION* pRegion)
32 LPRGNDATA lpRgnData;
34 DWORD sizeNeeed = GetRegionData((HRGN)pRegion->pOSRegion, 0, NULL);
36 lpRgnData = (LPRGNDATA)new char[sizeNeeed];
37 DWORD returnValue = GetRegionData((HRGN)pRegion->pOSRegion, sizeNeeed, lpRgnData);
39 PN_VECTOR_DELETE(pRegion->rects);
41 pRegion->numRects = lpRgnData->rdh.nCount;
42 pRegion->extents.left = lpRgnData->rdh.rcBound.left;
43 pRegion->extents.top = lpRgnData->rdh.rcBound.top;
44 pRegion->extents.right = lpRgnData->rdh.rcBound.right;
45 pRegion->extents.bottom = lpRgnData->rdh.rcBound.bottom;
47 if(lpRgnData->rdh.nCount)
49 pRegion->rects = new PNxRect[lpRgnData->rdh.nCount];
51 // now extract the information.
53 for(int j = 0; j < (int) lpRgnData->rdh.nCount;j++)
55 RECT* pRect = (RECT*)lpRgnData->Buffer;
56 pRegion->rects[j].left = pRect[j].left;
57 pRegion->rects[j].top = pRect[j].top;
58 pRegion->rects[j].right = pRect[j].right;
59 pRegion->rects[j].bottom = pRect[j].bottom;
63 PN_VECTOR_DELETE(lpRgnData);
65 REGION* DSObjects::RMACreateRectRegion(int left, int top, int right, int bottom)
67 REGION* retVal = new REGION;
68 retVal->pOSRegion = (void*)CreateRectRgn(left, top, right, bottom);
69 ExtractRects(retVal);
70 return retVal;
72 void DSObjects::RMASubtractRegion(REGION* regM, REGION* regS, REGION* regD)
74 CombineRgn((HRGN)regD->pOSRegion, (HRGN)regM->pOSRegion, (HRGN)regS->pOSRegion, RGN_DIFF);
75 ExtractRects(regD);
77 void DSObjects::RMAUnionRegion(REGION* reg1, REGION* reg2, REGION* regD)
79 CombineRgn((HRGN)regD->pOSRegion, (HRGN)reg1->pOSRegion, (HRGN)reg2->pOSRegion, RGN_OR);
80 ExtractRects(regD);
82 void DSObjects::RMAIntersectRegion(REGION* reg1, REGION* reg2, REGION* regD)
84 CombineRgn((HRGN)regD->pOSRegion, (HRGN)reg1->pOSRegion, (HRGN)reg2->pOSRegion, RGN_AND);
85 ExtractRects(regD);
87 BOOL DSObjects::RMAEqualRegion(REGION* reg1, REGION* reg2)
89 return EqualRgn((HRGN)reg1->pOSRegion, (HRGN)reg2->pOSRegion)
90 && !memcmp(&reg1->extents, &reg2->extents, sizeof(PNxRect)) ? TRUE : FALSE;
92 void DSObjects::RMADestroyRegion(REGION* reg)
94 if(reg) DeleteObject((HRGN)reg->pOSRegion),
95 PN_VECTOR_DELETE(reg->rects);
96 PN_DELETE(reg);
98 REGION* DSObjects::RMACreateRegion()
100 return RMACreateRectRegion(0,0,0,0);
104 // CRealMediaWindowlessSite
107 CRealMediaWindowlessSite::CRealMediaWindowlessSite(HRESULT& hr, IUnknown* pContext, CRealMediaWindowlessSite* pParentSite, IUnknown* pUnkOuter)
108 : CUnknown(NAME("CRealMediaWindowlessSite"), pUnkOuter, &hr)
109 , m_pContext(pContext)
110 , m_pParentSite(pParentSite)
111 , m_pCCF(pContext)
112 , m_fDamaged(false), m_fInRedraw(false), m_fIsVisible(true)
113 , m_lZOrder(0)
114 , m_pRegion(NULL), m_pRegionWithoutChildren(NULL)
116 m_size.cx = m_size.cy = 0;
117 m_position.x = m_position.y = 0;
119 memset(&m_lastBitmapInfo, 0, sizeof(m_lastBitmapInfo));
121 hr = S_OK;
123 if(!m_pContext || !m_pCCF)
125 hr = E_POINTER;
126 return;
129 m_pCCF->CreateInstance(CLSID_IRMAValues, (void**)&m_pValues);
132 CRealMediaWindowlessSite::~CRealMediaWindowlessSite()
134 POSITION pos = m_pChildren.GetHeadPosition();
135 while(pos) DestroyChild(m_pChildren.GetNext(pos));
137 RMADestroyRegion(m_pRegion);
138 RMADestroyRegion(m_pRegionWithoutChildren);
141 STDMETHODIMP CRealMediaWindowlessSite::NonDelegatingQueryInterface(REFIID riid, void** ppv)
143 return
144 QI2(IRMASite)
145 QI2(IRMASite2)
146 QI2(IRMASiteWindowless)
147 QI2(IRMAVideoSurface)
148 (m_pValues && m_pValues->QueryInterface(riid, ppv) == PNR_OK) ? PNR_OK :
149 CUnknown::NonDelegatingQueryInterface(riid, ppv);
152 // public
154 void CRealMediaWindowlessSite::GetTopLeft(PNxPoint* pPoint)
156 pPoint->x += m_position.x;
157 pPoint->y += m_position.y;
159 if(m_pParentSite)
160 m_pParentSite->GetTopLeft(pPoint);
163 REGION* CRealMediaWindowlessSite::GetRegion()
165 return m_pRegion;
168 // private
170 void CRealMediaWindowlessSite::RecomputeRegion()
172 if(m_pParentSite) m_pParentSite->RecomputeRegion();
173 else InternalRecomputeRegion();
176 void CRealMediaWindowlessSite::InternalRecomputeRegion()
178 ComputeRegion();
180 POSITION pos = m_pChildren.GetHeadPosition();
181 while(pos)
183 CRealMediaWindowlessSite* pSite = (CRealMediaWindowlessSite*)(IRMASite*)m_pChildren.GetNext(pos);
184 if(pSite) pSite->InternalRecomputeRegion();
188 void CRealMediaWindowlessSite::ComputeRegion()
190 REGION* pTempRegion = NULL;
192 if(m_pRegion)
194 pTempRegion = RMACreateRegion();
195 RMAUnionRegion(pTempRegion, m_pRegion, pTempRegion);
196 RMADestroyRegion(m_pRegion);
199 if(m_pRegionWithoutChildren)
201 RMADestroyRegion(m_pRegionWithoutChildren);
204 PNxPoint topleft = {0,0};
205 GetTopLeft(&topleft);
207 if(IsSiteVisible())
209 m_pRegionWithoutChildren = RMACreateRectRegion(topleft.x, topleft.y, topleft.x + m_size.cx, topleft.y + m_size.cy);
211 if(m_pParentSite)
213 RMAIntersectRegion(m_pRegionWithoutChildren, m_pParentSite->m_pRegionWithoutChildren, m_pRegionWithoutChildren);
215 POSITION pos = m_pParentSite->m_pChildren.GetHeadPosition();
216 while(pos)
218 CRealMediaWindowlessSite* pSiblingSite = (CRealMediaWindowlessSite*)(IRMASite*)m_pParentSite->m_pChildren.GetNext(pos);
219 if(pSiblingSite != this)
221 INT32 zOrder;
222 pSiblingSite->GetZOrder(zOrder);
224 if(zOrder > m_lZOrder && pSiblingSite->IsSiteVisible())
226 pSiblingSite->SubtractSite(m_pRegionWithoutChildren);
232 m_pRegion = RMACreateRegion();
233 RMAUnionRegion(m_pRegion, m_pRegionWithoutChildren, m_pRegion);
235 POSITION pos = m_pChildren.GetHeadPosition();
236 while(pos)
238 CRealMediaWindowlessSite* pChildSite = (CRealMediaWindowlessSite*)(IRMASite*)m_pChildren.GetNext(pos);
239 if(pChildSite->IsSiteVisible()) pChildSite->SubtractSite(m_pRegion);
242 else
244 m_pRegionWithoutChildren = RMACreateRectRegion(0,0,0,0);
245 m_pRegion = RMACreateRectRegion(0,0,0,0);
248 if(pTempRegion && !RMAEqualRegion(m_pRegion, pTempRegion))
250 ForceRedraw();
253 RMADestroyRegion(pTempRegion);
256 void CRealMediaWindowlessSite::SubtractSite(REGION* pRegion)
258 PNxPoint topLeft;
259 memset(&topLeft, 0, sizeof(PNxPoint));
260 GetTopLeft(&topLeft);
262 REGION* pTempRegion = RMACreateRectRegion(topLeft.x, topLeft.y, topLeft.x + m_size.cx, topLeft.y + m_size.cy);
264 RMASubtractRegion(pRegion, pTempRegion, pRegion);
265 RMADestroyRegion(pTempRegion);
268 void CRealMediaWindowlessSite::UpdateZOrder(CRealMediaWindowlessSite* pUpdatedChildSite, INT32 lOldZOrder, INT32 lNewZOrder)
270 POSITION pos = m_pChildren.GetHeadPosition();
271 while(pos)
273 CRealMediaWindowlessSite* pSite = (CRealMediaWindowlessSite*)(IRMASite*)m_pChildren.GetNext(pos);
275 INT32 lItsOldZOrder;
276 pSite->GetZOrder(lItsOldZOrder);
278 if(pSite != pUpdatedChildSite)
280 if(lOldZOrder < lNewZOrder)
282 if(lItsOldZOrder >= lOldZOrder && lItsOldZOrder < lNewZOrder)
284 pSite->SetInternalZOrder(lItsOldZOrder-1);
287 else
289 if(lItsOldZOrder >= lNewZOrder && lItsOldZOrder < lOldZOrder)
291 pSite->SetInternalZOrder(lItsOldZOrder+1);
295 else
297 pSite->SetInternalZOrder(lNewZOrder);
302 void CRealMediaWindowlessSite::SetInternalZOrder(INT32 lZOrder)
304 m_lZOrder = lZOrder;
307 // IRMASiteWindowless
309 STDMETHODIMP CRealMediaWindowlessSite::EventOccurred(PNxEvent* /*IN*/ pEvent)
311 return PNR_NOTIMPL; /* not necessary within our implementation */
314 STDMETHODIMP_(PNxWindow*) CRealMediaWindowlessSite::GetParentWindow()
316 return NULL;
319 // IRMASite
321 STDMETHODIMP CRealMediaWindowlessSite::AttachUser(IRMASiteUser* /*IN*/ pUser)
323 HRESULT hr = PNR_FAIL;
325 if(m_pUser) return PNR_UNEXPECTED;
327 if(CComQIPtr<IRMASite, &IID_IRMASite> pOuterSite = GetOwner())
328 hr = pUser->AttachSite(pOuterSite);
330 if(PNR_OK == hr)
331 m_pUser = pUser;
333 return hr;
336 STDMETHODIMP CRealMediaWindowlessSite::DetachUser()
338 HRESULT hr = PNR_OK;
340 if(!m_pUser) return PNR_UNEXPECTED;
342 hr = m_pUser->DetachSite();
344 if(PNR_OK == hr)
345 m_pUser = NULL;
347 return hr;
350 STDMETHODIMP CRealMediaWindowlessSite::GetUser(REF(IRMASiteUser*) /*OUT*/ pUser)
352 HRESULT hr = PNR_OK;
354 if(!m_pUser) return PNR_UNEXPECTED;
356 (pUser = m_pUser)->AddRef();
358 return hr;
361 STDMETHODIMP CRealMediaWindowlessSite::CreateChild(REF(IRMASite*) /*OUT*/ pChildSite)
363 HRESULT hr = PNR_OK;
365 CComPtr<IRMASite> pSite =
366 (IRMASite*)new CRealMediaWindowlessSite(hr, m_pContext, this);
368 if(FAILED(hr) || !pSite)
369 return E_FAIL;
371 pChildSite = pSite.Detach();
373 m_pChildren.AddTail(pChildSite);
375 return hr;
378 STDMETHODIMP CRealMediaWindowlessSite::DestroyChild(IRMASite* /*IN*/ pChildSite)
380 if(POSITION pos = m_pChildren.Find(pChildSite))
382 m_pChildren.RemoveAt(pos);
383 return PNR_OK;
386 return PNR_UNEXPECTED;
389 STDMETHODIMP CRealMediaWindowlessSite::AttachWatcher(IRMASiteWatcher* /*IN*/ pWatcher)
391 if(m_pWatcher) return PNR_UNEXPECTED;
393 if(m_pWatcher = pWatcher)
394 m_pWatcher->AttachSite((IRMASite*)this);
396 return PNR_OK;
399 STDMETHODIMP CRealMediaWindowlessSite::DetachWatcher()
401 if(!m_pWatcher) return PNR_UNEXPECTED;
403 m_pWatcher->DetachSite();
404 m_pWatcher = NULL;
406 return PNR_OK;
409 STDMETHODIMP CRealMediaWindowlessSite::SetPosition(PNxPoint position)
411 HRESULT hr = PNR_OK;
413 if(m_pWatcher)
415 hr = m_pWatcher->ChangingPosition(m_position, position);
418 if(PNR_OK == hr)
420 m_position = position;
422 POSITION pos = m_pPassiveWatchers.GetHeadPosition();
423 while(pos) m_pPassiveWatchers.GetNext(pos)->PositionChanged(&position);
425 RecomputeRegion();
428 return hr;
431 STDMETHODIMP CRealMediaWindowlessSite::GetPosition(REF(PNxPoint) position)
433 position = m_position;
434 return PNR_OK;
437 STDMETHODIMP CRealMediaWindowlessSite::SetSize(PNxSize size)
439 HRESULT hr = PNR_OK;
441 if(m_pWatcher)
443 hr = m_pWatcher->ChangingSize(m_size, size);
446 if(PNR_OK == hr && size.cx != 0 && size.cy != 0)
448 m_size = size;
450 POSITION pos = m_pPassiveWatchers.GetHeadPosition();
451 while(pos) m_pPassiveWatchers.GetNext(pos)->SizeChanged(&size);
453 RecomputeRegion();
456 return hr;
459 STDMETHODIMP CRealMediaWindowlessSite::GetSize(REF(PNxSize) size)
461 size = m_size;
462 return PNR_OK;
465 STDMETHODIMP CRealMediaWindowlessSite::DamageRect(PNxRect rect)
467 m_fDamaged = TRUE;
468 return PNR_OK;
471 STDMETHODIMP CRealMediaWindowlessSite::DamageRegion(PNxRegion region)
473 m_fDamaged = TRUE;
474 return PNR_OK;
477 STDMETHODIMP CRealMediaWindowlessSite::ForceRedraw()
479 // make sure we have a visible window and are not re-enterering and we have damage
480 if(!m_fInRedraw && m_fDamaged && m_fIsVisible)
482 m_fInRedraw = TRUE;
484 PNxEvent event = {RMA_SURFACE_UPDATE, NULL, (IRMAVideoSurface*)this, NULL, 0, 0};
485 m_pUser->HandleEvent(&event);
487 m_fInRedraw = FALSE;
488 m_fDamaged = FALSE;
491 return PNR_OK;
494 // IRMASite2
496 STDMETHODIMP CRealMediaWindowlessSite::UpdateSiteWindow(PNxWindow* /*IN*/ pWindow)
498 return PNR_OK;
501 STDMETHODIMP CRealMediaWindowlessSite::ShowSite(BOOL bShow)
503 m_fIsVisible = !!bShow;
504 RecomputeRegion();
505 return PNR_OK;
508 STDMETHODIMP_(BOOL) CRealMediaWindowlessSite::IsSiteVisible()
510 BOOL fIsVisible = m_fIsVisible;
511 if(m_pParentSite) fIsVisible = fIsVisible && m_pParentSite->IsSiteVisible();
512 return fIsVisible;
515 STDMETHODIMP CRealMediaWindowlessSite::SetZOrder(INT32 lZOrder)
517 if(!m_pParentSite) return PNR_UNEXPECTED;
519 if(lZOrder == -1 || lZOrder >= (INT32)m_pParentSite->GetNumberOfChildSites())
520 lZOrder = m_pParentSite->GetNumberOfChildSites() - 1;
522 if(m_lZOrder != lZOrder)
523 m_pParentSite->UpdateZOrder(this, m_lZOrder, lZOrder);
525 m_lZOrder = lZOrder;
527 return PNR_OK;
530 STDMETHODIMP CRealMediaWindowlessSite::GetZOrder(REF(INT32) lZOrder)
532 if(!m_pParentSite) return PNR_UNEXPECTED;
533 lZOrder = m_lZOrder;
534 return PNR_OK;
537 STDMETHODIMP CRealMediaWindowlessSite::MoveSiteToTop()
539 if(!m_pParentSite) return PNR_UNEXPECTED;
540 return PNR_NOTIMPL;
543 STDMETHODIMP CRealMediaWindowlessSite::GetVideoSurface(REF(IRMAVideoSurface*) pSurface)
545 (pSurface = (IRMAVideoSurface*)this)->AddRef();
546 return PNR_OK;
549 STDMETHODIMP_(UINT32) CRealMediaWindowlessSite::GetNumberOfChildSites()
551 return (UINT32)m_pChildren.GetCount();
554 STDMETHODIMP CRealMediaWindowlessSite::AddPassiveSiteWatcher(IRMAPassiveSiteWatcher* pWatcher)
556 m_pPassiveWatchers.AddTail(pWatcher);
557 return PNR_OK;
560 STDMETHODIMP CRealMediaWindowlessSite::RemovePassiveSiteWatcher(IRMAPassiveSiteWatcher* pWatcher)
562 if(POSITION pos = m_pPassiveWatchers.Find(pWatcher))
564 m_pPassiveWatchers.RemoveAt(pos);
565 return PNR_OK;
568 return PNR_UNEXPECTED;
571 STDMETHODIMP CRealMediaWindowlessSite::SetCursor(PNxCursor cursor, REF(PNxCursor) oldCursor)
573 return PNR_NOTIMPL;
576 // private
578 void CRealMediaWindowlessSite::IntersectRect(PNxRect* pRect, PNxRect* pBox, PNxRect* pRetVal)
580 pRetVal->left = max(pRect->left, pBox->left);
581 pRetVal->top = max(pRect->top, pBox->top);
582 pRetVal->right = min(pRect->right, pBox->right);
583 pRetVal->bottom = min(pRect->bottom, pBox->bottom);
586 // protected
588 bool CRealMediaWindowlessSite::GetBltService(IRMAVideoSurface** ppBltService)
590 bool fRet = false;
592 if(ppBltService)
594 if(m_pParentSite)
596 fRet = m_pParentSite->GetBltService(ppBltService);
598 else if(m_pBltService)
600 (*ppBltService = m_pBltService)->AddRef();
601 fRet = true;
605 return(fRet);
608 void CRealMediaWindowlessSite::SetBltService(IRMAVideoSurface* pBltService)
610 m_pBltService = pBltService;
613 // IRMAVideoSurface
615 STDMETHODIMP CRealMediaWindowlessSite::Blt(UCHAR* /*IN*/ pImageData, RMABitmapInfoHeader* /*IN*/ pBitmapInfo, REF(PNxRect) /*IN*/ inDestRect, REF(PNxRect) /*IN*/ inSrcRect)
617 BeginOptimizedBlt(pBitmapInfo);
618 return OptimizedBlt(pImageData, inDestRect, inSrcRect);
621 STDMETHODIMP CRealMediaWindowlessSite::BeginOptimizedBlt(RMABitmapInfoHeader* /*IN*/ pBitmapInfo)
623 if(memcmp(&m_bitmapInfo, pBitmapInfo, sizeof(RMABitmapInfoHeader)))
625 memcpy(&m_bitmapInfo, pBitmapInfo, sizeof(RMABitmapInfoHeader));
627 // format of image has changed somehow.
628 // do something here if this affects you.
632 CComPtr<IRMAVideoSurface> pBltService;
633 GetBltService(&pBltService);
634 if(!pBltService)
635 return PNR_UNEXPECTED;
637 RMA_COMPRESSION_TYPE ulType = (RMA_COMPRESSION_TYPE)-1;
638 pBltService->GetPreferredFormat(ulType);
640 if(pBitmapInfo->biCompression != ulType)
641 return PNR_UNEXPECTED;
643 return PNR_OK;
646 STDMETHODIMP CRealMediaWindowlessSite::OptimizedBlt(UCHAR* /*IN*/ pImageBits, REF(PNxRect) /*IN*/ rDestRect, REF(PNxRect) /*IN*/ rSrcRect)
648 CComPtr<IRMAVideoSurface> pBltService;
649 GetBltService(&pBltService);
651 REGION* pRegion = GetRegion();
653 if(!pBltService || !pRegion)
654 return PNR_UNEXPECTED;
656 PNxPoint origin;
657 memset(&origin, 0, sizeof(PNxPoint));
658 GetTopLeft(&origin);
659 PNxRect adjustedDestRect;
660 adjustedDestRect.left = rDestRect.left + origin.x;
661 adjustedDestRect.top = rDestRect.top + origin.y;
662 adjustedDestRect.right = rDestRect.right + origin.x;
663 adjustedDestRect.bottom = rDestRect.bottom + origin.y;
665 for(int i = 0; i < pRegion->numRects; i++)
667 PNxRect* pRect = pRegion->rects+i;
669 // intersect the dest rect with the rect from the
670 // region to get the final dest rect.
671 PNxRect finalDestRect;
672 IntersectRect(&adjustedDestRect, pRect, &finalDestRect);
674 // now compute the src rect for this blt.
675 double xStretch = (double) (rDestRect.right - rDestRect.left) / (double) (rSrcRect.right - rSrcRect.left);
676 double yStretch = (double) (rDestRect.bottom - rDestRect.top) / (double) (rSrcRect.bottom - rSrcRect.top);
678 PNxRect finalSrcRect;
679 finalSrcRect.left = (INT32)((double)(finalDestRect.left-origin.x) / xStretch + 0.5);
680 finalSrcRect.top = (INT32)((double)(finalDestRect.top-origin.y) / yStretch + 0.5);
681 finalSrcRect.right = (INT32)((double)(finalDestRect.right-origin.x) / xStretch + 0.5);
682 finalSrcRect.bottom = (INT32)((double)(finalDestRect.bottom-origin.y) / yStretch + 0.5);
684 pBltService->Blt(pImageBits, &m_bitmapInfo, finalDestRect, finalSrcRect);
687 return PNR_OK;
690 STDMETHODIMP CRealMediaWindowlessSite::EndOptimizedBlt()
692 memset(&m_bitmapInfo, 0, sizeof(m_bitmapInfo));
693 return PNR_OK;
696 STDMETHODIMP CRealMediaWindowlessSite::GetOptimizedFormat(REF(RMA_COMPRESSION_TYPE) /*OUT*/ ulType)
698 ulType = m_bitmapInfo.biCompression;
699 return PNR_OK;
702 STDMETHODIMP CRealMediaWindowlessSite::GetPreferredFormat(REF(RMA_COMPRESSION_TYPE) /*OUT*/ ulType)
704 CComPtr<IRMAVideoSurface> pBltService;
705 GetBltService(&pBltService);
706 if(!pBltService)
707 return PNR_UNEXPECTED;
709 return pBltService->GetPreferredFormat(ulType);