diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/nsv/nsvplay/vid_overlay.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/nsv/nsvplay/vid_overlay.cpp')
-rw-r--r-- | Src/nsv/nsvplay/vid_overlay.cpp | 654 |
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 |