vid_overlay.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654
  1. #include "video.h"
  2. #include <multimon.h>
  3. #include "subtitles.h"
  4. #define INIT_DIRECTDRAW_STRUCT(x) (ZeroMemory(&x, sizeof(x)), x.dwSize=sizeof(x))
  5. #define OV_COL_R 16
  6. #define OV_COL_G 0
  7. #define OV_COL_B 16
  8. OverlayVideoOutput::OverlayVideoOutput() {
  9. lpDD=NULL;
  10. lpddsOverlay=NULL;
  11. lpddsPrimary=NULL;
  12. is_fullscreen=0;
  13. yuy2_output=uyvy_output=0;
  14. m_parent=NULL;
  15. initing=false;
  16. needchange=0;
  17. memset(&m_oldrd,0,sizeof(m_oldrd));
  18. memset(&winRect,0,sizeof(winRect));
  19. subFont=NULL;
  20. m_fontsize=0;
  21. resetSubtitle();
  22. }
  23. OverlayVideoOutput::~OverlayVideoOutput() {
  24. if(is_fullscreen) removeFullScreen();
  25. LPDIRECTDRAWSURFACE o=lpddsOverlay;
  26. lpddsOverlay=NULL;
  27. if(o) o->Release();
  28. if(lpddsPrimary) lpddsPrimary->Release();
  29. if (lpDD) lpDD->Release(); // BU added NULL check in response to talkback
  30. if(subFont) DeleteObject(subFont);
  31. }
  32. static DWORD DD_ColorMatch(LPDIRECTDRAWSURFACE pdds, COLORREF rgb)
  33. {
  34. COLORREF rgbT;
  35. HDC hdc;
  36. DWORD dw = CLR_INVALID;
  37. DDSURFACEDESC ddsd;
  38. HRESULT hres;
  39. //
  40. // use GDI SetPixel to color match for us
  41. //
  42. if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
  43. {
  44. rgbT = GetPixel(hdc, 0, 0); // save current pixel value
  45. SetPixel(hdc, 0, 0, rgb); // set our value
  46. pdds->ReleaseDC(hdc);
  47. }
  48. //
  49. // now lock the surface so we can read back the converted color
  50. //
  51. ddsd.dwSize = sizeof(ddsd);
  52. while ((hres = pdds->Lock(NULL, &ddsd, 0, NULL)) ==
  53. DDERR_WASSTILLDRAWING)
  54. ;
  55. if (hres == DD_OK)
  56. {
  57. dw = *(DWORD *)ddsd.lpSurface; // get DWORD
  58. if(ddsd.ddpfPixelFormat.dwRGBBitCount<32)
  59. dw &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount) - 1; // mask it to bpp
  60. pdds->Unlock(NULL);
  61. }
  62. //
  63. // now put the color that was there back.
  64. //
  65. if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
  66. {
  67. SetPixel(hdc, 0, 0, rgbT);
  68. pdds->ReleaseDC(hdc);
  69. }
  70. return dw;
  71. }
  72. int OverlayVideoOutput::create(VideoOutput *parent, int w, int h, unsigned int ptype, int flipit, double aspectratio) {
  73. type=ptype;
  74. width=w;
  75. height=h;
  76. flip=flipit;
  77. m_parent=parent;
  78. initing=true;
  79. HWND hwnd=parent->getHwnd();
  80. if (lpDD) lpDD->Release();
  81. lpDD=NULL;
  82. update_monitor_coords(parent);
  83. if(!m_found_devguid) DirectDrawCreate(NULL,&lpDD,NULL);
  84. else DirectDrawCreate(&m_devguid,&lpDD,NULL);
  85. if(!lpDD) {
  86. initing=false;
  87. return 0;
  88. }
  89. lpDD->SetCooperativeLevel(hwnd,DDSCL_NOWINDOWCHANGES|DDSCL_NORMAL);
  90. DDSURFACEDESC ddsd;
  91. INIT_DIRECTDRAW_STRUCT(ddsd);
  92. ddsd.dwFlags = DDSD_CAPS;
  93. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  94. HRESULT ddrval = lpDD->CreateSurface(&ddsd, &lpddsPrimary, NULL );
  95. // init overlay
  96. DDSURFACEDESC ddsdOverlay;
  97. INIT_DIRECTDRAW_STRUCT(ddsdOverlay);
  98. ddsdOverlay.ddsCaps.dwCaps=DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY;
  99. ddsdOverlay.dwFlags= DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_PITCH;
  100. ddsdOverlay.dwWidth=w;
  101. ddsdOverlay.dwHeight=h;
  102. ddsdOverlay.lPitch=w*4;
  103. ddsdOverlay.dwBackBufferCount=0;
  104. DDPIXELFORMAT pf[]=
  105. {
  106. {sizeof(DDPIXELFORMAT),DDPF_FOURCC,MAKEFOURCC('Y','U','Y','2'),0,0,0,0,0},
  107. {sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('U','Y','V','Y'),0,0,0,0,0}, // UYVY
  108. {sizeof(DDPIXELFORMAT),DDPF_FOURCC,MAKEFOURCC('Y','V','1','2'),0,0,0,0,0},
  109. };
  110. int tab[5];
  111. if(type==NSV_MAKETYPE('Y','U','Y','2')) {
  112. tab[0]=0; // default is YUY2
  113. tab[1]=1;
  114. tab[2]=-1;
  115. } else if(type==NSV_MAKETYPE('U','Y','V','Y')) {
  116. tab[0]=1; // make UYVY default
  117. tab[1]=0;
  118. tab[2]=-1;
  119. } else if(type==NSV_MAKETYPE('Y','V','1','2')) {
  120. /*tab[0]=2;
  121. tab[1]=0;
  122. tab[2]=1;
  123. tab[3]=-1;*/
  124. //CT> Make YUY2 default too, cause YV12 is borked on some ATI cards/drivers :(
  125. tab[0]=0;
  126. tab[1]=1;
  127. tab[2]=-1;
  128. } else {
  129. tab[0]=-1; // default is RGB
  130. }
  131. int x=4096;
  132. HRESULT v=-1;
  133. for (x = 0; x < sizeof(tab)/sizeof(tab[0]) && tab[x]>=0; x ++) {
  134. ddsdOverlay.ddpfPixelFormat=pf[tab[x]];
  135. v=lpDD->CreateSurface(&ddsdOverlay, &lpddsOverlay, NULL);
  136. if (!FAILED(v)) break;
  137. }
  138. if(FAILED(v)||x>=sizeof(tab)/sizeof(tab[0])||tab[x]<0) {
  139. initing=false;
  140. return 0;
  141. }
  142. yuy2_output = (tab[x] == 0);
  143. uyvy_output = (tab[x] == 1);
  144. INIT_DIRECTDRAW_STRUCT(capsDrv);
  145. ddrval = lpDD->GetCaps(&capsDrv, NULL);
  146. uDestSizeAlign = capsDrv.dwAlignSizeDest;
  147. uSrcSizeAlign = capsDrv.dwAlignSizeSrc;
  148. dwUpdateFlags = DDOVER_SHOW | DDOVER_KEYDESTOVERRIDE;
  149. DEVMODE d;
  150. d.dmSize=sizeof(d);
  151. d.dmDriverExtra=0;
  152. EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &d);
  153. int rv=OV_COL_R, gv=OV_COL_G, bv=OV_COL_B;
  154. INIT_DIRECTDRAW_STRUCT(ovfx);
  155. ovfx.dwDDFX=0;
  156. switch(d.dmBitsPerPel) {
  157. case 16:
  158. ovfx.dckDestColorkey.dwColorSpaceLowValue=((rv>>3) << 11) | ((gv>>2) << 5) | (bv>>3);
  159. break;
  160. case 15:
  161. ovfx.dckDestColorkey.dwColorSpaceLowValue=((rv>>3) << 10) | ((gv>>3) << 5) | (bv>>3);
  162. break;
  163. case 24: case 32:
  164. ovfx.dckDestColorkey.dwColorSpaceLowValue=(rv << 16) | (gv << 8) | bv;
  165. break;
  166. }
  167. //try to get the correct bit depth thru directdraw (for fucked up 16 bits displays for ie.)
  168. {
  169. DDSURFACEDESC DDsd={sizeof(DDsd),};
  170. lpddsPrimary->GetSurfaceDesc(&ddsd);
  171. DDsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT; //create the surface at screen depth
  172. DDsd.dwWidth=8;
  173. DDsd.dwHeight=8;
  174. DDsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
  175. LPDIRECTDRAWSURFACE tempsurf;
  176. if(lpDD->CreateSurface(&DDsd, &tempsurf, NULL)==DD_OK)
  177. {
  178. int res=DD_ColorMatch(tempsurf, RGB(rv,gv,bv));
  179. if(res!=CLR_INVALID) ovfx.dckDestColorkey.dwColorSpaceLowValue=res;
  180. tempsurf->Release();
  181. }
  182. }
  183. ovfx.dckDestColorkey.dwColorSpaceHighValue=ovfx.dckDestColorkey.dwColorSpaceLowValue;
  184. getRects(&rs,&rd);
  185. if(FAILED(lpddsOverlay->UpdateOverlay(&rs, lpddsPrimary, &rd, dwUpdateFlags, &ovfx))) {
  186. initing=false;
  187. return 0;
  188. }
  189. initing=false;
  190. DDSURFACEDESC dd={sizeof(dd),};
  191. if (lpddsOverlay->Lock(NULL,&dd,DDLOCK_WAIT,NULL) != DD_OK) return 0;
  192. unsigned char *o=(unsigned char*)dd.lpSurface;
  193. if (uyvy_output||yuy2_output)
  194. {
  195. int x=dd.lPitch*height/2;
  196. while (x--)
  197. {
  198. if (uyvy_output)
  199. {
  200. *o++=128;
  201. *o++=0;
  202. }
  203. else
  204. {
  205. *o++=0;
  206. *o++=-128;
  207. }
  208. }
  209. }
  210. else
  211. {
  212. memset(o,0,dd.lPitch*height); o+=dd.lPitch*height;
  213. memset(o,128,dd.lPitch*height/2);
  214. }
  215. lpddsOverlay->Unlock(&dd);
  216. InvalidateRect(hwnd,NULL,TRUE);
  217. return 1;
  218. }
  219. void OverlayVideoOutput::getRects(RECT *drs, RECT *drd) {
  220. HWND hwnd=m_parent->getHwnd();
  221. if(GetParent(hwnd)) hwnd=GetParent(hwnd);
  222. RECT rd,rs;
  223. GetClientRect(hwnd,&rd);
  224. ClientToScreen(hwnd,(LPPOINT)&rd);
  225. ClientToScreen(hwnd,((LPPOINT)&rd) + 1);
  226. m_parent->adjustAspect(rd);
  227. rd.left-=m_mon_x;
  228. rd.right-=m_mon_x;
  229. rd.top-=m_mon_y;
  230. rd.bottom-=m_mon_y;
  231. memset(&rs,0,sizeof(rs));
  232. rs.right=width;
  233. rs.bottom=height;
  234. //resize overlay for off-screen
  235. RECT rfull;
  236. //m_parent->getViewport(&rfull,NULL,1); //FUCKO: assume monitor 0
  237. m_parent->getViewport(&rfull,hwnd,1); //FUCKO: okay to use this hwnd? (fixes multimon! -RG)
  238. if(rd.right>rfull.right) {
  239. int diff=rd.right-rfull.right;
  240. float sc=(float)(width)/(float)(rd.right-rd.left);
  241. rd.right=rfull.right;
  242. rs.right=width-(int)(diff*sc);
  243. }
  244. if(rd.left<rfull.left) {
  245. int diff=rfull.left-rd.left;
  246. float sc=(float)(width)/(float)(rd.right-rd.left);
  247. rd.left=rfull.left;
  248. rs.left=(int)(diff*sc);
  249. }
  250. if(rd.bottom>rfull.bottom) {
  251. int diff=rd.bottom-rfull.bottom;
  252. float sc=(float)(height)/(float)(rd.bottom-rd.top);
  253. rd.bottom=rfull.bottom;
  254. rs.bottom=height-(int)(diff*sc);
  255. }
  256. if(rd.top<rfull.top) {
  257. int diff=rfull.top-rd.top;
  258. float sc=(float)(height)/(float)(rd.bottom-rd.top);
  259. rd.top=rfull.top;
  260. rs.top=(int)(diff*sc);
  261. }
  262. if (capsDrv.dwCaps & DDCAPS_ALIGNSIZESRC && uDestSizeAlign) {
  263. rs.left = (int)((rs.left+uDestSizeAlign-1)/uDestSizeAlign)*uDestSizeAlign;
  264. rs.right = (int)((rs.right+uDestSizeAlign-1)/uDestSizeAlign)*uDestSizeAlign;
  265. }
  266. if (capsDrv.dwCaps & DDCAPS_ALIGNSIZEDEST && uDestSizeAlign) {
  267. rd.left = (int)((rd.left+uDestSizeAlign-1)/uDestSizeAlign)*uDestSizeAlign;
  268. rd.right = (int)((rd.right+uDestSizeAlign-1)/uDestSizeAlign)*uDestSizeAlign;
  269. }
  270. *drd=rd;
  271. *drs=rs;
  272. }
  273. void OverlayVideoOutput::timerCallback() {
  274. if(!m_parent) return;
  275. RECT rd,rs;
  276. getRects(&rs,&rd);
  277. if(memcmp(&m_oldrd,&rd,sizeof(RECT))) {
  278. m_oldrd=rd;
  279. if(!initing && lpddsOverlay)
  280. if(FAILED(lpddsOverlay->UpdateOverlay(&rs, lpddsPrimary, &rd, dwUpdateFlags, &ovfx))) {
  281. needchange=1;
  282. }
  283. }
  284. }
  285. int OverlayVideoOutput::onPaint(HWND hwnd, HDC hdc) {
  286. if(!m_parent) return 0;
  287. PAINTSTRUCT p;
  288. BeginPaint(hwnd,&p);
  289. RECT r;
  290. GetClientRect(hwnd,&r);
  291. LOGBRUSH lb={BS_SOLID,RGB(OV_COL_R,OV_COL_G,OV_COL_B),};
  292. HBRUSH br=CreateBrushIndirect(&lb);
  293. FillRect(p.hdc,&r,br);
  294. DeleteObject(br);
  295. if (curSubtitle)
  296. {
  297. int m_lastsubxp=curSubtitle->xPos;
  298. int m_lastsubyp=curSubtitle->yPos;
  299. HDC out=p.hdc;
  300. HGDIOBJ oldobj=SelectObject(out,subFont);
  301. SetBkMode(out,TRANSPARENT);
  302. int centerflags=0;
  303. if (m_lastsubxp < 127) centerflags |= DT_LEFT;
  304. else if (m_lastsubxp > 127) centerflags |= DT_RIGHT;
  305. else centerflags |= DT_CENTER;
  306. if (m_lastsubyp < 127) centerflags |= DT_TOP;
  307. else if (m_lastsubyp > 127) centerflags |= DT_BOTTOM;
  308. // draw outline
  309. SetTextColor(out,RGB(0,0,0));
  310. for (int y = -1; y < 2; y++)
  311. for (int x = -1; x < 2; x++)
  312. {
  313. if(!y && !x) continue;
  314. RECT r2={subRect.left+x,subRect.top+y,subRect.right+x,subRect.bottom+y};
  315. DrawText(out,curSubtitle->text,-1,&r2,centerflags|DT_NOCLIP|DT_NOPREFIX);
  316. }
  317. // draw text
  318. SetTextColor(out,RGB(curSubtitle->colorRed,curSubtitle->colorGreen,curSubtitle->colorBlue));
  319. DrawText(out,curSubtitle->text,-1,&subRect,centerflags|DT_NOCLIP|DT_NOPREFIX);
  320. SelectObject(out,oldobj);
  321. }
  322. EndPaint(hwnd,&p);
  323. return 1;
  324. }
  325. void OverlayVideoOutput::displayFrame(const char *buf, int size, int time) {
  326. if(!m_parent) return;
  327. DDSURFACEDESC dd={sizeof(dd),};
  328. if (m_parent->vid_vsync) lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,0);
  329. HRESULT result;
  330. if ((result=lpddsOverlay->Lock(NULL,&dd,DDLOCK_WAIT,NULL)) != DD_OK) {
  331. //CT>FUCKO:reenable me (ctrl+alt+del on win2k)
  332. //if(result==DDERR_SURFACELOST) width=-1; //will try to recreate the surface in the next processData() call
  333. return;
  334. }
  335. if(type==NSV_MAKETYPE('Y','V','1','2')) {
  336. const YV12_PLANES *planes=(YV12_PLANES *)buf;
  337. if (uyvy_output||yuy2_output) { // YV12planar->UYVY or YUY2
  338. unsigned char *o=(unsigned char*)dd.lpSurface;
  339. const unsigned char *yi=planes->y.baseAddr;
  340. const unsigned char *ui=planes->u.baseAddr;
  341. const unsigned char *vi=planes->v.baseAddr;
  342. int y=height;
  343. if (flip) o+=dd.lPitch*(height-1);
  344. while (y>0) {
  345. int x=width;
  346. unsigned char *oo=o;
  347. if (uyvy_output) while (x>0) {
  348. o[0]=*ui++; o[1]=*yi++; o[2]=*vi++; o[3]=*yi++;
  349. o+=4; x-=2;
  350. }
  351. else while (x>0) {
  352. o[0]=*yi++; o[1]=*ui++; o[2]=*yi++; o[3]=*vi++;
  353. o+=4; x-=2;
  354. }
  355. ui-=width/2;
  356. vi-=width/2;
  357. yi+=planes->y.rowBytes-width;
  358. x=width;
  359. if (flip) o=oo-dd.lPitch;
  360. else o+=dd.lPitch-width*2;
  361. oo=o;
  362. if (uyvy_output) while (x>0) {
  363. o[0]=*ui++; o[1]=*yi++; o[2]=*vi++; o[3]=*yi++;
  364. o+=4; x-=2;
  365. } else while (x>0) {
  366. o[0]=*yi++; o[1]=*ui++; o[2]=*yi++; o[3]=*vi++;
  367. o+=4; x-=2;
  368. }
  369. if (flip) o=oo-dd.lPitch;
  370. else o+=dd.lPitch-width*2;
  371. ui+=planes->u.rowBytes-(width/2);
  372. vi+=planes->v.rowBytes-(width/2);
  373. yi+=planes->y.rowBytes-width;
  374. y-=2;
  375. }
  376. } else { // woo native YV12 copy
  377. int f=!!flip;
  378. char *o=(char*)dd.lpSurface+(f*height*dd.lPitch);
  379. const char *i=(const char*)planes->y.baseAddr;
  380. int d_o=dd.lPitch;
  381. if (f) d_o=-d_o;
  382. else o-=d_o;
  383. int h2=height;
  384. while (h2--) {
  385. o+=d_o; memcpy(o,i,width); i+=planes->y.rowBytes;
  386. }
  387. d_o/=2;
  388. int w2=width/2;
  389. h2=height/2;
  390. i=(const char*)planes->v.baseAddr;
  391. o=(char*)dd.lpSurface+(height*dd.lPitch*(f+4))/4;
  392. if (!f) o-=d_o;
  393. while (h2--) {
  394. o+=d_o; memcpy(o,i,w2); i+=planes->v.rowBytes;
  395. }
  396. o=(char*)dd.lpSurface+(height*dd.lPitch*(f+5))/4;
  397. i=(const char*)planes->u.baseAddr;
  398. h2=height/2;
  399. if (!f) o-=d_o;
  400. while (h2--) {
  401. o+=d_o; memcpy(o,i,w2);i+=planes->u.rowBytes;
  402. }
  403. }
  404. } else if(type==NSV_MAKETYPE('Y','U','Y','2') || type==NSV_MAKETYPE('U','Y','V','Y')) {
  405. const char *a=buf;
  406. char *b=(char *)dd.lpSurface;
  407. int l=width*2,l2=dd.lPitch;
  408. if(flip) {
  409. b+=(height-1)*l2;
  410. l2=-l2;
  411. }
  412. int is_uyvy=type==NSV_MAKETYPE('U','Y','V','Y');
  413. if (uyvy_output && !is_uyvy || (yuy2_output && is_uyvy)) // convert to uyvy
  414. {
  415. for(int i=0;i<height;i++) {
  416. int x=width/2;
  417. while (x-->0) {
  418. b[0]=a[1];
  419. b[1]=a[0];
  420. b[2]=a[3];
  421. b[3]=a[2];
  422. a+=4;
  423. b+=4;
  424. }
  425. memcpy(b,a,l);
  426. b+=l2;
  427. a+=l;
  428. }
  429. } else {
  430. //wee straight YUY2 copy
  431. for(int i=0;i<height;i++) {
  432. memcpy(b,a,l);
  433. b+=l2;
  434. a+=l;
  435. }
  436. }
  437. }
  438. lpddsOverlay->Unlock(&dd);
  439. if (m_parent->osdShowing())
  440. {
  441. RECT rs, rd;
  442. getRects(&rs,&rd);
  443. HDC hdc;
  444. #if 1 // set both these 1s to 0s to put it back on ryan's mode
  445. HWND h=m_parent->getHwnd();
  446. hdc=GetDC(h);
  447. #else
  448. if (lpddsPrimary->GetDC(&hdc)==DD_OK)
  449. {
  450. #endif
  451. m_parent->drawOSD(hdc, &rd);
  452. #if 1
  453. ReleaseDC(h,hdc);
  454. #else
  455. lpddsPrimary->ReleaseDC(hdc);
  456. }
  457. #endif
  458. }
  459. }
  460. void OverlayVideoOutput::goFullScreen() {
  461. /* fullscreen_controls = new GuiObjectWnd;
  462. fullscreen_controls->setContent("video.fullscreen_controls");
  463. fullscreen_controls->init(m_parent);
  464. RECT r;
  465. Std::getViewport(&r,m_parent->gethWnd(),1);
  466. RECT nr = r;
  467. nr.top = (int)(r.bottom - (r.bottom - r.top) * 0.15);
  468. nr.bottom = (int)(r.bottom - (r.bottom - r.top) * 0.05);
  469. fullscreen_controls->resizeToRect(&nr);
  470. */
  471. is_fullscreen=1;
  472. }
  473. void OverlayVideoOutput::removeFullScreen() {
  474. /* delete fullscreen_controls;
  475. fullscreen_controls = NULL;*/
  476. is_fullscreen=0;
  477. }
  478. int OverlayVideoOutput::showOSD() {
  479. // if (fullscreen_controls != NULL) fullscreen_controls->setVisible(TRUE);
  480. // enabling the following code will cause the top & bottom OSD bars
  481. // to squish the image (instead of crop it):
  482. /*if(lpddsOverlay) {
  483. RECT rd,rs;
  484. getRects(&rs,&rd);
  485. HWND hwnd=m_parent->getHwnd();
  486. if(GetParent(hwnd)) hwnd=GetParent(hwnd);
  487. RECT temp;
  488. GetClientRect(hwnd,&temp);
  489. int bottom_margin = ((temp.bottom-temp.top) - (rd.bottom-rd.top)) / 2;
  490. int pixels_to_clip = max(0, m_parent->getOSDbarHeight() - bottom_margin);
  491. rd.bottom -= pixels_to_clip;
  492. lpddsOverlay->UpdateOverlay(&rs, lpddsPrimary, &rd, dwUpdateFlags, &ovfx);
  493. }*/
  494. return 1;
  495. }
  496. void OverlayVideoOutput::hideOSD() {
  497. //if (fullscreen_controls != NULL) fullscreen_controls->setVisible(FALSE);
  498. // 1) repaint the OSD area with the overlay color here
  499. HWND hwnd = m_parent->getHwnd();
  500. if(GetParent(hwnd)) hwnd=GetParent(hwnd);
  501. HDC hdc = GetDC(hwnd);
  502. if (hdc) {
  503. RECT r;
  504. GetClientRect(hwnd,&r);
  505. LOGBRUSH lb={BS_SOLID,RGB(OV_COL_R,OV_COL_G,OV_COL_B),};
  506. HBRUSH br=CreateBrushIndirect(&lb);
  507. FillRect(hdc,&r,br);
  508. DeleteObject(br);
  509. ReleaseDC(hwnd, hdc);
  510. }
  511. // 2) readjust the overlay destination rectangle
  512. /*if(lpddsOverlay) {
  513. RECT rd,rs;
  514. getRects(&rs,&rd);
  515. lpddsOverlay->UpdateOverlay(&rs, lpddsPrimary, &rd, dwUpdateFlags, &ovfx);
  516. }*/
  517. }
  518. void OverlayVideoOutput::drawSubtitle(SubsItem *item) {
  519. curSubtitle=item;
  520. HWND hwnd=m_parent->getHwnd();
  521. RECT oldrect=subRect;
  522. GetClientRect(hwnd,&subRect);
  523. if(item) {
  524. RECT oldwinRect=winRect;
  525. GetClientRect(hwnd,&winRect);
  526. if(!subFont || ((winRect.bottom-winRect.top)!=(oldwinRect.bottom-oldwinRect.top)) || m_fontsize!=item->fontSize) {
  527. if(subFont) DeleteObject(subFont);
  528. m_fontsize=item->fontSize;
  529. 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");
  530. }
  531. HDC out=GetDC(hwnd);
  532. SelectObject(out,subFont);
  533. SIZE s;
  534. GetTextExtentPoint32(out,item->text,strlen(item->text),&s);
  535. {
  536. // calcul for multiline text
  537. const char *p=item->text;
  538. int n=0;
  539. while(*p!=0) if(*p++=='\n') n++;
  540. if(n) s.cy*=(n+1);
  541. }
  542. if (item->xPos > 127) // towards the right
  543. {
  544. subRect.right -= ((subRect.right-subRect.left) * (255-item->xPos)) / 256;
  545. }
  546. else if (item->xPos < 127)
  547. {
  548. subRect.left += ((subRect.right-subRect.left) * item->xPos) / 256;
  549. }
  550. subRect.top += ((subRect.bottom-s.cy-subRect.top) * item->yPos)/255;
  551. subRect.bottom=subRect.top + s.cy;
  552. ReleaseDC(hwnd,out);
  553. }
  554. //just redraw the correct portion
  555. InvalidateRect(hwnd,&oldrect,TRUE);
  556. InvalidateRect(hwnd,&subRect,TRUE);
  557. }
  558. void OverlayVideoOutput::resetSubtitle()
  559. {
  560. curSubtitle=NULL;
  561. subRect.top=65536;
  562. }