aboutsummaryrefslogtreecommitdiff
path: root/Src/nsv/nsvplay/vid_overlay.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/nsv/nsvplay/vid_overlay.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/nsv/nsvplay/vid_overlay.cpp')
-rw-r--r--Src/nsv/nsvplay/vid_overlay.cpp654
1 files changed, 654 insertions, 0 deletions
diff --git a/Src/nsv/nsvplay/vid_overlay.cpp b/Src/nsv/nsvplay/vid_overlay.cpp
new file mode 100644
index 00000000..efe32661
--- /dev/null
+++ b/Src/nsv/nsvplay/vid_overlay.cpp
@@ -0,0 +1,654 @@
+#include "video.h"
+#include <multimon.h>
+#include "subtitles.h"
+
+#define INIT_DIRECTDRAW_STRUCT(x) (ZeroMemory(&x, sizeof(x)), x.dwSize=sizeof(x))
+#define OV_COL_R 16
+#define OV_COL_G 0
+#define OV_COL_B 16
+
+OverlayVideoOutput::OverlayVideoOutput() {
+ lpDD=NULL;
+ lpddsOverlay=NULL;
+ lpddsPrimary=NULL;
+ is_fullscreen=0;
+ yuy2_output=uyvy_output=0;
+ m_parent=NULL;
+ initing=false;
+ needchange=0;
+ memset(&m_oldrd,0,sizeof(m_oldrd));
+ memset(&winRect,0,sizeof(winRect));
+ subFont=NULL;
+ m_fontsize=0;
+ resetSubtitle();
+}
+
+OverlayVideoOutput::~OverlayVideoOutput() {
+ if(is_fullscreen) removeFullScreen();
+ LPDIRECTDRAWSURFACE o=lpddsOverlay;
+ lpddsOverlay=NULL;
+ if(o) o->Release();
+ if(lpddsPrimary) lpddsPrimary->Release();
+ if (lpDD) lpDD->Release(); // BU added NULL check in response to talkback
+ if(subFont) DeleteObject(subFont);
+}
+
+static DWORD DD_ColorMatch(LPDIRECTDRAWSURFACE pdds, COLORREF rgb)
+{
+ COLORREF rgbT;
+ HDC hdc;
+ DWORD dw = CLR_INVALID;
+ DDSURFACEDESC ddsd;
+ HRESULT hres;
+
+ //
+ // use GDI SetPixel to color match for us
+ //
+ if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
+ {
+ rgbT = GetPixel(hdc, 0, 0); // save current pixel value
+ SetPixel(hdc, 0, 0, rgb); // set our value
+ pdds->ReleaseDC(hdc);
+ }
+
+ //
+ // now lock the surface so we can read back the converted color
+ //
+ ddsd.dwSize = sizeof(ddsd);
+ while ((hres = pdds->Lock(NULL, &ddsd, 0, NULL)) ==
+ DDERR_WASSTILLDRAWING)
+ ;
+
+ if (hres == DD_OK)
+ {
+ dw = *(DWORD *)ddsd.lpSurface; // get DWORD
+ if(ddsd.ddpfPixelFormat.dwRGBBitCount<32)
+ dw &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount) - 1; // mask it to bpp
+ pdds->Unlock(NULL);
+ }
+
+ //
+ // now put the color that was there back.
+ //
+ if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
+ {
+ SetPixel(hdc, 0, 0, rgbT);
+ pdds->ReleaseDC(hdc);
+ }
+
+ return dw;
+}
+
+int OverlayVideoOutput::create(VideoOutput *parent, int w, int h, unsigned int ptype, int flipit, double aspectratio) {
+ type=ptype;
+ width=w;
+ height=h;
+ flip=flipit;
+ m_parent=parent;
+
+ initing=true;
+ HWND hwnd=parent->getHwnd();
+
+ if (lpDD) lpDD->Release();
+ lpDD=NULL;
+
+ update_monitor_coords(parent);
+
+ if(!m_found_devguid) DirectDrawCreate(NULL,&lpDD,NULL);
+ else DirectDrawCreate(&m_devguid,&lpDD,NULL);
+
+ if(!lpDD) {
+ initing=false;
+ return 0;
+ }
+
+ lpDD->SetCooperativeLevel(hwnd,DDSCL_NOWINDOWCHANGES|DDSCL_NORMAL);
+
+ DDSURFACEDESC ddsd;
+ INIT_DIRECTDRAW_STRUCT(ddsd);
+ ddsd.dwFlags = DDSD_CAPS;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ HRESULT ddrval = lpDD->CreateSurface(&ddsd, &lpddsPrimary, NULL );
+
+ // init overlay
+ DDSURFACEDESC ddsdOverlay;
+ INIT_DIRECTDRAW_STRUCT(ddsdOverlay);
+ ddsdOverlay.ddsCaps.dwCaps=DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY;
+ ddsdOverlay.dwFlags= DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_PITCH;
+ ddsdOverlay.dwWidth=w;
+ ddsdOverlay.dwHeight=h;
+ ddsdOverlay.lPitch=w*4;
+ ddsdOverlay.dwBackBufferCount=0;
+ DDPIXELFORMAT pf[]=
+ {
+ {sizeof(DDPIXELFORMAT),DDPF_FOURCC,MAKEFOURCC('Y','U','Y','2'),0,0,0,0,0},
+ {sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('U','Y','V','Y'),0,0,0,0,0}, // UYVY
+ {sizeof(DDPIXELFORMAT),DDPF_FOURCC,MAKEFOURCC('Y','V','1','2'),0,0,0,0,0},
+ };
+ int tab[5];
+ if(type==NSV_MAKETYPE('Y','U','Y','2')) {
+ tab[0]=0; // default is YUY2
+ tab[1]=1;
+ tab[2]=-1;
+ } else if(type==NSV_MAKETYPE('U','Y','V','Y')) {
+ tab[0]=1; // make UYVY default
+ tab[1]=0;
+ tab[2]=-1;
+ } else if(type==NSV_MAKETYPE('Y','V','1','2')) {
+ /*tab[0]=2;
+ tab[1]=0;
+ tab[2]=1;
+ tab[3]=-1;*/
+ //CT> Make YUY2 default too, cause YV12 is borked on some ATI cards/drivers :(
+ tab[0]=0;
+ tab[1]=1;
+ tab[2]=-1;
+ } else {
+ tab[0]=-1; // default is RGB
+ }
+
+ int x=4096;
+ HRESULT v=-1;
+ for (x = 0; x < sizeof(tab)/sizeof(tab[0]) && tab[x]>=0; x ++) {
+ ddsdOverlay.ddpfPixelFormat=pf[tab[x]];
+ v=lpDD->CreateSurface(&ddsdOverlay, &lpddsOverlay, NULL);
+ if (!FAILED(v)) break;
+ }
+ if(FAILED(v)||x>=sizeof(tab)/sizeof(tab[0])||tab[x]<0) {
+ initing=false;
+ return 0;
+ }
+
+ yuy2_output = (tab[x] == 0);
+ uyvy_output = (tab[x] == 1);
+
+ INIT_DIRECTDRAW_STRUCT(capsDrv);
+ ddrval = lpDD->GetCaps(&capsDrv, NULL);
+
+ uDestSizeAlign = capsDrv.dwAlignSizeDest;
+ uSrcSizeAlign = capsDrv.dwAlignSizeSrc;
+
+ dwUpdateFlags = DDOVER_SHOW | DDOVER_KEYDESTOVERRIDE;
+
+ DEVMODE d;
+ d.dmSize=sizeof(d);
+ d.dmDriverExtra=0;
+ EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &d);
+
+ int rv=OV_COL_R, gv=OV_COL_G, bv=OV_COL_B;
+
+ INIT_DIRECTDRAW_STRUCT(ovfx);
+ ovfx.dwDDFX=0;
+ switch(d.dmBitsPerPel) {
+ case 16:
+ ovfx.dckDestColorkey.dwColorSpaceLowValue=((rv>>3) << 11) | ((gv>>2) << 5) | (bv>>3);
+ break;
+ case 15:
+ ovfx.dckDestColorkey.dwColorSpaceLowValue=((rv>>3) << 10) | ((gv>>3) << 5) | (bv>>3);
+ break;
+ case 24: case 32:
+ ovfx.dckDestColorkey.dwColorSpaceLowValue=(rv << 16) | (gv << 8) | bv;
+ break;
+ }
+
+ //try to get the correct bit depth thru directdraw (for fucked up 16 bits displays for ie.)
+ {
+ DDSURFACEDESC DDsd={sizeof(DDsd),};
+ lpddsPrimary->GetSurfaceDesc(&ddsd);
+ DDsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT; //create the surface at screen depth
+ DDsd.dwWidth=8;
+ DDsd.dwHeight=8;
+ DDsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
+ LPDIRECTDRAWSURFACE tempsurf;
+ if(lpDD->CreateSurface(&DDsd, &tempsurf, NULL)==DD_OK)
+ {
+ int res=DD_ColorMatch(tempsurf, RGB(rv,gv,bv));
+ if(res!=CLR_INVALID) ovfx.dckDestColorkey.dwColorSpaceLowValue=res;
+ tempsurf->Release();
+ }
+ }
+
+ ovfx.dckDestColorkey.dwColorSpaceHighValue=ovfx.dckDestColorkey.dwColorSpaceLowValue;
+
+ getRects(&rs,&rd);
+ if(FAILED(lpddsOverlay->UpdateOverlay(&rs, lpddsPrimary, &rd, dwUpdateFlags, &ovfx))) {
+ initing=false;
+ return 0;
+ }
+ initing=false;
+
+ DDSURFACEDESC dd={sizeof(dd),};
+ if (lpddsOverlay->Lock(NULL,&dd,DDLOCK_WAIT,NULL) != DD_OK) return 0;
+ unsigned char *o=(unsigned char*)dd.lpSurface;
+ if (uyvy_output||yuy2_output)
+ {
+ int x=dd.lPitch*height/2;
+ while (x--)
+ {
+ if (uyvy_output)
+ {
+ *o++=128;
+ *o++=0;
+ }
+ else
+ {
+ *o++=0;
+ *o++=-128;
+ }
+ }
+ }
+ else
+ {
+ memset(o,0,dd.lPitch*height); o+=dd.lPitch*height;
+ memset(o,128,dd.lPitch*height/2);
+ }
+ lpddsOverlay->Unlock(&dd);
+
+ InvalidateRect(hwnd,NULL,TRUE);
+ return 1;
+}
+
+void OverlayVideoOutput::getRects(RECT *drs, RECT *drd) {
+ HWND hwnd=m_parent->getHwnd();
+ if(GetParent(hwnd)) hwnd=GetParent(hwnd);
+
+ RECT rd,rs;
+ GetClientRect(hwnd,&rd);
+ ClientToScreen(hwnd,(LPPOINT)&rd);
+ ClientToScreen(hwnd,((LPPOINT)&rd) + 1);
+
+ m_parent->adjustAspect(rd);
+ rd.left-=m_mon_x;
+ rd.right-=m_mon_x;
+ rd.top-=m_mon_y;
+ rd.bottom-=m_mon_y;
+
+ memset(&rs,0,sizeof(rs));
+ rs.right=width;
+ rs.bottom=height;
+
+ //resize overlay for off-screen
+ RECT rfull;
+ //m_parent->getViewport(&rfull,NULL,1); //FUCKO: assume monitor 0
+ m_parent->getViewport(&rfull,hwnd,1); //FUCKO: okay to use this hwnd? (fixes multimon! -RG)
+ if(rd.right>rfull.right) {
+ int diff=rd.right-rfull.right;
+ float sc=(float)(width)/(float)(rd.right-rd.left);
+ rd.right=rfull.right;
+ rs.right=width-(int)(diff*sc);
+ }
+ if(rd.left<rfull.left) {
+ int diff=rfull.left-rd.left;
+ float sc=(float)(width)/(float)(rd.right-rd.left);
+ rd.left=rfull.left;
+ rs.left=(int)(diff*sc);
+ }
+ if(rd.bottom>rfull.bottom) {
+ int diff=rd.bottom-rfull.bottom;
+ float sc=(float)(height)/(float)(rd.bottom-rd.top);
+ rd.bottom=rfull.bottom;
+ rs.bottom=height-(int)(diff*sc);
+ }
+ if(rd.top<rfull.top) {
+ int diff=rfull.top-rd.top;
+ float sc=(float)(height)/(float)(rd.bottom-rd.top);
+ rd.top=rfull.top;
+ rs.top=(int)(diff*sc);
+ }
+
+ if (capsDrv.dwCaps & DDCAPS_ALIGNSIZESRC && uDestSizeAlign) {
+ rs.left = (int)((rs.left+uDestSizeAlign-1)/uDestSizeAlign)*uDestSizeAlign;
+ rs.right = (int)((rs.right+uDestSizeAlign-1)/uDestSizeAlign)*uDestSizeAlign;
+ }
+ if (capsDrv.dwCaps & DDCAPS_ALIGNSIZEDEST && uDestSizeAlign) {
+ rd.left = (int)((rd.left+uDestSizeAlign-1)/uDestSizeAlign)*uDestSizeAlign;
+ rd.right = (int)((rd.right+uDestSizeAlign-1)/uDestSizeAlign)*uDestSizeAlign;
+ }
+
+ *drd=rd;
+ *drs=rs;
+}
+
+void OverlayVideoOutput::timerCallback() {
+ if(!m_parent) return;
+
+ RECT rd,rs;
+ getRects(&rs,&rd);
+
+ if(memcmp(&m_oldrd,&rd,sizeof(RECT))) {
+ m_oldrd=rd;
+ if(!initing && lpddsOverlay)
+ if(FAILED(lpddsOverlay->UpdateOverlay(&rs, lpddsPrimary, &rd, dwUpdateFlags, &ovfx))) {
+ needchange=1;
+ }
+ }
+}
+
+int OverlayVideoOutput::onPaint(HWND hwnd, HDC hdc) {
+ if(!m_parent) return 0;
+
+ PAINTSTRUCT p;
+ BeginPaint(hwnd,&p);
+
+ RECT r;
+ GetClientRect(hwnd,&r);
+ LOGBRUSH lb={BS_SOLID,RGB(OV_COL_R,OV_COL_G,OV_COL_B),};
+ HBRUSH br=CreateBrushIndirect(&lb);
+ FillRect(p.hdc,&r,br);
+ DeleteObject(br);
+
+ if (curSubtitle)
+ {
+ int m_lastsubxp=curSubtitle->xPos;
+ int m_lastsubyp=curSubtitle->yPos;
+
+ HDC out=p.hdc;
+
+ HGDIOBJ oldobj=SelectObject(out,subFont);
+
+ SetBkMode(out,TRANSPARENT);
+ int centerflags=0;
+ if (m_lastsubxp < 127) centerflags |= DT_LEFT;
+ else if (m_lastsubxp > 127) centerflags |= DT_RIGHT;
+ else centerflags |= DT_CENTER;
+
+ if (m_lastsubyp < 127) centerflags |= DT_TOP;
+ else if (m_lastsubyp > 127) centerflags |= DT_BOTTOM;
+
+ // draw outline
+ SetTextColor(out,RGB(0,0,0));
+ for (int y = -1; y < 2; y++)
+ for (int x = -1; x < 2; x++)
+ {
+ if(!y && !x) continue;
+ RECT r2={subRect.left+x,subRect.top+y,subRect.right+x,subRect.bottom+y};
+ DrawText(out,curSubtitle->text,-1,&r2,centerflags|DT_NOCLIP|DT_NOPREFIX);
+ }
+ // draw text
+ SetTextColor(out,RGB(curSubtitle->colorRed,curSubtitle->colorGreen,curSubtitle->colorBlue));
+ DrawText(out,curSubtitle->text,-1,&subRect,centerflags|DT_NOCLIP|DT_NOPREFIX);
+ SelectObject(out,oldobj);
+ }
+
+ EndPaint(hwnd,&p);
+
+ return 1;
+}
+
+void OverlayVideoOutput::displayFrame(const char *buf, int size, int time) {
+ if(!m_parent) return;
+
+ DDSURFACEDESC dd={sizeof(dd),};
+ if (m_parent->vid_vsync) lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,0);
+ HRESULT result;
+ if ((result=lpddsOverlay->Lock(NULL,&dd,DDLOCK_WAIT,NULL)) != DD_OK) {
+ //CT>FUCKO:reenable me (ctrl+alt+del on win2k)
+ //if(result==DDERR_SURFACELOST) width=-1; //will try to recreate the surface in the next processData() call
+ return;
+ }
+ if(type==NSV_MAKETYPE('Y','V','1','2')) {
+ const YV12_PLANES *planes=(YV12_PLANES *)buf;
+ if (uyvy_output||yuy2_output) { // YV12planar->UYVY or YUY2
+ unsigned char *o=(unsigned char*)dd.lpSurface;
+ const unsigned char *yi=planes->y.baseAddr;
+ const unsigned char *ui=planes->u.baseAddr;
+ const unsigned char *vi=planes->v.baseAddr;
+ int y=height;
+ if (flip) o+=dd.lPitch*(height-1);
+ while (y>0) {
+ int x=width;
+ unsigned char *oo=o;
+
+ if (uyvy_output) while (x>0) {
+ o[0]=*ui++; o[1]=*yi++; o[2]=*vi++; o[3]=*yi++;
+ o+=4; x-=2;
+ }
+ else while (x>0) {
+ o[0]=*yi++; o[1]=*ui++; o[2]=*yi++; o[3]=*vi++;
+ o+=4; x-=2;
+ }
+ ui-=width/2;
+ vi-=width/2;
+ yi+=planes->y.rowBytes-width;
+ x=width;
+ if (flip) o=oo-dd.lPitch;
+ else o+=dd.lPitch-width*2;
+ oo=o;
+ if (uyvy_output) while (x>0) {
+ o[0]=*ui++; o[1]=*yi++; o[2]=*vi++; o[3]=*yi++;
+ o+=4; x-=2;
+ } else while (x>0) {
+ o[0]=*yi++; o[1]=*ui++; o[2]=*yi++; o[3]=*vi++;
+ o+=4; x-=2;
+ }
+ if (flip) o=oo-dd.lPitch;
+ else o+=dd.lPitch-width*2;
+ ui+=planes->u.rowBytes-(width/2);
+ vi+=planes->v.rowBytes-(width/2);
+ yi+=planes->y.rowBytes-width;
+ y-=2;
+ }
+ } else { // woo native YV12 copy
+ int f=!!flip;
+ char *o=(char*)dd.lpSurface+(f*height*dd.lPitch);
+ const char *i=(const char*)planes->y.baseAddr;
+ int d_o=dd.lPitch;
+ if (f) d_o=-d_o;
+ else o-=d_o;
+
+ int h2=height;
+ while (h2--) {
+ o+=d_o; memcpy(o,i,width); i+=planes->y.rowBytes;
+ }
+
+ d_o/=2;
+
+ int w2=width/2;
+ h2=height/2;
+ i=(const char*)planes->v.baseAddr;
+ o=(char*)dd.lpSurface+(height*dd.lPitch*(f+4))/4;
+
+ if (!f) o-=d_o;
+ while (h2--) {
+ o+=d_o; memcpy(o,i,w2); i+=planes->v.rowBytes;
+ }
+ o=(char*)dd.lpSurface+(height*dd.lPitch*(f+5))/4;
+ i=(const char*)planes->u.baseAddr;
+ h2=height/2;
+
+ if (!f) o-=d_o;
+ while (h2--) {
+ o+=d_o; memcpy(o,i,w2);i+=planes->u.rowBytes;
+ }
+ }
+ } else if(type==NSV_MAKETYPE('Y','U','Y','2') || type==NSV_MAKETYPE('U','Y','V','Y')) {
+ const char *a=buf;
+ char *b=(char *)dd.lpSurface;
+ int l=width*2,l2=dd.lPitch;
+ if(flip) {
+ b+=(height-1)*l2;
+ l2=-l2;
+ }
+ int is_uyvy=type==NSV_MAKETYPE('U','Y','V','Y');
+ if (uyvy_output && !is_uyvy || (yuy2_output && is_uyvy)) // convert to uyvy
+ {
+ for(int i=0;i<height;i++) {
+ int x=width/2;
+ while (x-->0) {
+ b[0]=a[1];
+ b[1]=a[0];
+ b[2]=a[3];
+ b[3]=a[2];
+ a+=4;
+ b+=4;
+ }
+ memcpy(b,a,l);
+ b+=l2;
+ a+=l;
+ }
+ } else {
+ //wee straight YUY2 copy
+ for(int i=0;i<height;i++) {
+ memcpy(b,a,l);
+ b+=l2;
+ a+=l;
+ }
+ }
+ }
+
+ lpddsOverlay->Unlock(&dd);
+
+ if (m_parent->osdShowing())
+ {
+ RECT rs, rd;
+ getRects(&rs,&rd);
+
+ HDC hdc;
+#if 1 // set both these 1s to 0s to put it back on ryan's mode
+ HWND h=m_parent->getHwnd();
+ hdc=GetDC(h);
+#else
+ if (lpddsPrimary->GetDC(&hdc)==DD_OK)
+ {
+#endif
+ m_parent->drawOSD(hdc, &rd);
+#if 1
+ ReleaseDC(h,hdc);
+#else
+ lpddsPrimary->ReleaseDC(hdc);
+ }
+#endif
+ }
+}
+
+void OverlayVideoOutput::goFullScreen() {
+/* fullscreen_controls = new GuiObjectWnd;
+ fullscreen_controls->setContent("video.fullscreen_controls");
+ fullscreen_controls->init(m_parent);
+
+ RECT r;
+ Std::getViewport(&r,m_parent->gethWnd(),1);
+
+ RECT nr = r;
+ nr.top = (int)(r.bottom - (r.bottom - r.top) * 0.15);
+ nr.bottom = (int)(r.bottom - (r.bottom - r.top) * 0.05);
+ fullscreen_controls->resizeToRect(&nr);
+ */
+ is_fullscreen=1;
+}
+
+void OverlayVideoOutput::removeFullScreen() {
+/* delete fullscreen_controls;
+ fullscreen_controls = NULL;*/
+ is_fullscreen=0;
+}
+
+int OverlayVideoOutput::showOSD() {
+// if (fullscreen_controls != NULL) fullscreen_controls->setVisible(TRUE);
+
+ // enabling the following code will cause the top & bottom OSD bars
+ // to squish the image (instead of crop it):
+ /*if(lpddsOverlay) {
+ RECT rd,rs;
+ getRects(&rs,&rd);
+
+ HWND hwnd=m_parent->getHwnd();
+ if(GetParent(hwnd)) hwnd=GetParent(hwnd);
+
+ RECT temp;
+ GetClientRect(hwnd,&temp);
+ int bottom_margin = ((temp.bottom-temp.top) - (rd.bottom-rd.top)) / 2;
+ int pixels_to_clip = max(0, m_parent->getOSDbarHeight() - bottom_margin);
+ rd.bottom -= pixels_to_clip;
+
+ lpddsOverlay->UpdateOverlay(&rs, lpddsPrimary, &rd, dwUpdateFlags, &ovfx);
+ }*/
+
+
+ return 1;
+}
+
+void OverlayVideoOutput::hideOSD() {
+ //if (fullscreen_controls != NULL) fullscreen_controls->setVisible(FALSE);
+
+ // 1) repaint the OSD area with the overlay color here
+ HWND hwnd = m_parent->getHwnd();
+ if(GetParent(hwnd)) hwnd=GetParent(hwnd);
+
+ HDC hdc = GetDC(hwnd);
+ if (hdc) {
+ RECT r;
+ GetClientRect(hwnd,&r);
+ LOGBRUSH lb={BS_SOLID,RGB(OV_COL_R,OV_COL_G,OV_COL_B),};
+ HBRUSH br=CreateBrushIndirect(&lb);
+ FillRect(hdc,&r,br);
+ DeleteObject(br);
+
+ ReleaseDC(hwnd, hdc);
+ }
+
+ // 2) readjust the overlay destination rectangle
+ /*if(lpddsOverlay) {
+ RECT rd,rs;
+ getRects(&rs,&rd);
+ lpddsOverlay->UpdateOverlay(&rs, lpddsPrimary, &rd, dwUpdateFlags, &ovfx);
+ }*/
+
+}
+
+void OverlayVideoOutput::drawSubtitle(SubsItem *item) {
+ curSubtitle=item;
+
+ HWND hwnd=m_parent->getHwnd();
+
+ RECT oldrect=subRect;
+ GetClientRect(hwnd,&subRect);
+
+ if(item) {
+
+ RECT oldwinRect=winRect;
+ GetClientRect(hwnd,&winRect);
+ if(!subFont || ((winRect.bottom-winRect.top)!=(oldwinRect.bottom-oldwinRect.top)) || m_fontsize!=item->fontSize) {
+ if(subFont) DeleteObject(subFont);
+ m_fontsize=item->fontSize;
+ subFont=CreateFont(14+item->fontSize+18*(winRect.bottom-winRect.top)/768,0,0,0,FW_SEMIBOLD,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_OUTLINE_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,DEFAULT_PITCH|FF_DONTCARE,"Arial");
+ }
+
+ HDC out=GetDC(hwnd);
+ SelectObject(out,subFont);
+ SIZE s;
+ GetTextExtentPoint32(out,item->text,strlen(item->text),&s);
+ {
+ // calcul for multiline text
+ const char *p=item->text;
+ int n=0;
+ while(*p!=0) if(*p++=='\n') n++;
+ if(n) s.cy*=(n+1);
+ }
+
+ if (item->xPos > 127) // towards the right
+ {
+ subRect.right -= ((subRect.right-subRect.left) * (255-item->xPos)) / 256;
+ }
+ else if (item->xPos < 127)
+ {
+ subRect.left += ((subRect.right-subRect.left) * item->xPos) / 256;
+ }
+
+ subRect.top += ((subRect.bottom-s.cy-subRect.top) * item->yPos)/255;
+
+ subRect.bottom=subRect.top + s.cy;
+
+ ReleaseDC(hwnd,out);
+ }
+
+ //just redraw the correct portion
+ InvalidateRect(hwnd,&oldrect,TRUE);
+ InvalidateRect(hwnd,&subRect,TRUE);
+}
+
+void OverlayVideoOutput::resetSubtitle()
+{
+ curSubtitle=NULL;
+ subRect.top=65536;
+} \ No newline at end of file